Texture Baking colorizer shaders [SOLVED]



  • On 28/12/2016 at 01:37, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R18 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hello.

    In order to use C4D shaders in my render engine, I have to bake them into images.
    This works for most of shaders (Noise, gradient, fresnel, e.t.c)

    But, when a shader (e.g. colorizer) contains bitmaps as subshaders, BakeTexture call returns BAKE_TEX_ERR_TEXTURE_MISSING.

    For example, I have a colorizer shader with an Xbitmap in its SLA_COLORIZER_TEXTURE parameter. 
    The bitmap uses "my_image.jpg" as BITMAPSHADER_FILENAME. When I bake that colorizer, the BakeTexture returns missing texture.
    If I set the bitmap filename path into absolute, the baking works correctly.
    The image exists in tex/ folder in the same path as the project.

    Is there anything I can do to make BakeTexture find the texture ?

    Thank you very much for your time.



  • On 30/12/2016 at 07:55, xxxxxxxx wrote:

    Hi Peterakos, thanks for writing us.

    With reference to your question, I've investigated the issue and it seems that if you're using a temporary document as shown in this thread to run your baking computations, it's mandatory to set the document path in order to have Cinema looking into that folder or inside the "contained /tex subfolder and load the bitmap specified with a relative path. If not set Cinema will struggle to find the texture and will look in other places like the application startup folder or it application data users's folder.

    Although setting the document path makes baking working out-of-the-box, i suggest you to have a look at GenerateTexturePath(), which provides you with an helper to generate texture path looking inside the following folders (in order of search)
      a)  the suggested path (if passed as argument);
      b)  the current project folder;
      c)  the ex subfolder in the current project folder;
      d)  the application user data folder;
      e)  the application startup folder;
      f)  the Textures paths specified in the Preferences.

    For the sake of completeness find below a short example.

    Best, Riccardo

        // allocate a temp doc  
      AutoAlloc<BaseDocument> tempDoc;  
      if (!tempDoc)  
          return false;  
         
      tempDoc->SetDocumentPath("<Somewhere On Your Drive>");  
         
      // allocate a primitive sphere  
      BaseObject* primSphere = BaseObject::Alloc(Osphere);  
      if (!primSphere)  
          return false;  
         
      // obtain the polygon representation  
      PolygonObject* polygonSphere = ToPoly(primSphere);  
         
      // insert into the temp doc  
      tempDoc->InsertObject(polygonSphere, nullptr, nullptr);  
         
      // allocate a texture tag  
      TextureTag* sphereTextureTag = TextureTag::Alloc();  
      if (!sphereTextureTag)  
          return false;  
         
      // set the texture tag params  
      sphereTextureTag->SetParameter(DescID(TEXTURETAG_PROJECTION), TEXTURETAG_PROJECTION_CUBIC, DESCFLAGS_SET_0);  
         
      // insert into the polygonSphere  
      polygonSphere->InsertTag(sphereTextureTag);  
         
      // allocate a material  
      AutoAlloc<Material> sphereMaterial;  
      if (!sphereMaterial)  
          return false;  
         
      // get the BaseContainer of the material  
      BaseContainer *sphereMaterialBC = sphereMaterial->GetDataInstance();  
      if (!sphereMaterialBC)  
          return false;  
         
      // allocate the colorizer shader  
      AutoAlloc<BaseShader> colorizerShader(Xcolorizer);  
      if (!colorizerShader)  
          return false;  
         
      // retrieve the BaseContainer of the colorizer   
      BaseContainer* colorizerShaderBC = colorizerShader->GetDataInstance();  
      if (!colorizerShaderBC)  
          return false;  
         
      // allocate the bitmap shader  
      AutoAlloc<BaseShader> bitmapShader(Xbitmap);  
      if (!bitmapShader)  
          return false;  
         
      // retrieve the BaseContainer of the bitmap  
      BaseContainer* bitmapShaderBC = bitmapShader->GetDataInstance();  
      if (!bitmapShaderBC)  
          return false;  
         
      Filename bitmapFilename("bitmap.jpg");  
         
      // set the filename of the bitmap shader  
      // NOTE: the file should reside in the application directory if the project files has not been   
      // saved on disk or inside the /tex folder where the project files resides  
      bitmapShaderBC->SetFilename(BITMAPSHADER_FILENAME, bitmapFilename);  
         
      // set the texture link of the colorizer shader to the bitmapShader  
      colorizerShaderBC->SetLink(SLA_COLORIZER_TEXTURE, bitmapShader);  
      colorizerShader->InsertShader(bitmapShader.Release());  
         
      // set the color link of the material to the colorizer shader  
      sphereMaterialBC->SetLink(MATERIAL_COLOR_SHADER, colorizerShader);  
      sphereMaterial->InsertShader(colorizerShader.Release());  
         
      // update   
      sphereMaterial->Message(MSG_UPDATE);  
      sphereMaterial->Update(true, true);  
         
      // insert the material and set the texture tag to use this material  
      sphereTextureTag->SetMaterial(sphereMaterial);  
      tempDoc->InsertMaterial(sphereMaterial.Release());  
          
      // allocate a BaseContainer for the texture baking settings and set a few meaningful values  
      BaseContainer textureBakingBC;  
      textureBakingBC.SetInt32(BAKE_TEX_WIDTH, 512);  
      textureBakingBC.SetInt32(BAKE_TEX_HEIGHT, 512);  
      textureBakingBC.SetBool(BAKE_TEX_COLOR, true);  
         
      // get the UVW tag from the sphere - it's not required to run GenerateUVW() to get the proper  
      // UVW representation because it's done internally by the InitBakeTexture  
      UVWTag* sphereUVWTag = (UVWTag * )polygonSphere->GetTag(Tuvw);  
         
      // proceed to bake the texture assigned in the color slot  
      BAKE_TEX_ERR initBakingRes = BAKE_TEX_ERR_NONE, bakingRes = BAKE_TEX_ERR_NONE;
        //  init the baking process  
      BaseDocument* bakingDoc = InitBakeTexture(tempDoc, sphereTextureTag, sphereUVWTag, NULL, textureBakingBC, &initBakingRes, NULL);  
      if (initBakingRes != BAKE_TEX_ERR_NONE)  
      {  
          GePrint("Failed to init texture baking[" + String::IntToString(initBakingRes) + "]");  
          BaseDocument::Free(bakingDoc);  
          return false;  
      }  
         
      // allocate the bitmap used for storing and saving the baking computations  
      AutoAlloc<BaseBitmap> bakingBmp;  
      if (!bakingBmp)  
      {  
          BaseDocument::Free(bakingDoc);  
          return false;  
      }  
         
      // execute the texture baking  
      bakingRes = BakeTexture(bakingDoc, textureBakingBC, bakingBmp, NULL, NULL, NULL);  
      if (bakingRes != BAKE_TEX_ERR_NONE)  
      {  
          GePrint("Failed to bake the texture[" + String::IntToString(bakingRes) + "]");  
          BaseDocument::Free(bakingDoc);  
          return false;  
      }  
         
      GePrint("Texture baking accomplished");  
         
      // free the baking document because we're still owning it  
      BaseDocument::Free(bakingDoc);  
         
      // save the bitmap on disk  
      Filename bakingBmpFilename("TextureBackingOutput.jpg");  
      Filename bakingBmpFullFilename = tempDoc->GetDocumentPath() + bakingBmpFilename;  
      IMAGERESULT bakingBmpRes = bakingBmp->Save(bakingBmpFullFilename, FILTER_JPG, nullptr, SAVEBIT_0);  
      if (bakingBmpRes != IMAGERESULT_OK)  
      {  
          GePrint("Failed to save baked texture bitmap [" + String::IntToString(bakingBmpRes) + "]");  
          return false;  
      }  
         
      GePrint("Texture baking saved on " + bakingBmpFullFilename.GetString());  
         
      return true;
    


  • On 30/12/2016 at 11:17, xxxxxxxx wrote:

    I cannot express how much I thank you !!
    Have a nice day !


Log in to reply