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

    Sub Shaders [SOLVED]

    SDK Help
    0
    7
    719
    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 29/08/2016 at 16:29, xxxxxxxx wrote:

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

      ---------
      So I have some code I've been hacking up here. I've loosely through trial and error and foum searches hacked together how to assign shaders in code, but the shader I'm working with now is a shader within a shader, I'm making assumptions assignment should be the same, but this doesn't appear to be the case.

      		if (_emissionShader) {
      			if (_emissionShader->GetType() == Xbitmap) {
      				// The renderer emission channel accept only one type of shader, the blah shader, within that you
      				// need to set the texture
      				BaseShader* soloShader = BaseShader::Alloc(ID_SOLO_SHADER);
      				BaseShader* shader = (BaseShader* )_emissionShader->GetClone(COPYFLAGS_0, nullptr);
      				soloShader->SetParameter(DescID(EFF_TEX_LINK), GeData(shader), DESCFLAGS_SET_0);
        
      				_newMaterial->SetParameter(DescID(EMISSION_SLOT), GeData(soloShader), DESCFLAGS_SET_0);
      				_newMaterial->InsertShader(soloShader);
      				_newMaterial->InsertShader(shader);
      			}
      		}
      

      The Emission Channel has a slot that accepts a specifc shader, so I create that, then I get the clone of an Xbitmap I got from elsewhere. I set Solo Shader's Link field to the Xbitmap, then I set the emission channel to Solo shader itself. Inserting solo shader yields expected output, it is indeed linked, but inserting the Xbitmap doesn't make it appear in Solo Shader's interface.

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

        On 30/08/2016 at 01:17, xxxxxxxx wrote:

        Hello,

        a shader must be inserted into the object that uses the shader. So a sub-shader must be inserted into the parent shader, not into the material. Your "shader" should be inserted into "soloShader" not "_newMaterial". You find some examples on how to handle shaders in the BaseShader Manual.

        Best wishes,
        Sebastian

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

          On 30/08/2016 at 10:38, xxxxxxxx wrote:

          Yeah, what was confusing was I didn't see InsertShader listed as a method of BaseShader. Hovering in C++ today I just noticed it's a Baselist2D method. Thanks for the tip.

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

            On 20/10/2016 at 08:11, xxxxxxxx wrote:

            Originally posted by xxxxxxxx

            Hello,

            a shader must be inserted into the object that uses the shader. So a sub-shader must be inserted into the parent shader, not into the material. Your "shader" should be inserted into "soloShader" not "_newMaterial". You find some examples on how to handle shaders in the BaseShader Manual.

            Best wishes,
            Sebastian

            Hello Sebastian,

            What if one wants to implement something like this:
            Create a shader which can be instanced. So, the shader is created and inserted to material. It can be linked using data->SetLink(IDD_SHADER_X, new_shader) to several properties/ports of other shaders of the same material. 
            So, then edited in one place it is changed everywhere for every property where it is attached. And if you want to enumerate all shaders then you need to access the material with

            for (BaseShader * shader_i = mat->GetFirstShader(); shader_i; shader_i = shader_i->GetNext())
            {...}
            

            Do you see any problems in such approach?
            I afraid that if shader after some ctrl+Z and ctrl+Y may change it's pointer and the links like mentioned IDD_SHADER_X which have referenced the pointers to the old shaders will point to invalid pointers which is not good.
            Is it correct guess?
            Right now I have no problems with this potential problem because do such checks in every shader function:

            	if (!node) return FALSE;
            	if (!node->IsInstanceOf(Xbase)) return FALSE;
              
            	BaseShader * shader = (BaseShader * ) node;
            	BaseContainer * data = shader->GetDataInstance();
            	if (!data) return FALSE;
              
            	BaseList2D * _mat = shader->GetMain();
            	if (!_mat) return FALSE;
            	if (!_mat->IsInstanceOf(Mbase)) return FALSE;
            	BaseMaterial * mat = (BaseMaterial * )_mat;
            

            I think it is possible to avoid this potential problem and store the global list of shaders in Document and link them using some special own implemented IDs and get access to shader pointers using the global map of ID -> shader pointers. This map must be updated, and unique ID of shader must be stored in it's container and be copied in CopyTo method. With this approach it should be possible to copy/paste own implemented shader copies or instances among different materials. This is idea, not yet tested. What do you think about it?

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

              On 21/10/2016 at 00:29, xxxxxxxx wrote:

              Hello,

              one should never store a reference to a (C4DAtom based) element of the Cinema 4D API as a pointer. Instead use a BaseLink to reference such an element. See the BaseLink Manual.

              For questions no longer related to this thread please open a new thread. Thanks.

              best wishes,
              Sebastian

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

                On 21/10/2016 at 11:35, xxxxxxxx wrote:

                When I say that I store pointers then I mean something like this:

                void init_child_shaders(BaseShader * shaderBase, BaseShader * shaderChild)
                {
                	if (!shaderBase) return;
                  
                	if (shaderBase == shaderChild) return;
                  
                	BaseContainer * data = shaderBase->GetDataInstance();
                	BaseDocument * doc = shaderBase->GetDocument();
                  
                	Int32 numLinks = data->GetInt32(SHADER_BLOCK_NUM_CHILDREN);
                  
                	if (doc != 0)
                	{
                		for (Int32 i = 0; i < numLinks; i++)
                			data->SetLink(SHADER_BLOCK_NUM_CHILDREN + 1 + i, shaderChild);
                	}
                }
                

                So here it links with pointers. Is this correct?

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

                  On 24/10/2016 at 00:17, xxxxxxxx wrote:

                  Hello,

                  a BaseContainer stores the pointer internally using a BaseLink so this should work fine (ouf course you should add nullptr checks).

                  For questions no longer related to this thread's topic please open a new thread.

                  best wishes,
                  Sebastian

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