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++  ;


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  
  // insert into the polygonSphere  
  // 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);  
  // set the color link of the material to the colorizer shader  
  sphereMaterialBC->SetLink(MATERIAL_COLOR_SHADER, colorizerShader);  
  // update   
  sphereMaterial->Update(true, true);  
  // insert the material and set the texture tag to use this material  
  // 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  
    //  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) + "]");  
      return false;  
  // allocate the bitmap used for storing and saving the baking computations  
  AutoAlloc<BaseBitmap> bakingBmp;  
  if (!bakingBmp)  
      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) + "]");  
      return false;  
  GePrint("Texture baking accomplished");  
  // free the baking document because we're still owning it  
  // 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 !