Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Sample shader with modified ChannelData

    SDK Help
    0
    8
    800
    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 28/04/2015 at 09:27, xxxxxxxx wrote:

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

      ---------
      I want to sample a shader in my shader but with different UV coordinates than the ones requested 
      for my shader. Modifying ChannelData::p doesn't change anything (strangely) (and also the SDK says it's
      read-only).

      Any idea how to do it?
      Thanks

      Update: Nevermind, the problem is the Noise shader. Everything else seems to work fine. I am only
      wondering why it won't work for the Noise shader (even if I change it to UV space)

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

        On 29/04/2015 at 08:55, xxxxxxxx wrote:

        Hello,

        if you could share the code you use to sample the shader we might be able to find out what is going wrong.

        Best wishes,
        Sebastian

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

          On 29/04/2015 at 10:12, xxxxxxxx wrote:

          Hi Sebastian,

          I've doctored this code since the actual codebase is much larger and more complex. But
          basically it mimics what a certain code branch will do:

          virtual Vector Output(BaseShader* shader, ChannelData* cd) {
            if (!shader || !cd) return Vector(1.0, 0, 0);
            BaseContainer* bc = shader->GetDataInstace();
            if (!bc) return Vector(1.0, 1.0, 0);
            BaseShader* subShader = static_cast<BaseShader*>(
              bc->GetLink(MYSHADER_SUBSHADER, shader->GetDocument(), Xbase));
            if (!subShader) return Vector(0.0, 1.0, 0);
            
            static const Int32 stepu = 1.0 / 6;
            static const Int32 stepv = 1.0 / 6;
            
            Float u = fmod(Abs(cd->p.x), 1);
            Float v = fmod(Abs(cd->p.y), 1);
            
            // This function calculates the stepped value of *x* based on
            // the specified *step*.
            auto steppit = [](const Float x, const Float step) -> Float {
              if (Abs(step - 1.0) <= EPSILON) return 0.0;
              Float r = (x - fmod(x, step)) / (1.0 - step);
              // Rounding errors could lead r to exceed 1.0 *sligthly*,
              // but we really need to make sure it does not, otherwise we
              // will start sampling the other end of the shader again.
              if (r > 1.0) r = 1.0;
              else if (r < 0.0) r = 0.0;
              return r;
            };
            
            u = steppit(i, stepu);
            v = steppit(i, stepv);
            
            ChannelData data = *cd;
            data.p = Vector(u, v, 0);
            return subShader->Sample(&data);
          }
          

          Of course, InitRender() and FreeRender() are called on the subShader.

          Thanks,
          Niklas

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

            On 30/04/2015 at 08:31, xxxxxxxx wrote:

            I am currently facing a much more important problem. 😢
            I only know at the time ShaderData::Output() is called what sub-shader I need to sample. So once
            I figured it out, I will call InitRender() on it. But unfortunately that leads me to a deadlock.

            What happens is the following:

            1. I figure out a shader that I need to sample from my shader , I create an AutoLocker 
            2. I create a clone of the shader that I want to sample and insert it as a shader into my shader
            3. I use the copy of the InitRenderStruct from InitRender() and initialize its member  vd  with the
            VolumeData from the ChannelData.
            4. I call subShader- >InitRender() with the new InitRenderStruct, but this call never exits
            5. I unlock the AutoLocker

            I found this case happening when subShader  is a Layer shader. I thought it would be dangerous
            to initialize a shader from Output(), but is it impossible?

            Thanks a lot in advance,
            Niklas

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

              On 04/05/2015 at 07:17, xxxxxxxx wrote:

              I've moved the initialization to my InitRender() method and now it all works fine (except for the Noise
              Shader which still ignores the U/V data I pass). It's been much more effort to actually figure out the
              shader's that will be needed rather than initializing them on-demand as I could deduce it from the
              ChannelData that was passed to Output().

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

                On 04/05/2015 at 07:38, xxxxxxxx wrote:

                @Niklas, you can get the correct Noise for whatever UV coordinate you want with a hack, noise shader got a Bitmap view that you can get with a size "1k for example" , and then hit the pixel that you want from the UV coordinate

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

                  On 11/05/2015 at 02:04, xxxxxxxx wrote:

                  Hello,

                  sampling a shader I prefer to use a fully setup ChannelData object like this:

                    
                  ChannelData channelData;  
                    
                  channelData.off = 0;  
                  channelData.scale = 0;  
                  channelData.t = 0;  
                  channelData.texflag = TEX_TILE;  
                    
                    
                  channelData.p.x = u;  
                  channelData.p.y = (1.0-v);  
                  channelData.p.z = w;  
                    
                  channelData.d = Vector(1,1,1);  
                    
                  channelData.n = Vector(0,1,0);  
                    
                  channelData.vd = NULL;  
                    
                  Vector res = shader->Sample(&channelData);  
                  

                  best wishes,
                  Sebastian

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

                    On 11/05/2015 at 04:55, xxxxxxxx wrote:

                    Thank you Sebastian, I'll give it a try!

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