static UsdPrim
_GetMaterialParent(const UsdStageRefPtr& stage,
               const PxrUsdMayaShadingModeExportContext::AssignmentVector& assignments)
{
    SdfPath commonAncestor;
    TF_FOR_ALL(iter, assignments) {
        const SdfPath& assn = iter->first;
        if (stage->GetPrimAtPath(assn)) {
            if (commonAncestor.IsEmpty()) {
                commonAncestor = assn;
            }
            else {
                commonAncestor = commonAncestor.GetCommonPrefix(assn);
            }
        }
    }

    if (commonAncestor.IsEmpty()) {
        return UsdPrim();
    }

    if (commonAncestor == SdfPath::AbsoluteRootPath()) {
        return stage->GetPseudoRoot();
    }

    SdfPath shaderExportLocation = commonAncestor;
    while (!shaderExportLocation.IsRootPrimPath()) {
        shaderExportLocation = shaderExportLocation.GetParentPath();
    }
    shaderExportLocation = shaderExportLocation.AppendChild(TfToken("Looks"));

    return UsdGeomScope::Define(stage, shaderExportLocation).GetPrim();
}
UsdPrim
PxrUsdMayaShadingModeExportContext::MakeStandardMaterialPrim(
        const AssignmentVector& assignmentsToBind,
        const std::string& name) const
{
    UsdPrim ret;

    std::string materialName = name;
    if (materialName.empty()) {
        MStatus status;
        MFnDependencyNode seDepNode(_shadingEngine, &status);
        if (!status) {
            return ret;
        }
        MString seName = seDepNode.name();
        materialName = MNamespace::stripNamespaceFromName(seName).asChar();
    }

    materialName = PxrUsdMayaUtil::SanitizeName(materialName);
    UsdStageRefPtr stage = GetUsdStage();
    if (UsdPrim materialParent = _GetMaterialParent(stage, assignmentsToBind)) {
        SdfPath materialPath = materialParent.GetPath().AppendChild(
                TfToken(materialName));
        UsdShadeMaterial material = UsdShadeMaterial::Define(
                GetUsdStage(), materialPath);

        UsdPrim materialPrim = material.GetPrim();

        // could use this to determine where we want to export.
        TF_FOR_ALL(iter, assignmentsToBind) {
            const SdfPath &boundPrimPath = iter->first;
            const VtIntArray &faceIndices = iter->second;

            UsdPrim boundPrim = stage->OverridePrim(boundPrimPath);
            if (faceIndices.empty()) {
                material.Bind(boundPrim);
            } else if (TfGetEnvSetting(PIXMAYA_EXPORT_OLD_STYLE_FACESETS)) {
                UsdGeomFaceSetAPI faceSet = material.CreateMaterialFaceSet(
                        boundPrim);
                faceSet.AppendFaceGroup(faceIndices, materialPath);
            } else {
                // It might be worth adding a utility method for the following 
                // block of code in core.
                UsdGeomSubset faceSubset = 
                    UsdShadeMaterial::CreateMaterialBindFaceSubset(
                        UsdGeomImageable(boundPrim), 
                        /* subsetName */ TfToken(materialName),
                        faceIndices);
                material.Bind(faceSubset.GetPrim());

                UsdShadeMaterial::SetMaterialBindFaceSubsetsFamilyType(
                    UsdGeomImageable(boundPrim), 
                    UsdGeomSubset::FamilyType::Partition);
            }
        }

        return materialPrim;
    }
Example #3
0
File: cache.cpp Project: MWDD/USD
/* static */
void
UsdKatanaCache::_SetMutedLayers(
    const UsdStageRefPtr &stage, const std::string &layerRegex) 
{
    // Trace this function to track its performance
    TRACE_FUNCTION();

    // Unmute layers that are currently muted, but not requested to be muted
    SdfLayerHandleVector stageLayers = stage->GetUsedLayers();

    bool regexIsEmpty = layerRegex == "" || layerRegex == "^$";
    
    // use a better regex library?
    regex_t regex;
    regcomp(&regex, layerRegex.c_str(), REG_EXTENDED);
    regmatch_t* rmatch = 0;

    TF_FOR_ALL(stageLayer, stageLayers)
    {
        SdfLayerHandle layer = *stageLayer;
        if (!layer) {
            continue;
        }
        std::string layerPath = layer->GetRepositoryPath();
        const std::string layerIdentifier = layer->GetIdentifier();

        bool match = false;
        
        if (!regexIsEmpty)
        {
            if (layer && !regexec(
                &regex, 
                layerIdentifier.c_str(), 
                0, rmatch, 0))
            {
                match = true;
            }
        }
        
        if (!match && stage->IsLayerMuted(layerIdentifier)) {
            TF_DEBUG(USDKATANA_CACHE_RENDERER).Msg("{USD RENDER CACHE} "
                                "Unmuting Layer: '%s'\n",
                                layerIdentifier.c_str());
            stage->UnmuteLayer(layerIdentifier);
        }

        if (match && !stage->IsLayerMuted(layerIdentifier)) {
            TF_DEBUG(USDKATANA_CACHE_RENDERER).Msg("{USD RENDER CACHE} "
                    "Muting Layer: '%s'\n",
                    layerIdentifier.c_str());
            stage->MuteLayer(layerIdentifier);
        }
    }
Example #4
0
void
GusdUSD_StageProxy::_StageData::Update(const UsdStageRefPtr& stage)
{
    UT_ASSERT(stage);

    double preroll = 0.0;
    double postroll = 0.0;

    if (const auto& pseudoRoot = stage->GetPseudoRoot()) {

        const TfToken prerollName("shot:preroll");
        const TfToken postrollName("shot:postroll");

        static const Usd_PrimFlagsPredicate pred(UsdPrimIsActive &&
                                                 UsdPrimIsDefined &&
                                                 !UsdPrimIsAbstract);
        for(const auto& prim : pseudoRoot.GetFilteredChildren(pred)) {

            VtValue val;
            double dval;

            if (auto prerollAttr = prim.GetAttribute(prerollName)) {
                prerollAttr.Get(&val);

                dval = 0.0;
                if (val.IsHolding<int>()) {
                    dval = double(val.UncheckedGet<int>());
                } else if (val.IsHolding<double>()) {
                    dval = val.UncheckedGet<double>();
                }
                preroll = std::max(preroll, dval);
            }

            if (auto postrollAttr = prim.GetAttribute(postrollName)) {
                postrollAttr.Get(&val);

                dval = 0.0;
                if (val.IsHolding<int>()) {
                    dval = double(val.UncheckedGet<int>());
                } else if (val.IsHolding<double>()) {
                    dval = val.UncheckedGet<double>();
                }
                postroll = std::max(postroll, dval);
            }
        }
    }

    const auto& lyr = stage->GetRootLayer();
    
    startTimeCode = lyr->GetStartTimeCode() - preroll;
    endTimeCode = lyr->GetEndTimeCode() + postroll;
}
NdrNodeDiscoveryResultVec
UsdHydraDiscoveryPlugin::DiscoverNodes(const Context &context)
{
    NdrNodeDiscoveryResultVec result;

    static std::string shaderDefsFile = _GetShaderResourcePath(
            "shaderDefs.usda");
    if (shaderDefsFile.empty())
        return result;

    auto resolverContext = ArGetResolver().CreateDefaultContextForAsset(
            shaderDefsFile);

    const UsdStageRefPtr stage = UsdStage::Open(shaderDefsFile, 
            resolverContext);

    if (!stage) {
        TF_RUNTIME_ERROR("Could not open file '%s' on a USD stage.", 
                         shaderDefsFile.c_str());
        return result;
    }

    ArResolverContextBinder binder(resolverContext);
    const TfToken discoveryType(ArGetResolver().GetExtension(
            shaderDefsFile));

    auto rootPrims = stage->GetPseudoRoot().GetChildren();
    for (const auto &shaderDef : rootPrims) {
        UsdShadeShader shader(shaderDef);
        if (!shader) {
            continue;
        }

        auto discoveryResults = UsdShadeShaderDefUtils::GetNodeDiscoveryResults(
                shader, shaderDefsFile);

        result.insert(result.end(), discoveryResults.begin(), 
                      discoveryResults.end());

        if (discoveryResults.empty()) {
            TF_RUNTIME_ERROR("Found shader definition <%s> with no valid "
                "discovery results. This is likely because there are no "
                "resolvable info:sourceAsset values.", 
                shaderDef.GetPath().GetText());
        }
    }

    return result;
}
Example #6
0
void
GusdUSD_StageProxy::_Reload(const UsdStageRefPtr& stage)
{
    UT_ASSERT_P(stage);

    stage->Reload();

    _stageData.Update(stage);

    // Stage contents may have changed, so caches need to be flushed.
    _cache.ClearDataCaches(*this);
}
Example #7
0
 void    _SetLoaded(const SdfPath& path, const UsdStageRefPtr& stage)
         {
             /* Mark descendants, to reduce future lock contention.
                TODO: This will also have the effect of increasing the
                size of the set, which may slow down lookups.
                Test how this affects prim load checks on larger stages
                (i.e., millions of prims) .*/
             if(UsdPrim prim = stage->GetPrimAtPath(path)) {
                 for(UsdPrim p: UsdPrimRange::AllPrims(prim))
                     _loaded.insert(p.GetPath());
             }
         }
PXR_NAMESPACE_USING_DIRECTIVE

void
TestTemplates()
{
    // --------------------------------------------------------------------- //
    // This test operates on /RootPrim.foo
    // and /RootPrim.foo:hidden
    // --------------------------------------------------------------------- //
    SdfPath primPath("/RootPrim");
    TfToken prop("foo");
    TfToken metaField("hidden");
    std::string propPath(primPath.GetString() + "." + prop.GetString());

    // --------------------------------------------------------------------- //
    // Author scene and compose the Stage 
    // --------------------------------------------------------------------- //
    SdfLayerRefPtr layer = SdfLayer::CreateAnonymous();
    UsdStageRefPtr stage = UsdStage::Open(layer->GetIdentifier());

    TF_VERIFY(stage->OverridePrim(primPath),
              "Failed to create prim at %s",
              primPath.GetText());

    UsdPrim prim(stage->GetPrimAtPath(primPath));
    TF_VERIFY(prim, "Failed to get Prim from %s", primPath.GetText());

    // Grab the attribute we will be testing with.
    UsdAttribute attr =
        prim.CreateAttribute(prop, SdfValueTypeNames->Double3Array);
    TF_VERIFY(attr, "Failed to create property at %s", propPath.c_str());

    // --------------------------------------------------------------------- //
    // Setup some test data 
    // --------------------------------------------------------------------- //
    VtVec3dArray vtVecOut(1);
    VtVec3dArray vtVecIn;
    std::string tmp;

    VtValue value;

    // ===================================================================== //
    // TEST READING METADATA
    // ===================================================================== //

    // --------------------------------------------------------------------- //
    // GetMetadata & SetMetadata the value as a VtValue
    // --------------------------------------------------------------------- //
    TF_VERIFY(attr.SetMetadata(metaField, VtValue(true)),
              "VtValue: Failed to set hidden metadata at %s",
              propPath.c_str());

    // Print the layer for debugging.
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "Metadata -- VtValue:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify the result.
    TF_VERIFY(attr.GetMetadata(metaField, &value),
              "Metadata -- VtValue: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(value.IsHolding<bool>(),
              "Metadata -- VtValue: not holding bool%s",
              propPath.c_str());
   TF_VERIFY(value.Get<bool>(),
              "Metadata -- VtValue: value was not true %s",
              propPath.c_str());

    // --------------------------------------------------------------------- //
    // GetMetadata & SetMetadata the value as bool 
    // --------------------------------------------------------------------- //
    bool valueIn = false;
    TF_VERIFY(attr.SetMetadata(metaField, true),
              "Metadata -- bool: Failed to set property at %s",
              propPath.c_str());

    // Print the layer for debugging.
    tmp = "";
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "Metadata -- bool:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify Result.
    TF_VERIFY(attr.GetMetadata(metaField, &valueIn),
              "Metadata -- bool: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(valueIn,
              "Metadata -- bool: value was not true %s",
              propPath.c_str());

    
    // ===================================================================== //
    // TEST READING VALUES
    // ===================================================================== //
    
    // --------------------------------------------------------------------- //
    // Get & Set the value as a VtValue
    // --------------------------------------------------------------------- //
    vtVecOut[0] = GfVec3d(9,8,7);
    TF_VERIFY(attr.Set(VtValue(vtVecOut)),
              "VtValue: Failed to set property at %s",
              propPath.c_str());

    // Print the layer for debugging.
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "VtValue:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify the result.
    TF_VERIFY(attr.Get(&value),
              "VtValue: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(value.IsHolding<VtVec3dArray>(),
              "VtValue: not holding VtVec3dArray %s",
              propPath.c_str());
   TF_VERIFY(value.Get<VtVec3dArray>()[0] == vtVecOut[0],
              "VtValue: VtVec3d[0] does not match %s",
              propPath.c_str());

    // --------------------------------------------------------------------- //
    // Get & Set the value as a VtArray 
    // --------------------------------------------------------------------- //
    vtVecOut[0] = GfVec3d(6,5,4);
    TF_VERIFY(attr.Set(vtVecOut),
              "Failed to set property at %s",
              propPath.c_str());

    // Print the layer for debugging.
    tmp = "";
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "VtArray:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify Result.
    TF_VERIFY(attr.Get(&vtVecIn),
              "VtArray: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(vtVecIn[0] == vtVecOut[0],
              "VtArray: VtVec3d[0] does not match %s",
              propPath.c_str());

    // --------------------------------------------------------------------- //
    // Get & Set the value as a VtDictionary (Dictionary composition semantics
    // are exercised in testUsdMetadata).
    // --------------------------------------------------------------------- //
    VtDictionary inDict;
    inDict["$Side"] = "R";
    TF_VERIFY(!prim.HasAuthoredMetadata(SdfFieldKeys->PrefixSubstitutions));
    TF_VERIFY(prim.SetMetadata(SdfFieldKeys->PrefixSubstitutions, inDict));
    VtDictionary outDict;
    TF_VERIFY(prim.HasAuthoredMetadata(SdfFieldKeys->PrefixSubstitutions));
    // Verify bug 97783 - GetMetadata should return true if Usd was able to
    // retrieve/compose a VtDictionary.
    TF_VERIFY(prim.GetMetadata(SdfFieldKeys->PrefixSubstitutions,&outDict));
    TF_VERIFY(inDict == outDict);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "VtDictionary:" << std::endl;
    tmp = "";
    layer->ExportToString(&tmp);
    std::cout << tmp << std::endl;
    
}
Example #9
0
 void    Load(const SdfPathSet& paths, const UsdStageRefPtr& stage)
         {
             stage->LoadAndUnload(paths, SdfPathSet());
             _SetLoaded(paths, stage);
         }
Example #10
0
 /** Load prims. Must already have a write lock.
     @{ */
 void    Load(const SdfPath& path, const UsdStageRefPtr& stage)
         {
             stage->Load(path);
             _SetLoaded(path, stage);
         }
void
My_TestGLDrawing::InitTest()
{
    std::cout << "My_TestGLDrawing::InitTest()\n";
    _stage = UsdStage::Open(GetStageFilePath());
    SdfPathVector excludedPaths;

    if (UsdImagingGLEngine::IsHydraEnabled()) {
        std::cout << "Using HD Renderer.\n";
        _engine.reset(new UsdImagingGLEngine(
            _stage->GetPseudoRoot().GetPath(), excludedPaths));
        if (!_GetRenderer().IsEmpty()) {
            if (!_engine->SetRendererPlugin(_GetRenderer())) {
                std::cerr << "Couldn't set renderer plugin: " <<
                    _GetRenderer().GetText() << std::endl;
                exit(-1);
            } else {
                std::cout << "Renderer plugin: " << _GetRenderer().GetText()
                    << std::endl;
            }
        }
    } else{
        std::cout << "Using Reference Renderer.\n"; 
        _engine.reset(
            new UsdImagingGLEngine(_stage->GetPseudoRoot().GetPath(), 
                    excludedPaths));
    }

    std::cout << glGetString(GL_VENDOR) << "\n";
    std::cout << glGetString(GL_RENDERER) << "\n";
    std::cout << glGetString(GL_VERSION) << "\n";

    if (_ShouldFrameAll()) {
        TfTokenVector purposes;
        purposes.push_back(UsdGeomTokens->default_);
        purposes.push_back(UsdGeomTokens->proxy);

        // Extent hints are sometimes authored as an optimization to avoid
        // computing bounds, they are particularly useful for some tests where
        // there is no bound on the first frame.
        bool useExtentHints = true;
        UsdGeomBBoxCache bboxCache(UsdTimeCode::Default(), purposes, useExtentHints);

        GfBBox3d bbox = bboxCache.ComputeWorldBound(_stage->GetPseudoRoot());
        GfRange3d world = bbox.ComputeAlignedRange();

        GfVec3d worldCenter = (world.GetMin() + world.GetMax()) / 2.0;
        double worldSize = world.GetSize().GetLength();

        std::cerr << "worldCenter: " << worldCenter << "\n";
        std::cerr << "worldSize: " << worldSize << "\n";
        if (UsdGeomGetStageUpAxis(_stage) == UsdGeomTokens->z) {
            // transpose y and z centering translation
            _translate[0] = -worldCenter[0];
            _translate[1] = -worldCenter[2];
            _translate[2] = -worldCenter[1] - worldSize;
        } else {
            _translate[0] = -worldCenter[0];
            _translate[1] = -worldCenter[1];
            _translate[2] = -worldCenter[2] - worldSize;
        }
    } else {
        _translate[0] = GetTranslate()[0];
        _translate[1] = GetTranslate()[1];
        _translate[2] = GetTranslate()[2];
    }

    if(IsEnabledTestLighting()) {
        if(UsdImagingGLEngine::IsHydraEnabled()) {
            // set same parameter as GlfSimpleLightingContext::SetStateFromOpenGL
            // OpenGL defaults
            _lightingContext = GlfSimpleLightingContext::New();
            GlfSimpleLight light;
            if (IsEnabledCameraLight()) {
                light.SetPosition(GfVec4f(_translate[0], _translate[2], _translate[1], 0));
            } else {
                light.SetPosition(GfVec4f(0, -.5, .5, 0));
            }
            light.SetDiffuse(GfVec4f(1,1,1,1));
            light.SetAmbient(GfVec4f(0,0,0,1));
            light.SetSpecular(GfVec4f(1,1,1,1));
            GlfSimpleLightVector lights;
            lights.push_back(light);
            _lightingContext->SetLights(lights);

            GlfSimpleMaterial material;
            material.SetAmbient(GfVec4f(0.2, 0.2, 0.2, 1.0));
            material.SetDiffuse(GfVec4f(0.8, 0.8, 0.8, 1.0));
            material.SetSpecular(GfVec4f(0,0,0,1));
            material.SetShininess(0.0001f);
            _lightingContext->SetMaterial(material);
            _lightingContext->SetSceneAmbient(GfVec4f(0.2,0.2,0.2,1.0));
        } else {
            glEnable(GL_LIGHTING);
            glEnable(GL_LIGHT0);
            if (IsEnabledCameraLight()) {
                float position[4] = {_translate[0], _translate[2], _translate[1], 0};
                glLightfv(GL_LIGHT0, GL_POSITION, position);
            } else {
                float position[4] = {0,-.5,.5,0};
                glLightfv(GL_LIGHT0, GL_POSITION, position);
            }
        }
    }
}
void
My_TestGLDrawing::DrawTest(bool offscreen)
{
    std::cout << "My_TestGLDrawing::DrawTest()\n";

    HdPerfLog& perfLog = HdPerfLog::GetInstance();
    perfLog.Enable();
    
    // Reset all counters we care about.
    perfLog.ResetCache(HdTokens->extent);
    perfLog.ResetCache(HdTokens->points);
    perfLog.ResetCache(HdTokens->topology);
    perfLog.ResetCache(HdTokens->transform);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingExtent, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingPrimvar, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingTopology, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingVisibility, 0);
    perfLog.SetCounter(UsdImagingTokens->usdVaryingXform, 0);

    int width = GetWidth(), height = GetHeight();

    double aspectRatio = double(width)/height;
    GfFrustum frustum;
    frustum.SetPerspective(60.0, aspectRatio, 1, 100000.0);

    GfMatrix4d viewMatrix;
    viewMatrix.SetIdentity();
    viewMatrix *= GfMatrix4d().SetRotate(GfRotation(GfVec3d(0, 1, 0), _rotate[0]));
    viewMatrix *= GfMatrix4d().SetRotate(GfRotation(GfVec3d(1, 0, 0), _rotate[1]));
    viewMatrix *= GfMatrix4d().SetTranslate(GfVec3d(_translate[0], _translate[1], _translate[2]));

    GfMatrix4d projMatrix = frustum.ComputeProjectionMatrix();

    GfMatrix4d modelViewMatrix = viewMatrix; 
    if (UsdGeomGetStageUpAxis(_stage) == UsdGeomTokens->z) {
        // rotate from z-up to y-up
        modelViewMatrix = 
            GfMatrix4d().SetRotate(GfRotation(GfVec3d(1.0,0.0,0.0), -90.0)) *
            modelViewMatrix;
    }

    GfVec4d viewport(0, 0, width, height);
    _engine->SetCameraState(modelViewMatrix, projMatrix, viewport);

    size_t i = 0;
    TF_FOR_ALL(timeIt, GetTimes()) {
        UsdTimeCode time = *timeIt;
        if (*timeIt == -999) {
            time = UsdTimeCode::Default();
        }
        UsdImagingGLRenderParams params;
        params.drawMode = GetDrawMode();
        params.enableLighting = IsEnabledTestLighting();
        params.enableIdRender = IsEnabledIdRender();
        params.frame = time;
        params.complexity = _GetComplexity();
        params.cullStyle = IsEnabledCullBackfaces() ?
                            UsdImagingGLCullStyle::CULL_STYLE_BACK :
                            UsdImagingGLCullStyle::CULL_STYLE_NOTHING;

        glViewport(0, 0, width, height);

        glEnable(GL_DEPTH_TEST);

        if(IsEnabledTestLighting()) {
            if(UsdImagingGLEngine::IsHydraEnabled()) {
                _engine->SetLightingState(_lightingContext);
            } else {
                _engine->SetLightingStateFromOpenGL();
            }
        }

        if (!GetClipPlanes().empty()) {
            params.clipPlanes = GetClipPlanes();
            for (size_t i=0; i<GetClipPlanes().size(); ++i) {
                glEnable(GL_CLIP_PLANE0 + i);
            }
        }

        GfVec4f const &clearColor = GetClearColor();
        GLfloat clearDepth[1] = { 1.0f };

        // Make sure we render to convergence.
        TfErrorMark mark;
        do {
            glClearBufferfv(GL_COLOR, 0, clearColor.data());
            glClearBufferfv(GL_DEPTH, 0, clearDepth);
            _engine->Render(_stage->GetPseudoRoot(), params);
        } while (!_engine->IsConverged());
        TF_VERIFY(mark.IsClean(), "Errors occurred while rendering!");

        std::cout << "itemsDrawn " << perfLog.GetCounter(HdTokens->itemsDrawn) << std::endl;
        std::cout << "totalItemCount " << perfLog.GetCounter(HdTokens->totalItemCount) << std::endl;

        std::string imageFilePath = GetOutputFilePath();
        if (!imageFilePath.empty()) {
            if (time != UsdTimeCode::Default()) {
                std::stringstream suffix;
                suffix << "_" << std::setw(3) << std::setfill('0') << params.frame << ".png";
                imageFilePath = TfStringReplace(imageFilePath, ".png", suffix.str());
            }
            std::cout << imageFilePath << "\n";
            WriteToFile("color", imageFilePath);
        }
        i++;
    }