Render bug?



  • On 12/02/2014 at 22:39, xxxxxxxx wrote:

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

    ---------
    Hi Folks,

    not sure if this is a bug, or if it's intended to be this way. But..

    I'm trying to render a document to an image via the software renderer. I can render the scene, and display the image in the viewer. With the following settings applied, it renders as it should:

    Software Renderer
    Save Boolean = TRUE
    File = (location here - must not be blank)
    Alpha channel = TRUE
    Straight Alpha = TRUE

    This gets me a software rendered image, with an accompanying alpha channel in the picture viewer's layer tab. The image in the layer itself is all black (is this a bug?) but the alpha does have data, I can see it when I view it as a single pass. This is when calling the render from pressing the render button.

    Now the problems, when I turn off the save bool, the alpha channel is now empty - the layer itself is there, but there is no alpha data in it. Alternatively, if I leave the save bool on, but leave the file location field blank, the alpha channel is also empty with the layer itself still being there.

    Similar principles apply to this when running it through code - though I haven't managed to get an alpha channel out of it yet at all (even with the filename field filled and the save bool ticked). Here are my settings for the code side of things:

      
    // BaseDocument *doc --> get/make a document   
      
    MultipassBitmap *bmp;   
    bmp = MultipassBitmap::Alloc(640,480,COLORMODE_ARGB);   
      
    BaseContainer rd;   
    rd.SetLong(RDATA_RENDERENGINE_PREVIEWSOFTWARE);   
    rd.SetReal(RDATA_XRES_VIRTUAL,640);   
    rd.SetReal(RDATA_YRES_VIRTUAL,480);   
    rd.SetBool(RDATA_SAVEIMAGE,TRUE);   
    rd.SetFilename(RDATA_PATH, "path here..");   
    rd.SetBool(RDATA_ALPHACHANNEL,TRUE);   
    rd.SetBool(RDATA_STRAIGHTALPHA,TRUE);   
      
    RenderDocument(doc,rd,NULL,NULL,bmp,RENDERFLAGS_EXTERNAL,NULL);   
    ShowBitmap(bmp);   
    

    Is this a bug in R14? Or is it something about the render process I've missed or misunderstood? Fortunately/unfortunately I need this feature to work as it's a part of one of the main features of my plugin!

    Cheers,

    WP.

    P.s. just for reference, here's an older topic where it appears a user was previously able to get it working, albeit on an older version: click me!



  • On 13/02/2014 at 11:35, xxxxxxxx wrote:

    FYI- The same thing happens in R13.
    The alpha is black unless I select the Single Pass or Multi-Pass option.
    It seems like this was done intentionally. But I'm not really sure though.
    I don't really use the picture viewer that much.

    If you're having trouble creating an image with an alpha channel.
    I have an example of that sort of thing that might possibly help you out:

    //This code saves a .png image with an Alpha channel using a MultipassBitmap image to store alphas  
    //We need to use a MultipassBitmap like this when not using the built-in render dialog  
      
    Bool SimplePlugin::Execute(BaseDocument *doc)  
    {   
      //The size of the image to render  
      LONG bw = 640;  
      LONG bh = 480;  
      
      //We must first create a BaseBitmap image  
      //Then later on we will use it to extract the Alpha data from it  
      AutoAlloc<BaseBitmap> bmp;  
      if(!bmp) return FALSE;  
      bmp->Init(bw,bh);  
      
      //The final image that will also contain an Alpha channel  
      MultipassBitmap *multiBmp = MultipassBitmap::Alloc(bw,bh,COLORMODE_ARGB);  
      if(!multiBmp) return FALSE;  
      
      //Options  
      BaseContainer rdata = doc->GetActiveRenderData()->GetData();  
      rdata.SetLong(RDATA_XRES, bw);  
      rdata.SetLong(RDATA_YRES, bh);  
      rdata.SetLong(RDATA_RENDERENGINE_PREVIEWSOFTWARE, TRUE);  
      rdata.SetBool(RDATA_ALPHACHANNEL, TRUE);  
      rdata.SetLong(RDATA_ANTIALIASING, ANTI_BEST);  
      
      if(RenderDocument(doc, rdata, NULL, NULL, multiBmp, RENDERFLAGS_EXTERNAL,NULL))  
      {  
          //Add an Alpha channel if one doesn't exist  
          BaseBitmap *alpha = bmp->GetInternalChannel();  
          if(!alpha) alpha = bmp->AddChannel(TRUE,FALSE);  
      
          //Loop through each pixel of the image  
          LONG x,y;  
          for(y=0; y<bh; y++)  
          {  
              for(x=0; x<bw; x++)  
              {  
                  //Create an alpha pixel for each image pixel and store them in the variable "alphaValues"  
                  UWORD alphaValues = 0;  
                  multiBmp->GetAlphaPixel(multiBmp->GetChannelNum(0),x,y,&alphaValues);  
      
                  //Apply the alphaValues data to the image  
                  bmp->SetAlphaPixel(alpha,x,y,alphaValues);  
              }  
          }  
      }  
       
        
      //Save the MultipassBitmap image containing both the image & alpha data to a file on the desktop  
      Filename fn = GeGetC4DPath(C4D_PATH_DESKTOP)+"myimage.png";  
      LONG Result = multiBmp->Save(fn, FILTER_PNG, NULL, SAVEBIT_ALPHA);  
      ShowBitmap(multiBmp);  
      
      MultipassBitmap::Free(multiBmp);  //Free the MultipassBitmap memory to prevent leaks  
      
      EventAdd();  
      
      return TRUE;  
    }
    

    -ScottA



  • On 13/02/2014 at 18:02, xxxxxxxx wrote:

    Hi Scott,
     
    that code is very similar to what I had/have. I'm able to get the images etc from the renderer, but the alpha data is just not there. Even displaying the returned MultipassBitmap from the render in the picture viewer shows no alpha data in the alpha layer. When manually hitting the render button it works - but only if the save boolean is ticked and the filename field is filled out. Any other settings or way doesn't seem to work whether it be manually set off or through code.
     
    I'm not too concerned with the black thumbnail - though I think it should display a small res black and white image. But that aside, I'm more concerned with there not being any alpha data in the layer itself. I've put myself into quite a corner here, as it's part of the crux of one of my plugins - I need it.
     
    I could possibly go through the images manually and create my own alpha etc using some GeRayCollider() code, or comparing the background colour to the pixel colours in the image etc.  But that seems unnecessary - I should be able to get this data from the standard renderer.
     
    Is anyone able to replicate this scenario? Why would the save Boolean and path field have anything to do with the display of the alpha channel (and the alpha data in general)? Or is this behaving like a bug (apart from me!!)?
     
    WP.



  • On 19/02/2014 at 15:30, xxxxxxxx wrote:

    Since nobody is replying. I'll tell you what I know about this. Which might be completely wrong.
    There's zero posts about layers in the forums (other than my own). And the docs don't help much either.

    AFAIK. There's no way to "Render" an image with an alpha " Layer ".
    You can only render an image with an alpha " Channel ".
    The only way I know how to create an alpha layer. Is to load the image into C4D as a PaintTexture file. Then use the PaintLayer class's options to select the image's alpha "channel". Then duplicate it to it's own layer.

    This code will do that:

    //This code renders the scene and saves the image with an alpha channel  
    //Then It loads the image back into C4D and duplicates the alpha into it's own Layer  
    //NOTE: Layers only get saved in .tiff or .psd file formats  
      
    Bool SimplePlugin::Execute(BaseDocument *doc)  
    {  
      //The size of the image to render  
      LONG bw = 640;  
      LONG bh = 480;  
      
      //We must first create a BaseBitmap image  
      //Then later on we will use it to extract the Alpha data from it  
      AutoAlloc<BaseBitmap> bmp;  
      if(!bmp) return FALSE;  
      bmp->Init(bw,bh);  
      
      //The final image that will also contain an Alpha channel  
      MultipassBitmap *multiBmp = MultipassBitmap::Alloc(bw,bh,COLORMODE_ARGB);  
      if(!multiBmp) return FALSE;  
      
      //Options  
      BaseContainer rdata = doc->GetActiveRenderData()->GetData();  
      rdata.SetLong(RDATA_XRES, bw);  
      rdata.SetLong(RDATA_YRES, bh);  
      rdata.SetLong(RDATA_RENDERENGINE_PREVIEWSOFTWARE, TRUE);  
      rdata.SetBool(RDATA_ALPHACHANNEL, TRUE);  
      rdata.SetLong(RDATA_ANTIALIASING, ANTI_BEST);  
      
      if(RenderDocument(doc, rdata, NULL, NULL, multiBmp, RENDERFLAGS_EXTERNAL,NULL))  
      {  
          //Add an Alpha channel if one doesn't exist  
          BaseBitmap *alpha = bmp->GetInternalChannel();  
          if(!alpha) alpha = bmp->AddChannel(TRUE,FALSE);  
      
          //Loop through each pixel of the image  
          LONG x,y;  
          for(y=0; y<bh; y++)  
          {  
              for(x=0; x<bw; x++)  
              {  
                  //Create an alpha pixel for each image pixel and store them in the variable "alphaValues"  
                  UWORD alphaValues = 0;  
                  multiBmp->GetAlphaPixel(multiBmp->GetChannelNum(0),x,y,&alphaValues);  
      
                  //Apply the alphaValues data to the image  
                  bmp->SetAlphaPixel(alpha,x,y,alphaValues);  
              }  
          }  
      }   
        
      //Save the MultipassBitmap image containing both the image & alpha data to a file on the desktop  
      Filename fn = GeGetC4DPath(C4D_PATH_DESKTOP)+"render.psd";  
      LONG result = multiBmp->Save(fn, FILTER_PSD, NULL, SAVEBIT_ALPHA);  
      
      MultipassBitmap::Free(multiBmp);  //Free the MultipassBitmap memory to prevent leaks  
      
      
      /////////////////////////////////////////////////////////////////////////////////////////  
      //Now we load our saved image with an alpha back into C4D so we add new alpha layer to it  
      /////////////////////////////////////////////////////////////////////////////////////////  
      
      BaseContainer bc;  
      bc.SetFilename(LOADTEXTURE_FILENAME, fn);  
      PaintTexture *pTex = (PaintTexture* )SendPainterCommand(PAINTER_LOADTEXTURE, doc, NULL, &bc);  
      if (!pTex) return FALSE;  
      
      if(pTex)  
      {  
          PaintLayer *pLayer = pTex->GetFirstLayer();  
          if(pLayer && pLayer->IsInstanceOf(OBJECT_PAINTLAYERBMP))  
          {  
              Bool ret = PaintTexture::SetSelected_Texture((PaintLayerBmp* )pLayer,NULL);    
              LONG count = pTex->GetLayerCount();  
              //GePrint(LongToString(count));  
              PaintLayer *alpha = pTex->GetAlphaFirst();   
              pTex->SetActiveLayer(alpha,TRUE);  
              CallCommand(170052);    //Duplicate the alpha Layer  
          }  
      
          //Opens a new Texture View window if desired  
          //CallCommand(170103);  
      
          CallCommand(170004);    //Save Texture  
      
      }  
        
      EventAdd();  
      return TRUE;  
    }
    

    Since I'm rendering the scene and then loading it right back into C4D all in one go. This seems like it could be a potentially dangerous thing if the image takes too long to render and save during the first half of the code.
    But it seems to work fine using software preview mode. And not asking it to render and save anything too heavy.

    I'll bet there's probably a better(safer) way to this.
    But since there's nothing at all on the forums about doing this kind of thing. Hopefully this code should at least get you started on creating your own custom image layers.

    -ScottA



  • On 20/02/2014 at 17:25, xxxxxxxx wrote:

    Thanks Scott,
     
    I'll have a play with the code above. I have heard of the PaintTexture before, but have not used it to date. Yet another bitmap-based class to learn..!
     
    Cheers,
     
    WP.



  • On 22/02/2014 at 18:07, xxxxxxxx wrote:

    OK, I really think there's a bug in this one. I'm all but 100% sure there's an issue with the renderer itself (unless it's done this way deliberately...).
     
    The PaintTexture draw comes out the same as the MultipassBitmap and BaseBitmap renders - which probably makes sense given the PaintTexture is 'made' using the same multipass image that the renderer spits out.
     
    None of the images when rendered using 'Software' have alpha data in it, unless the render button is pressed manually, with the save option ticked and filename path filled in (and of course the alpha channel ticked etc). Oddly enough, the same thing happens with the 'Hardware' renderer also.
     
    Unfortunately, using the standard renderer is not an option because of the time it might take to render an image.
     
    There might be a couple of ways I could 'cheat' my way around this, but before I go down this path (which I really want to avoid if possible!), is anyone (support) able to jump in here and clarify/confirm/something else with the above?
     
    Normally I would say it's me and my code, but the same thing happens when the scene is rendered 'manually' via the render button. Cheers,
     
    WP.


Log in to reply