Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Sampling from ShaderLink into BaseBitmap [SOLVED]

    SDK Help
    0
    7
    612
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 25/05/2016 at 07:46, xxxxxxxx wrote:

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

      ---------
      Hello,

      I must be missing something very obvious. I cannot get proper bitmap pixels sampled from a shaderlink. I am running this from GetVritualObjects.

      For example, I have a generator plugin that generates a plane. 
      I have a shader link in the description that lets the user input a shader, like a bitmap or a noise shader.
      I need to sample this shader into a bitmap that I can use later to do some calculations, based on the plane UVs.
      This would be done from inside GetVirtualObjects. Or is there a better place to do it?

      Here is the code I am using:

      	AutoAlloc<BaseBitmap> bmp;
      	BaseShader* shaderLink = (BaseShader* )bc->GetLink(MYSHADERLINK,doc);
        
      	if (shaderLink)
      	{
      		InitRenderStruct irs;
      		shaderLink->InitRender(irs);
        
      		LONG bitmapWidth = 100; 
      		LONG bitmapHeight = 100; 
        
      		IMAGERESULT res = bmp->Init(bitmapWidth, bitmapHeight);
        
      		if (res == IMAGERESULT_OK)
      		{
      			ChannelData chD;
      			chD.p = Vector(0, 0, 0);
      			chD.n = Vector(0, 1, 0);
      			chD.d = Vector(0, 0, 0);
      			chD.t = 0.0;
      			chD.texflag = TEX_TILE;
      			chD.vd = NULL;
      			chD.off = 0.0;
      			chD.scale = 0.0;
        
      			for (LONG x=0; x < bitmapWidth; x++) 
      			{
      				for (LONG y=0; y < bitmapHeight; y++) 
      				{
      					chD.p.x = (Real) x ;
      					chD.p.y = (Real) y ;
      					Vector pixel = shaderLink->Sample(&chD);
        
      					LONG r1 = pixel.x * 255;
      					LONG g1 = pixel.y * 255;
      					LONG b1 = pixel.z * 255;
      					bmp->SetPixel(x, y, r1, g1, b1);
      				}
      			}
      		}
      	}
      

      Any help would be greatly appreciated.

      Edited for a better explanation.

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 25/05/2016 at 08:02, xxxxxxxx wrote:

        1. ChannelData.p is READ ONLY.  And it is in UVW coordinate space not image or other space.

        2. Sample() must be called within a set of InitRender()/FreeRender() calls.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 25/05/2016 at 08:16, xxxxxxxx wrote:

          Thank you for the reply Robert.

          Do you have an example by any chance with the correct InitRender()/FreeRender() calls that I can look at?

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 25/05/2016 at 08:47, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            1. ChannelData.p is READ ONLY.  And it is in UVW coordinate space not image or other space.

            It is READ ONLY from the context of a shader. However to feed the shader, you can manipulate ChannelData.p to your liking (outside of ShaderData::Output())

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 26/05/2016 at 01:50, xxxxxxxx wrote:

              Hi Salozo,

              There are several mistakes in your code.

              First, you're missing the call to shaderLink- >FreeRender() after you've finished with the sampling.
              (Note you can check the return value of InitRender() if INITRENDERRESULT_OK.)

              Second, and this seems the most important issue, U and V coordinates have to be in the [0-1] range.
              This is why you're not getting the shader pixels as expected.
              The following lines have to be changed:

              Originally posted by xxxxxxxx

              chD.p.x = (Real) x ;
              chD.p.y = (Real) y ;
              

              Divide x and y by the width and height of the bitmap.

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 26/05/2016 at 05:24, xxxxxxxx wrote:

                Also note that Cinema calls FreeRender() even when the InitRender()
                returned an error. Some shaders might depend on this behavioura and
                you should replicate it to avoid memory leaks or even more
                crucial errorrs.

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 26/05/2016 at 12:32, xxxxxxxx wrote:

                  Thank you Yannik, Nicklas and Robert. Yannick's remark did the trick.

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post