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
    • Recent
    • Tags
    • Users
    • Login

    Python ShaderData/ChannelData problem [SOLVED]

    Scheduled Pinned Locked Moved PYTHON Development
    9 Posts 0 Posters 756 Views
    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 Offline
      Helper
      last edited by

      On 16/12/2014 at 00:43, xxxxxxxx wrote:

      Hi,

      this topic is also somehow related to another one by me in the C++ section of this forum:
      Custom Tile Shader problem with previews

      I tried to translate my test shader that you can find in the link above to Python.
      Just because it makes prototyping such stuff more comfortable that you can simply reload registered Python plugins in C4D after source code changes.

      But unfortunately I run into a problem here too.

      Any manipulations I try to make to "cd.p" are ignored.

      Here is the source code:

        
      #############################################################  
      ## CINEMA 4D Python Tile Shader Test                       ##  
      #############################################################  
      ## by Thomas Chen (2014)                                   ##  
      #############################################################  
      ## Py-TileShaderTest.pyp                                   ##  
      #############################################################  
        
      import c4d  
      from c4d import plugins  
        
        
      #warning Please obtain your own plugin ID from http://www.plugincafe.com  
      PLUGIN_ID = 1000010  
        
        
      class TileShaderTest(plugins.ShaderData) :  
        
        tiles = 1  
        texture = None  
        
        
        def __init__(self) :  
            #if a Python exception occurs during the calculation  
            #of a pixel colorize this one in red for debugging purposes  
            self.SetExceptionColor(c4d.Vector(1.0, 0.0, 0.0))  
        
        
        def Init(self, node) :  
            #Called when a new instance of the node plugin has been allocated.  
        
            node[c4d.TILESHADERTEST_TILES] = self.tiles  
            node[c4d.TILESHADERTEST_TEXTURE] = self.texture  
        
            return True  
        
        
        def InitRender(self, sh, irs) :  
            #Precalculate any data for rendering.  
        
            self.tiles = sh[c4d.TILESHADERTEST_TILES]  
              
            self.texture = sh[c4d.TILESHADERTEST_TEXTURE]  
            if self.texture:  
                self.texture.InitRender(irs)  
         
            return 0  
        
        
        def FreeRender(self, sh) :  
            #Free any resources used for the precalculated data from InitRender()  
              
            if (self.texture) :  
                self.texture.FreeRender()  
              
            self.texture = None  
        
        
        def Output(self, sh, cd) :  
            #Called for each point of the visible surface of a shaded object. Here you should calculate and return the channel color for the point cd.p.  
        
            cd.p.x = cd.p.x * self.tiles  
            cd.p.y = cd.p.y * self.tiles  
              
            col = c4d.Vector(0.0, 0.0, 0.0)  
              
            if self.texture:  
                col = self.texture.Sample(cd)  
         
            return col  
        
        
      def RegisterTileShaderTest() :  
          
        return plugins.RegisterShaderPlugin(PLUGIN_ID, "Py-TileShaderTest", 0, TileShaderTest, "xtileshadertest", 0)  
        
      if __name__ == '__main__':  
        RegisterTileShaderTest()  
        
      

      That seams to have no effect at all:

              cd.p.x = cd.p.x \* self.tiles  
            cd.p.y = cd.p.y \* self.tiles
      

      I also tried to hardcode different values for "tiles" and to assign different formulas and hardcoded values to "cd.p" too.

      The output is always the complete texture at the whole uv area when I return:

              self.texture.Sample(cd)
      

      Any idea what I miss here?

      Kind regards,
      Tom

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

        On 16/12/2014 at 11:54, xxxxxxxx wrote:

        Hello Tom,

        just assign cd.p to a variable first, like:

          
          def Output(self, sh, cd) :  
                
              x = cd.p.x *1.8  
              y = cd.p.y *1.8  
              z = cd.p.z  
              cd.p = c4d.Vector(x,y,z)  
          
              col = c4d.Vector(0.0, 0.0, 0.0)  
          
              if self.texture:  
                  col = self.texture.Sample(cd)  
              return col  
        

        Best wishes
        Martin

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

          On 16/12/2014 at 12:22, xxxxxxxx wrote:

          again,

          I´ve just read your c++ post more closely.

          for the other issues you can set some texflags.

          cd.texflag= 0
          or
          cd.texflag= c4d.TEX_TILE

          Hope this helps?

          Best wishes
          Martin

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

            On 16/12/2014 at 13:41, xxxxxxxx wrote:

            Hi Martin,

            thank you very much for your replies!
            I'll try that immediately. 😉

            But just for my understanding can you explain to me why this extra step with additional variables is necessary at all to assign new values to cd.p?
            That would be really nice from you .
            I just can't see the logic behind it but I want to grok what I have to do and why.

            ~~And for the other thing with  ~~

             ~~     cd.texflag = c4d.TEX_TILE~~
            

            ~~or
            ~~

             ~~     cd.texflag = 0~~
            

            I have still tried that myself before (at least the first version) but unfortunately I can't see any effect at all. Do you also have tried that yourself and it really worked for you?

            Kind regards,
            Tom

            Edit:
            I now implemented your tip with the extra variables and of course it works! !Smile[URL-REMOVED]
            Though I still don't understand why but nevertheless, thank you again for that valuable hint.

            Edit 2:
            Strange, meanwhile I also had success with cd.texflag = c4d.TEX_TILE.
            Maybe the refresh hadn't worked as I tried that the first time or I don't know what the problem was.
            At least it works partly in a way that all the previews and the tiling behave as expected but the mirroring is prohibited completely and the mix with no mirroring internally but the option with seamless mirroring of the shader output as a whole didn't work that way.
            (Like this: or this: )

            Only for the editor preview but not for the rendering.
            But that would just be the cherry on the cake and I can deal with the current result too if no one knows the perfect solution.

            Know I just have to implemenrt that in my C++ version in a similar way. 😉
            But I have to check that out tomorrow.


            [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

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

              On 17/12/2014 at 03:15, xxxxxxxx wrote:

              Hi Tom,

              I´m glad it is working for you!
              to edit 2:
              sometimes you need to delete the shader and open another one to make your script changes happen
              after you´ve reloaded python shader plugin.
              I´ve no experiences with this, but I guess you´ve allready tried _the   c4d.TEX_MIRROR flag?
              _Please let me know if you found out about the cherry.
              For further explanations why we need a variable, please ask the support team.

              Best wishes
              Martin

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

                On 17/12/2014 at 15:56, xxxxxxxx wrote:

                Hi Tom,

                Although I'm not a Python expert, apparently the *= operator exists in Python, just like in C/C++.  Why not try that out?

                Example:

                  
                cd.p.x *= self.tiles  
                cd.p.y *= self.tiles  
                

                BTW, there should be no reason to have to use intermediate variables.  The only reason off the top of my head is type mismatch or a close equivalent.  Specifying that it's a Vector() is the only notable difference with monkeytack's working code.

                I hope that helps,

                Joey Gaspe
                SDK Support Engineer

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

                  On 17/12/2014 at 16:28, xxxxxxxx wrote:

                  Hello Joey,

                  your example wont work.
                  Please give it a try.
                  As your are much more a programmer than me, it would be nice to understand what´s going on.

                  Best wishes
                  Martin

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

                    On 18/12/2014 at 02:47, xxxxxxxx wrote:

                    Hi Joey,

                    Martin is right that makes no difference.
                    And how should it as [ _ a *= b_ ] is the same as [ _ a = a * b_ ]?

                    But I figured out that it just don't work if you try to assign the single components of the vector seperately (what isn't really necessary for my simple example here but it might be for more complex ones)

                    So the following works:

                    cd.p *= self.tiles
                    

                    as well as:

                    cd.p = cd.p * self.tiles
                    

                    But as mentioned above it doesn't work with cd.p.x , cd.p.y and cd.p.z.

                    And as I said, I have no idea why that is.
                    (But I'd still like to understand! 😉)

                    Kind regards,
                    Tom

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

                      On 18/12/2014 at 07:18, xxxxxxxx wrote:

                      Hi guys,

                      You have a point, and it's on our side, not Python itself.  I found out that this is actually a known issue in Cinema 4D's own Vector Python code, and so will be logged as a defect.

                      In the mean time, you'll have to use the workaround you've found, so I'll close the topic.

                      Thanks,

                      Joey Gaspe
                      SDK Support Engineer

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