can't get bitmap shader work correctly



  • On 01/02/2018 at 11:11, xxxxxxxx wrote:

    HI
    It's my first post here.
    I script a bit for a while, but it's my first try to write a plugin, so there could be  many dirty things.

    I'm currently trying to write a ShaderData plugin to manipulate textures.
    As I didn't find any example in python, for texturing/bitmap part, I try to "port" the sample from microbion site  (bmFlip), but which is in C++.
    The workfow is a bit different. I try my own "version" and it has worked for a while,  but it's pretty buggy. Sometime I get it in viewport, sometime in render, and now just bug the other modes (World or Local, who just display World position color) and no more render succes. If I clear the bitmap channel, all return fine.
    I'm obviously doing something wrong with my bitmap part "implentation".
    In output the shader call is in the "Espace UV" part.

    Somebody could put me in the right direction ?
    I can join the complete folder if necessary.

    And a second question I try to access different members of volumeData.
    it work, but I all time get this message : "UnboundLocalError: local variable 'raypos' referenced before assignment".

    And in case  I don't see anything to put an attachment, it must be extern ?

      
    import os  
    import math  
      
    import c4d  
    from c4d import plugins, bitmaps, utils  
      
      
    PLUGIN_ID = 1040539  
      
    FPLUGTWO_TEXTURE = 1000  
    FPLUGTWO_FLIPX = 1010  
    FPLUGTWO_FLIPY = 1020  
    FPLUGTWO_MODE  = 1030  
    FPLUGTWO_UV    = 0  
    FPLUGTWO_WORLD = 1  
    FPLUGTWO_LOCAL = 2  
    FPLUGTWO_PREVIEW = 1040  
    FPLUGTWO_TOTO = 1050  
      
    class FPlugTwo(c4d.plugins.ShaderData) :  
      
      print "FPlugTwo ok"  
            
      def __init__(self) :  
          #debug color  
          self.ape = True  
          self.mode = 0  
          self.shader = None  
          self.flipx = False  
          self.flipy = False  
          self.mode = 1  
          self.preview = True  
          self.toto = 0.5  
            
          self.SetExceptionColor(c4d.Vector(1,0,0))  
        
      def Init(self, node) :  
          donnees = node.GetDataInstance()  
          donnees.SetBool(FPLUGTWO_FLIPX, self.flipx)  
          donnees.SetBool(FPLUGTWO_FLIPY, self.flipy)  
          donnees.SetLong(FPLUGTWO_MODE, self.mode)  
          donnees.SetBool(FPLUGTWO_PREVIEW, self.preview)  
          donnees.SetReal(FPLUGTWO_TOTO, self.toto)  
          return True  
            
      def InitRender(self, sh, irs) :  
          donnees = sh.GetDataInstance()  
          self.shader = donnees.GetLink(FPLUGTWO_TEXTURE, irs.doc)  
          print self.shader  
          self.flipx = donnees.GetBool(FPLUGTWO_FLIPX)  
          self.flipy = donnees.GetBool(FPLUGTWO_FLIPY)  
          self.mode = donnees.GetLong(FPLUGTWO_MODE)  
          self.preview = donnees.GetBool(FPLUGTWO_PREVIEW, self.preview)  
          self.toto = donnees.GetReal(FPLUGTWO_TOTO)  
          self.irs = irs  
          if self.shader :  
              result = self.shader.InitRender(irs);  
              if result == c4d.INITRENDERRESULT_OK :  
                  print "INITRENDERRESULT_OK"  
              else :  
                  print "something Wrong in InitRender"                  
              return result  
          return 0  
        
      #This method seem not used, or not relevant  
      def Message(self, node, type, msgdat) :  
          donnees = node.GetDataInstance()  
          if type == c4d.MSG_INITIALCHANNEL:  
              print "MSG_INITIALCHANNEL"              
          #data = ((PluginShader* )node)->GetDataInstance();  
          #HandleInitialChannel(node, BMFLIPSHADER_TEXTURE, type, msgdat);  
          #HandleShaderMessage(node, (PluginShader* )data->GetLink(BMFLIPSHADER_TEXTURE, node->GetDocument(), Xbase), type, msgdat);  
          return True  
        
      def Output(self, sh, cd) :  
          pos = c4d.Vector()  
          nor = c4d.Vector()  
        
          if self.mode == FPLUGTWO_WORLD : # Espace Monde  
              if cd.vd : # 3D  
                  #just some tests  
                  pos  = cd.vd.p  
                  nor  = cd.vd.orign  
                  uvPos= cd.vd.uvw  
                  #print uvPos  
                  aRay = cd.vd.ray  
                  #print aRay  
                  raypos = aRay.p  
                  rayDir = aRay.v  
                  rayIOR = aRay.ior/4.0  
                  rayLength = cd.vd.dist #The distance between p and ray->p, i.e. the ray length.   
                  rayAngle = (cd.vd.cosc  \+ 1) /2.0 #The angle between ray vector and unbumped normal.  
                  mapVal = self.rangeMapper( rayAngle, 0.6, 1.0, 0.0, 1.0)  
                  print mapVal  
                  linVal = math.pow(mapVal, 2.2) #0.45454  
                  colVal = c4d.Vector(linVal,linVal/2.0,linVal)            
              else : # Aperçu  
                  if self.ape : pos = (cd.p - 0.5) * 100.0  
                  else : return pos              
              color = colVal  
            
          elif self.mode == FPLUGTWO_UV : # Espace UV  
              #color = cd.p  
              color = self.shader.Sample(cd)  
            
          elif self.mode == FPLUGTWO_LOCAL : # Espace Objet  
              if cd.vd : # 3D  
                  pos = cd.vd.p  
              else : # Aperçu  
                  if self.ape : pos = (cd.p - 0.5) * 100.0  
                  else : return pos  
              color = pos  
        
      def FreeRender(self, sh) :  
          #Free any resources used for the precalculated data from InitRender().  
          return  
        
        
      
    def registerThePlug() :  
      #c4d.plugins.RegisterShaderPlugin(id, str, info, g, description[, disklevel][, res])  
        
      IDS_FPLUGTWO=10000  
      name = plugins.GeLoadString(IDS_FPLUGTWO);  
      return plugins.RegisterShaderPlugin(PLUGIN_ID, name, 0, FPlugTwo, "FPlugTwo", 0)  
        
    if __name__ == "__main__":  
      registerThePlug()  
    


  • On 02/02/2018 at 04:02, xxxxxxxx wrote:

    Hello and Welcome to Plugin Café f_lcc !

    First of all I would like to remind you that we are not suppose to develop your plugin or even debug it.
    Please help us to help you. Instead of telling it's not working, tell us what you want to achieve.
    Moreover keep your example simple, one problem, one example (it will also help you to debug your code).

    With that said, there are few issues in your code.

    Output function:

    1. This function as it's written in the SDK, should return a c4d.Vector, then make sure all your conditions return a vector.
    2. Variable scope, if you create a variable within an indentation, this variable will only be available in this indentation scope or children one. (cf color variable)
    3. self.rangeMapper did not exist, so I replaced by c4d.utils.RangeMap(rayAngle, 0.6, 1.0, 0.0, 1.0, True). Use Clamp value to True since you are using pow.
    4. Always check for variable(cf self.shader)

    While I know you are currently learning, in python you can do MyVariable = 10 if x < y else 20

    	def Output(self, sh, cd) :
    		pos = c4d.Vector()
    		nor = c4d.Vector()
    		color = c4d.Vector()
      
    		if self.mode == FPLUGTWO_WORLD : # Espace Monde
    			colVal = c4d.Vector()
      
    			if cd.vd : # 3D
    				#just some tests
    				pos  = cd.vd.p
    				nor  = cd.vd.orign
    				uvPos= cd.vd.uvw
    				#print uvPos
    				aRay = cd.vd.ray
    				#print aRay
    				raypos = aRay.p
    				rayDir = aRay.v
    				rayIOR = aRay.ior/4.0
    				rayLength = cd.vd.dist #The distance between p and ray->p, i.e. the ray length. 
    				rayAngle = (cd.vd.cosc  \+ 1) /2.0 #The angle between ray vector and unbumped normal.
    				mapVal = c4d.utils.RangeMap(rayAngle, 0.6, 1.0, 0.0, 1.0, True) 
    				linVal = math.pow(mapVal, 2.2) #0.45454
    				colVal = c4d.Vector(linVal, linVal/2.0, linVal)
      
    			else : # Aperçu
    				pos = (cd.p - 0.5) * 100.0 if self.ape else pos
    				return pos
      
    			color = colVal
    		
    		elif self.mode == FPLUGTWO_UV : # Espace UV
    			#color = cd.p
    			color = self.shader.Sample(cd) if self.shader else cd.p
      
    		
    		elif self.mode == FPLUGTWO_LOCAL : # Espace Objet
    			if cd.vd : # 3D
    				pos = cd.vd.p
    			else : # Aperçu
    				if self.ape : pos = (cd.p - 0.5) * 100.0
    				else : return pos
    			color = pos
      
    		return color
    

    FreeRender:

    1. In your InitRender you initialize a shader, Free this one when the render is finnish or you have some memory leaks.
        def FreeRender(self, sh) :
            #Free any resources used for the precalculated data from InitRender().
            if self.shader:
                self.shader.FreeRender()
            return
    

    If you have any others questions feel free to ask :)



  • On 02/02/2018 at 07:58, xxxxxxxx wrote:

    Thank for the quick response.

    ok i will be more secifique next time.

    Work perfectly now.

    And true I hardly forgot the importance of scope :)


Log in to reply