Python ShaderData/ChannelData problem [SOLVED]



  • 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



  • 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



  • 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



  • 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
    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.



  • 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



  • 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



  • 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



  • 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



  • 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


Log in to reply