Render Preview Image of Shader

On 30/03/2013 at 04:08, xxxxxxxx wrote:

User Information:
Cinema 4D Version:    
Platform:      
Language(s) :

---------
I'm trying to render a preview-image of a BaseShader, but I get crashes in sdl.cdl. I guess it's because
I don't pass a VolumeData to the ChannelData? I can't get it right. Strange thing is, that the call-stack
only shows one call to my plugin which is the BaseContainer destructor.. And I don't even use a
BaseContainer in this code.

Code:
    sla.cdl!5f9f1ac6()    
    [Unten angegebene Rahmen sind möglicherweise nicht korrekt und/oder fehlen, keine Symbole geladen für sla.cdl]   
    xtensions.cdl!5f73a5e7()    
    CINEMA 4D.exe!01718250()    
    CINEMA 4D.exe!01718250()    
    CINEMA 4D.exe!016a2b74()    
    CINEMA 4D.exe!01bcd2d2()    
    CINEMA 4D.exe!01bd0012()    
    CINEMA 4D.exe!01509238()    
    CINEMA 4D.exe!0145a4de()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!016186e1()    
    CINEMA 4D.exe!016186e1()    
    CINEMA 4D.exe!01716a94()    
    CINEMA 4D.exe!016a17bb()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!016186e1()    
    CINEMA 4D.exe!016186e1()    
    CINEMA 4D.exe!01716a94()    
    CINEMA 4D.exe!01716a94()    
    CINEMA 4D.exe!016a2595()    
    CINEMA 4D.exe!017024ef()    
    CINEMA 4D.exe!01711f53()    
    CINEMA 4D.exe!01626739()    
    CINEMA 4D.exe!016975ce()    
    CINEMA 4D.exe!01b71a3c()    
    CINEMA 4D.exe!0161130f()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!0161132c()    
    CINEMA 4D.exe!016186e1()    
    CINEMA 4D.exe!01716b74()    
    CINEMA 4D.exe!01701696()    
    CINEMA 4D.exe!01711f53()    
    CINEMA 4D.exe!01626739()    
    CINEMA 4D.exe!016975ce()    
    CINEMA 4D.exe!01716b74()    
    CINEMA 4D.exe!0170e612()    
    CINEMA 4D.exe!01716f63()    
    CINEMA 4D.exe!0172088e()    
    CINEMA 4D.exe!0171a86d()    
    CINEMA 4D.exe!01b71a3c()    
    CINEMA 4D.exe!0171cd91()    
    CINEMA 4D.exe!0174e19c()    
    CINEMA 4D.exe!0174e19c()    
    user32.dll!75368e63()    
    user32.dll!75368e9f()    
    msctf.dll!74dc5123()    
    msctf.dll!74dc439e()    
    msctf.dll!74dc3ad3()    
    user32.dll!7537491f()    
    user32.dll!75374902()    
    user32.dll!753729d5()    
    user32.dll!753729b8()    
    user32.dll!75368112()    
    CINEMA 4D.exe!01b58efc()    
    CINEMA 4D.exe!0161a415()    
    CINEMA 4D.exe!01619581()    
    CINEMA 4D.exe!016975ce()    
    CINEMA 4D.exe!0169fbe9()    
    CINEMA 4D.exe!01701696()    
    CINEMA 4D.exe!01711f53()    
    CINEMA 4D.exe!01711f53()    
    CINEMA 4D.exe!01711f53()    
    CINEMA 4D.exe!01643962()    
    CINEMA 4D.exe!01619581()    
    CINEMA 4D.exe!016975ce()    
    CINEMA 4D.exe!01696d7a()    
    CINEMA 4D.exe!01619581()    
    CINEMA 4D.exe!016975ce()    
    CINEMA 4D.exe!016975ce()    
    KernelBase.dll!75195338()    
>   myplugin.cdl!BaseContainer::~BaseContainer()  Zeile 41   C++
    0039c634()   
    CINEMA 4D.exe!01bd59cd()    
    CINEMA 4D.exe!01ba3054()    
    CINEMA 4D.exe!01b1bd67()    
    CINEMA 4D.exe!00e60ef9()    
    CINEMA 4D.exe!01bc7dbf()    
    CINEMA 4D.exe!01707671()    
    CINEMA 4D.exe!0147ad67()

Code:
Bool RenderShader(BaseShader* shader, BaseBitmap* bmp, Real scale=1.0) {
    InitRenderStruct irs;
    if (shader->InitRender(irs) != INITRENDERRESULT_OK) return FALSE;

LONG w = bmp->GetBw();
    LONG h = bmp->GetBh();
    ChannelData cd;

for (LONG x=0; x < w; x++) {
      for (LONG y=0; y < h; y++) {

cd.p.x = x * scale;
        cd.p.y = y * scale;
        cd.p.z = 0.0;

Vector pixel = shader->Sample(&cd);
        LONG r = pixel.x * 255;
        LONG g = pixel.y * 255;
        LONG b = pixel.z * 255;
        bmp->SetPixel(x, y, r, g, b);
      }
    }

shader->FreeRender();
    return TRUE;
}

Any tips much appreciated. Thanks in advance!

-Niklas

On 30/03/2013 at 05:27, xxxxxxxx wrote:

The only bad thing I notice is that you are not checking any pointers for NULL.
An empty VolumeData pointer in the ChannelData should not a problem.

On 30/03/2013 at 05:50, xxxxxxxx wrote:

Hi Jack,

I ensure to pass valid pointers before calling the function anyway so I
decided to not include these checks in the function.

Hm.. I'll try again in another environment, since you say it actually
looks to be correct.

Thanks,

-Niklas

On 30/03/2013 at 06:13, xxxxxxxx wrote:

I've tried to do it in Python first:

from __future__ import division
  
import c4d
from c4d.modules import render
  
def RenderShader(shader, bmp, scale=1.0) :
    irs = render.InitRenderStruct(doc)
    if shader.InitRender(irs) != c4d.INITRENDERRESULT_OK:
        return False
  
    cd = render.ChannelData()
    w, h = bmp.GetSize()
    for x in xrange(w) :
        for y in xrange(h) :
            cd.p.x = x * scale
            cd.p.y = y * scale
            c = shader.Sample(cd)
  
            r = int(c.x * 255)
            g = int(c.y * 255)
            b = int(c.z * 255)
            bmp.SetPixel(x, y, r, g, b)
  
    shader.FreeRender()
    return True
  
def main() :
    bmp = c4d.bitmaps.BaseBitmap()
    bmp.Init(128, 128, 24)
  
    mat = doc.GetActiveMaterial()
    sha = mat.GetFirstShader()
    if not RenderShader(sha, bmp, 1.0) :
        print "Rendering shader was not successful."
        return
  
    c4d.bitmaps.ShowBitmap(bmp)
  
main()

But all I get is a mono-coloured image (black or grey, depending on the shader in the active
material).

On 30/03/2013 at 11:06, xxxxxxxx wrote:

This works!! 🙂

Bool RenderShader(BaseShader* shader, BaseBitmap* bmp, Real scale=1.0) {
    InitRenderStruct irs;
    if (shader->InitRender(irs) != INITRENDERRESULT_OK) return FALSE;
  
    LONG w = bmp->GetBw();
    LONG h = bmp->GetBh();
    ChannelData cd;
    cd.p = Vector(0, 0, 0);
    cd.n = Vector(0, 0, 1);
    cd.d = Vector(0, 0, 0);
    cd.t = 0.0;
    cd.texflag = 0;
    cd.vd = NULL;
    cd.off = 0.0;
    cd.scale = 0.0;
  
    for (LONG x=0; x < w; x++) {
        for (LONG y=0; y < h; y++) {
            cd.p.x = (Real) x * scale;
            cd.p.y = (Real) y * scale;
            Vector pixel = shader->Sample(&cd);
  
            LONG r = MIN(255, pixel.x * 255);
            LONG g = MIN(255, pixel.y * 255);
            LONG b = MIN(255, pixel.z * 255);
            bmp->SetPixel(x, y, r, g, b);
        }
    }
  
    shader->FreeRender();
    return TRUE;
}

I just initialized every value of the ChannelData.

-Niklas

On 30/03/2013 at 11:11, xxxxxxxx wrote:

Works for most shaders.. But eg. the tile shader is black only.. 😕

On 30/03/2013 at 11:24, xxxxxxxx wrote:

hm,

i haven't red everything, but this might help. it is a class to sample a baseshader into 
vertexmap data.

http://codepad.org/qD96O7rR