Jump to content

Materials and Shaders with Python


Recommended Posts

Hi guys, I sincerely need your help,

I am trying to manipulate my materials with python...i want to select all my cinema 4d materials, and insert a Filter shader at the top of the color channel texture slot, and then set its lightness to -30%, but without loosing the existing content. Then, in case that the first shader in the texture channel was a bitmap shader, i want to copy the whole content of the slot with my filter on top, and paste it to the bump channel, where i desaturate the new filter shader i have just insert to -100%. Then copy the whole thing again to the reflections channel, change contrast, gamma...

I have menaged to select my cinema 4d materials, change some parameters, and even insert the shader where i want, but i loose everything that was there...

can you please guys help me?


Link to post
import c4d

def main():
    materials = doc.GetMaterials()
    for mat in materials:
        if mat.GetType() == 5703:
            filter_shader = c4d.BaseShader(1011128)
            texture = mat[c4d.MATERIAL_COLOR_SHADER].GetClone()
            filter_shader[c4d.SLA_FILTER_TEXTURE] = texture
            filter_shader[c4d.SLA_FILTER_LIGHTNESS] = 0.3
            doc.AddUndo(c4d.UNDOTYPE_CHANGE, mat)
            mat[c4d.MATERIAL_COLOR_SHADER] = filter_shader
            if texture.GetType() == 5833: # checks if the diffuse slot is an bitmap shader
                #check if bump channel is active and if not - activate
                if not mat[c4d.MATERIAL_USE_BUMP]:
                    mat[c4d.MATERIAL_USE_BUMP] = True
                bump_shader = filter_shader.GetClone()
                bump_shader[c4d.SLA_FILTER_SATURATION] = -1.0
                mat[c4d.MATERIAL_BUMP_SHADER] = bump_shader
                #check if reflectance is active and if not - activate
                if not mat[c4d.MATERIAL_USE_REFLECTION]:
                    mat[c4d.MATERIAL_USE_REFLECTION] = True
                refl_shader = filter_shader.GetClone()

                refl_shader[c4d.SLA_FILTER_HUE] = 0.0
                refl_shader[c4d.SLA_FILTER_SATURATION] = -1.0
                refl_shader[c4d.SLA_FILTER_LIGHTNESS] = 0.0
                refl_shader[c4d.SLA_FILTER_BRIGHNESS] = 0.0
                refl_shader[c4d.SLA_FILTER_CONTRAST] = 0.0
                refl_shader[c4d.SLA_FILTER_GAMMA] = 1.0

                mat[base+c4d.REFLECTION_LAYER_COLOR_TEXTURE] = refl_shader

if __name__=='__main__':

Cheers :)

Link to post

Thank you, thank you, and thank you....I cant find the words to express my gratitude...

I was missing the GetClone function...never thought about that...and now I understand that I have to insert every shader one by one... i mean first the texture variable that contains all the tree underneath, in the filter i have just created which is floating somewhere in the memory, ....and then the whole thing again in the color channel slot. Awesome!

I have noticed that you use the corresponding integer of the ID formula that describe the object (ex: 5833, instead of c4d.BaseShader.c4d.Xbitmap...(now i am not so sure if it's right to put BaseShader or BaseList2D??). Anyway, i was wondering if you know a way to get the description ID formula of something directly from the console, instead of searching on the python SDK web page....

thank you once again man....you really made my day!

Cheers! :)

Link to post

Hi Kalugin, I tested your script and it works (thank you again, for your help)...but it has a problem;

when the script runs and encounter a material that does not have any texture in the color texture slot, it stops and the rest of the materials remain the same as before. On the console it says: AttributeError: 'NoneType' object has no attribute 'GetClone'.

I think that I should post an "if statement" somewhere, telling him to continue if it finds nothing (Nonetype)...I will let you know, if I find out...

cheers :)



Link to post
  • 2 weeks later...

Hi Alex, I was just wondering if you know a way to extract the path of any texture file associated with a channel of a material.

I have realized that all I really need are the textures, but sometimes the shader tree of a given channel can be really messed up and complicated, so it would be awesome if I could only take the texture path used in that specific channel, (the bump one for example) and than load it in a new material, precisely a corona material... and if the texture is more than one, to load them under a cinema 4d layer shader... what do you think?

Thank you again for your time and help,


Link to post

That's more complicated. You will need a recursive function to dig in the shader structure and check for textures everywhere. Also you would need a different code for the different shaders as they have different slots and ids. Creating the layer shader should not be that hard. It can be done - in theory :).

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


We are dedicated Cinema 4D Community of friendly and passionate artists, hobbyists and developers. Feel free to join us to share your knowledge, your art and anything that might help Community to grow. We are providing guidance, free plugins and files, feedback, sponsorships and various discounts for our Contributors and much more. :cowboypistol:

  • Create New...

Copyright C4D Cafe © 2021 Powered by Invision Community