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

    Open source wrapper for Octane/Redshift/Arnold/Vray/Corona in Cinema 4D.

    General Talk
    programming learning-resource
    7
    23
    22.9k
    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.
    • DunhouD
      Dunhou @czt_306
      last edited by Dunhou

      Hi community!

      New versions here!

      I had change the name from renderEngine to Renderer, and also changed the main structure. see more in the very first of this topic. (renderEngine had been move to versions folder, if you still interested.)

      This version is way more organized and user-friendly, you can use few lines of code to do something normal work, find an example below:

      Cheers~
      DunHou


      Result:

      e7eb47f4-f118-45d7-9101-bb610a25921b-image.png

      Code:

      import c4d
      import maxon
      from Renderer import Redshift, EasyTransaction, TextureHelper
      
      tex_helper: TextureHelper = TextureHelper()
      disp: maxon.Url = tex_helper.GetAssetUrl("file_fa9c42774dd05049")
      
      def HowToUse():
      
          material: c4d.BaseMaterial = Redshift.Material("MyMaterial")
      
          with EasyTransaction(material) as tr:
      
              tr.AddDisplacementTree(filepath = disp, shadername = "DISP")
      
              tr.InsertMaterial()
      
      if __name__ == '__main__':
          HowToUse()
      

      https://boghma.com
      https://github.com/DunHouGo

      DunhouD 1 Reply Last reply Reply Quote 2
      • DunhouD
        Dunhou @Dunhou
        last edited by

        Hi community!

        Here is a little example of how we modify aovs in Octane, find more examples in the top.

        Have fun with it😊

        Cheers~
        DunHou

        Result:

        a25ad801-72c0-4e10-9572-e4e20541d0e3-image.png

        Codes:

        import c4d
        import maxon
        import Renderer
        from Renderer import Octane
        from pprint import pprint
        
        # How to create and modify octane aovs
        def modify_octane_aov():
        
            # Get the doc host the aovs, in this case th active doc
            doc: c4d.documents.BaseDocument = c4d.documents.GetActiveDocument()
            # Set Octane AOVHelper instance
            aov_helper = Octane.AOV(doc)
            
            # Create a Octane aov item
            # the id can find from Renderer.constants.octane_id.py or in octane folder
            # If #name is None, defulat to type.
            diff_aov = aov_helper.create_aov_shader(aov_type = Octane.RNDAOV_DIFFUSE)
        
            # Add the DIFFUSE aov we just created to the Octane aov system
            aov_helper.add_aov(diff_aov)
            
            # Add some aovs
            aov_helper.add_aov(aov_helper.create_aov_shader(aov_type = Octane.RNDAOV_POST,aov_name = 'POST'))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_DIF_D))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_DIF_I))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_REFL_D))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_REFL_I))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_WIRE))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_OBJECT_LAYER_COLOR))
            aov_helper.add_aov(aov_helper.create_aov_shader(Octane.RNDAOV_VOLUME))
            
            # Remove last aov: volume
            aov_helper.remove_last_aov()
            
            # Remove specified aov: wire
            aov_helper.remove_aov_type(aov_type = Octane.RNDAOV_WIRE)
            
            # Add 2 custom aovs with id 1 and 2
            aov_helper.add_custom_aov(customID = 1)
            aov_helper.add_custom_aov(customID = 2)
            
            # Get the custom aov with id 2
            custom2 = aov_helper.get_custom_aov(customID = 2)
            if custom2:
                print(f'We find a Custom AOV with id 2 Named{custom2.GetName()}')
                
            # Print current aov info
            aov_helper.print_aov()
        
        
        if __name__ == '__main__':
            Renderer.ClearConsole()
            modify_octane_aov()
        

        https://boghma.com
        https://github.com/DunHouGo

        DunhouD 1 Reply Last reply Reply Quote 0
        • DunhouD
          Dunhou @Dunhou
          last edited by

          Hi community!

          Here is a little example of how we modify scene objects in Arnold, find more examples in the top.

          We want:

          • Add a Arnold Sky with hdr
          • Add a gobo light with a node-base gobo material, and a IES light
          • Add a cube and add a custom mask to the driver
          • Add a Scatter with custom instance shapes
          • Auto export proxy with a BaseObject and load back the ass file (need to save project first)

          Have fun with it😊

          Cheers~
          DunHou

          Results:

          63288895-1f52-49f3-8a3e-5a691c394d8f-image.png
          8cfd5b22-0bbe-42f5-b949-86aa3d19591a-image.png

          Codes:

          import c4d
          import maxon
          import Renderer
          from Renderer import Arnold, TextureHelper
          from pprint import pprint
          
          # Create a TextureHelper instance
          tex_helper: TextureHelper = TextureHelper()
          
          # How to create and modify arnold scene
          def modify_arnold_scene():
          
              # Get the doc host the scene, in this case th active doc
              doc: c4d.documents.BaseDocument = c4d.documents.GetActiveDocument()
              # Set arnold SceneHelper instance
              scene_helper = Arnold.Scene(doc)
              
              ### == Light == ###
              # Add a rig of hdr and rgb backdrop
              hdr_url: str =  tex_helper.GetAssetStr(maxon.Id("file_d21cf4cfdec8c636"))
              scene_helper.add_dome_rig(texture_path = hdr_url, rgb = c4d.Vector(0,0,0))
              
              # Add a light object and and some modify tags
              gobo_url: maxon.Url = tex_helper.GetAssetUrl("file_66b116a34a150e7e")
              gobo_light = scene_helper.add_gobo(texture_path = str(gobo_url), intensity=2, exposure=0)
              scene_helper.add_light_modifier(light = gobo_light, gsg_link = True, rand_color = True)
              
              # Add a IES light
              ies_url: str = tex_helper.GetAssetStr("file_6f300f2ba077da4a")
              ies = scene_helper.add_ies(texture_path = ies_url, intensity=1, exposure=0)
              
              ### == Tag == ###
              # Add a Cude object and an arnold tag with mask_name
              cube = c4d.BaseObject(c4d.Ocube)
              scene_helper.add_mask_tag(node=cube, mask_name='My Mask 01')
              doc.InsertObject(cube)
                  
              ### == Object == ###
              # Add a scatter obejct with some children and count 12345
              generate_object = c4d.BaseObject(c4d.Oplane)
              doc.InsertObject(generate_object)
              scatter_A = c4d.BaseObject(c4d.Oplatonic)
              scatter_B = c4d.BaseObject(c4d.Ooiltank)
              doc.InsertObject(scatter_A)
              doc.InsertObject(scatter_B)
              scatters: list[c4d.BaseObject] = [scatter_A, scatter_B]
              scene_helper.add_scatter(generator_node=generate_object, scatter_nodes=scatters, count=12345)
              
              # Add a object and set auto proxy
              the_object = c4d.BaseObject(c4d.Oplane)
              doc.InsertObject(the_object)
              the_object.SetName("Original Object")
              scene_helper.auto_proxy(nodes=the_object,remove_objects=False)
          
          if __name__ == '__main__':
              Renderer.ClearConsole()
              modify_arnold_scene()
              c4d.EventAdd()
          

          https://boghma.com
          https://github.com/DunHouGo

          DunhouD 1 Reply Last reply Reply Quote 0
          • DunhouD
            Dunhou @Dunhou
            last edited by Dunhou

            Hi community!

            Another little update, as we didn't have DataDescriptionDatabaseInterface as @ferdinand said in How can we get the default port of a GraphNode?

            I add a ConverterPorts to Renderer, we can use this to get the "default " port of a node until the DataDescriptionDatabaseInterface is valid in python.

            Note: It can only provide the str data of the port and it's not 100% rigorous

            Cheers~
            DunHou


            Result:

            ef6aaffd-aa4f-4def-9b4e-e626bda37c51-image.png

            Codes:

            import c4d
            from Renderer import Redshift,EasyTransaction,ClearConsole
            
            def ConvertTest():
            
                material: c4d.BaseMaterial = c4d.documents.GetActiveDocument().GetActiveMaterial()
            
                with EasyTransaction(material) as tr: 
            
                    nodes = tr.GetActiveNodes()
                    
                    for node in nodes:
                        print(f"Node: {tr.GetName(node)}")
                        print(f"Default Input: {tr.GetConvertInput(node)}")
                        print(f"Default Output: {tr.GetConvertOutput(node)}")
                        print("-"*10)
                    
            if __name__ == '__main__':
                ClearConsole()
                ConvertTest()
            

            https://boghma.com
            https://github.com/DunHouGo

            DunhouD 1 Reply Last reply Reply Quote 0
            • DunhouD
              Dunhou @Dunhou
              last edited by

              Hi community!

              I had add a basic support to V-Ray and Corona to fit the basic PBR usage, no Scene and AOV yet (AOV seems I can not get them in python, if someone knows where it stores, please let me know that).

              Cheers~
              DunHou

              https://boghma.com
              https://github.com/DunHouGo

              1 Reply Last reply Reply Quote 1
              • M
                m_adam
                last edited by

                Hi regarding Vray, I once wrote this plugin that have the duty to create ObjectId passes.
                I did not try it since age, but previously Vray AOV where stored within a branch on the Render Engine.

                I don't have vray installed currently, but I guess if you compile the C++ SDK, with the help of the C++ SDK Active Object Example it should be trivial to inspect a Vray scene and find these AOV.

                Cheers,
                Maxime

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                DunhouD 1 Reply Last reply Reply Quote 1
                • DunhouD
                  Dunhou @m_adam
                  last edited by Dunhou

                  Hi community!

                  Thanks for @m_adam prompt, I had add a AOV to Vray as same as other renderers, see a basic example here, hope it can help 😊

                  Cheer~
                  DunHou


                  Result:

                  3b1dfcb9-efb4-4dcc-a65f-a4800c3b9517-image.png

                  Code:

                  import c4d
                  import Renderer
                  from Renderer import Vray
                  
                  def modify_vray_aov():
                  
                      # Set Vray AOVHelper instance
                      doc = c4d.documents.GetActiveDocument()
                      vp: c4d.documents.BaseVideoPost = Renderer.GetVideoPost(doc, Renderer.ID_VRAY)    
                      aov_helper = Vray.AOV(vp)
                  
                      # Add the DIFFUSE aov
                      diff_aov = aov_helper.create_aov_shader(aov_type = Vray.VRAY_AOV_DIFFUSE)
                      aov_helper.add_aov(diff_aov)
                  
                      # Add some aovs
                      aov_helper.add_aov(aov_helper.create_aov_shader(aov_type = Vray.VRAY_AOV_BACKGROUND, aov_name = 'BG'))
                      aov_helper.add_aov(aov_helper.create_aov_shader(Vray.VRAY_AOV_SPECULAR))
                      aov_helper.add_aov(aov_helper.create_aov_shader(Vray.VRAY_AOV_REFLECTION))
                      aov_helper.add_aov(aov_helper.create_aov_shader(Vray.VRAY_AOV_SHADOW))
                      aov_helper.add_aov(aov_helper.create_aov_shader(Vray.VRAY_AOV_LIGHT_MIX))
                  
                      # Remove last aov
                      aov_helper.remove_last_aov()
                  
                      # Remove specified aov: diffuse
                      aov_helper.remove_aov_type(aov_type = Vray.VRAY_AOV_DIFFUSE[0])
                  
                      # Print current aov info
                      aov_helper.print_aov()
                  
                      c4d.EventAdd()
                  
                  if __name__ == '__main__':
                      Renderer.ClearConsole()
                      modify_vray_aov()
                  

                  https://boghma.com
                  https://github.com/DunHouGo

                  DunhouD 1 Reply Last reply Reply Quote 1
                  • DunhouD
                    Dunhou @Dunhou
                    last edited by

                    Hi again,

                    Also another Corona AOV example here .

                    Finally preliminarily implemented using this library to approximate the operation of the renderer in Cinema 4D .

                    The learning process was very enjoyable, hope you also have fun with it ✌

                    Cheers~
                    DunHou


                    Result:

                    3a357d30-a82d-4905-94ca-b914295cb296-image.png

                    Code:

                    import c4d
                    import Renderer
                    from Renderer import Corona
                    
                    def modify_corona_aov():
                    
                        # Get the doc host the aovs, in this case th active doc vp
                        doc: c4d.documents.BaseDocument = c4d.documents.GetActiveDocument()
                        vp: c4d.documents.BaseVideoPost = Renderer.GetVideoPost(doc, Renderer.ID_CORONA)
                        # Set Corona AOVHelper instance
                        aov_helper = Corona.AOV(vp)
                    
                        # turn on the mutipass
                        aov_helper.enable_mutipass(True)
                        
                        # Add the DIFFUSE aov
                        diff_aov = aov_helper.create_aov_shader(aov_type = Corona.CORONA_MULTIPASS_TYPE_ALBEDO)    
                        aov_helper.add_aov(diff_aov)
                    
                        # Add some aovs
                        aov_helper.add_aov(aov_helper.create_aov_shader(aov_type = Corona.CORONA_MULTIPASS_TYPE_EMISSION, aov_name = 'emmision aov'))
                        aov_helper.add_aov(aov_helper.create_aov_shader(Corona.CORONA_MULTIPASS_TYPE_REFLECT))
                        aov_helper.add_aov(aov_helper.create_aov_shader(Corona.CORONA_MULTIPASS_TYPE_REFRACT))
                        aov_helper.add_aov(aov_helper.create_aov_shader(Corona.CORONA_MULTIPASS_TYPE_TRANSLUCENCY))
                        aov_helper.add_aov(aov_helper.create_aov_shader(Corona.CORONA_MULTIPASS_TYPE_ZDEPTH))
                    
                        # Remove last aov: volume
                        aov_helper.remove_last_aov()
                    
                        # Remove specified aov: wire
                        aov_helper.remove_aov_type(aov_type = Corona.CORONA_MULTIPASS_TYPE_TRANSLUCENCY)
                    
                        # Print current aov info
                        aov_helper.print_aov()
                    
                        Corona.AovManager()
                    
                    if __name__ == '__main__':
                        Renderer.ClearConsole()
                        modify_aorona_aov()
                        c4d.EventAdd()
                    

                    https://boghma.com
                    https://github.com/DunHouGo

                    1 Reply Last reply Reply Quote 0
                    • DunhouD
                      Dunhou
                      last edited by

                      Hi community!

                      New Updates here :

                      • Fix some Octane and Corona functions (base on layer)
                      • Add MaterialMaker and PBRPackage

                      PBRPackage means a suite of pbr textures, like a stone texture pack form PolyHaven or Megascan, you can provide the folder and the name to get the slot they should be:

                      • we have a texture pack named Rock Stone 01
                      • this package had some textures in D:/myTextures ,like Rock Stone 01_albedo.jpg/Rock Stone 01_Normal.png/Rock Stone 01_disp.exr.
                      • we can provide the folder like D:/myTextures and its name like Rock Stone 01
                      • then we get textures in a dictionary
                      data = {"diffuse": Rock Stone 01_albedo.jpg,
                                    "normal": Rock Stone 01_Normal.jpg,
                                    "displacement": Rock Stone 01_disp.jpg,
                                    etc...
                      }
                      

                      Material Maker can easily add pbr materials from a package, and also you can use it with individuals textures.

                      But all of this build with this library, so only node materials on Redshift/Arnold/Vray, Octane and Corona is supported by thier own logics.

                      Cheers~
                      DunHou

                      https://boghma.com
                      https://github.com/DunHouGo

                      1 Reply Last reply Reply Quote 0
                      • DunhouD
                        Dunhou
                        last edited by

                        Hi community!

                        Add Basic CentiLeo Material support, also with ConvertPorts data, This a "new" GPU Renderer and in active development. I am very interested in it.

                        Not add AOV due to still being in the early stages of development, waiting for this.

                        Cheers~
                        DunHou

                        https://boghma.com
                        https://github.com/DunHouGo

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