How to Create and Populate a Layer Shader?
-
thanks, i understand that by inserting a an already set up shader (when copied LayerShader from another material) all its shader hierarchy gets inserted as well and does not need to be manually processed. still i don't understand to set up a fresh LayerShader.
if I manually create a LayerShader holding a sub shaders, I get exactly what you described above
Material- LayerShader
-
- Sub Shader <-- child !
But when I use this code example to set up a LayerShader, i get :
https://developers.maxon.net/forum/topic/13469/python-layershader-addlayer-defining-shader
Material- LayerShader
- Sub Shader (gradient) <-- not a child !
mat.InsertShader(gradient_shader, sha_xlayer)
inserts gradient_shader after, not under sha_xlayer (as mentioned in the docs)
but this would make the example incorrect, not?
wouldn't copying such a LayerShader to another material result in problems?
how do you insert a shader as child ?test code :
set up a LayerShader according to the example mentioned
import c4d def main(): mat = c4d.Material(c4d.Mbase) doc = c4d.documents.GetActiveDocument() doc.InsertMaterial(mat) xlayer = c4d.BaseShader(c4d.Xlayer) mat.InsertShader(xlayer) mat[c4d.MATERIAL_COLOR_SHADER] = xlayer hsl = xlayer.AddLayer(c4d.TypeHSL) layer = xlayer.AddLayer(c4d.TypeShader) gradient = c4d.BaseShader(c4d.Xgradient) mat.InsertShader(gradient, xlayer) layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_LINK, gradient) c4d.EventAdd() if __name__=='__main__': main()
print complete shader tree of selected or first material
import c4d def main(): li = doc.GetActiveMaterials() if not li: li = doc.GetMaterials() printNodeTree(li[0]) def printNodeTree(node, indent='+'): if isinstance(node, c4d.BaseMaterial): print(node) node = node.GetFirstShader() while node: print(indent,node) printNodeTree(node.GetDown(), indent+'+') node = node.GetNext() if __name__=='__main__': main()
-
Thank you for reaching out to us. I have forked this question from Copy LayerShader to a New Material, as it is a new question.
The code @m_adam did provide in the thread you are referring to, is unfortunately not correct and likely the cause of the crashes you encountered. Also, your function
printNodeTree
is ill suited for what you are using it for, as you must take branching information into account. I have provided a rough overview over branches in Copy LayerShader to a New Material.Below you will find a code example for instantiating and layer shader and populating it with layers. While writing the example I found out that the
LayerShader
documentation both for Python and C++ contains problems ranging from errors to inconveniences. The code example serves as intermediate solution until we fix the docs.The caveat is here that a shader contained in a
LayerShader
must be inserted into the layer shader, and not the material the layer shader itself is part of. A layer shader is also an exception, as it does not insert its child shaders in the shader branch of the layer shader, but as direct children. I.e., it is notlayerShader.InsertShader(someChild)
butsomeChild.InsertUnder(layerShader)
.Cheers,
FerdinandThe code:
"""Demonstrates how to instantiate, populate, and modify a layer shader. Run the example as a Script Manger script, it will insert a new material with a layer shader in the color channel into the active document. """ from typing import Optional import c4d doc: c4d.documents.BaseDocument # The active document op: Optional[c4d.BaseObject] # The active object, None if unselected def CreateLayerShaderSetup() -> c4d.LayerShader: """Instantiates and populates a layer shader. """ # Instantiate the shader. layerShader = c4d.LayerShader() # We add multiple layers, the layer types are documented in LayerShaderLayer.GetType(). The # method LayerShader.AddLayer()also has a return value, it returns a LayerShaderLayer, other # than documented in the Python docs. # When not defining an insertion point, the second argument to #AddLayer(), the order of the # AddLayer() calls matters. layer0: c4d.LayerShaderLayer = layerShader.AddLayer(c4d.TypeShader) layer1: c4d.LayerShaderLayer = layerShader.AddLayer(c4d.TypeShader) layerHsl: c4d.LayerShaderLayer = layerShader.AddLayer(c4d.TypeHSL) # Set some of the parameters of the layers. The documentation for Get/SetParameter of # LayerShader is unfortunately hardly useable for both Python (which just points to the C++ # docs) and C++. I have pasted the symbols at the bottom of this file as a working solution # until we fix the C++ documentation and update the Python one. I would also recommend using # the VS Code bindings we provide in the meantime, due to their auto-complete feature. # Set the lightness of the HSL layer to -50%. layerHsl.SetParameter(c4d.LAYER_S_PARAM_HSL_LIGHTNESS, -.5) # Create a noise shader and link it in the first shader layer. noiseShader = c4d.BaseList2D(c4d.Xnoise) # The shader linked by the layer shader must be parented to the layer shader, not the material. # It also must be indeed parented to the shader and not inserted under its shader branch. noiseShader.InsertUnder(layerShader) layer0.SetParameter(c4d.LAYER_S_PARAM_SHADER_LINK, noiseShader) # Do the same for the second shader layer, and this time also adjust the layer strength and # set the layer mode. noiseShader = c4d.BaseList2D(c4d.Xnoise) noiseShader[c4d.SLA_NOISE_GLOBAL_SCALE] = .25 noiseShader.InsertUnder(layerShader) layer1.SetParameter(c4d.LAYER_S_PARAM_SHADER_LINK, noiseShader) layer1.SetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND, 0.5) layer1.SetParameter(c4d.LAYER_S_PARAM_SHADER_MODE, c4d.BlendMultiply) # Return the layer shader. return layerShader def main() -> None: """ """ # Create a new material and layer shader setup. material = c4d.BaseList2D(c4d.Mmaterial) shader = CreateLayerShaderSetup() # Insert the shader into the material, and link it in the color channel. material.InsertShader(shader) material[c4d.MATERIAL_COLOR_SHADER] = shader # Insert the material and push an update event to Cinema 4D. doc.InsertMaterial(material) doc.SetActiveMaterial(material) c4d.EventAdd() if __name__ == '__main__': main() """ The layer shader symbols are: /// @addtogroup BlendMode /// @ingroup group_enumeration /// @{ /// The blend modes for the layers of LayerShader. enum BlendMode { BlendNormal = 1, ///< Normal. BlendMultiply, ///< Multiply. BlendScreen, ///< Screen. BlendOverlay, ///< Overlay. BlendHardLight, ///< Hard light. BlendSoftLight, ///< Soft light. BlendDodge, ///< Dodge. BlendBurn, ///< Burn. BlendDarken, ///< Darken. BlendLighten, ///< Lighten. BlendAdd, ///< Add. BlendSubtract, ///< Subtract. BlendDifference, ///< Difference. BlendExclusion, ///< Exclusion. BlendHue, ///< Hue. BlendSat, ///< Saturation. BlendColor, ///< Color. BlendLuminance, ///< Luminance. BlendLevr, ///< Levr. BlendAlphaMask ///< Alpha mask. }; /// @} /// @addtogroup LAYER_S_PARAM_ALL /// @ingroup group_containerid /// @{ /// Common parameters for all layer types. #define LAYER_S_PARAM_ALL_ACTIVE 1000 ///< ::Bool Active. #define LAYER_S_PARAM_ALL_SELECTED 1001 ///< ::Bool Selected. #define LAYER_S_PARAM_ALL_FLAGS 1002 ///< ::Int32 Flags: @enumerateEnum{LayerFlags} /// @} /// @addtogroup LAYER_S_PARAM_FOLDER /// @ingroup group_containerid /// @{ /// Parameters for @ref TypeFolder layers. #define LAYER_S_PARAM_FOLDER_MODE 2000 ///< ::Int32 Blend mode: @enumerateEnum{BlendMode} #define LAYER_S_PARAM_FOLDER_BLEND 2001 ///< ::Float Blend parameter. #define LAYER_S_PARAM_FOLDER_OPEN 2002 ///< ::Bool Folder is open. #define LAYER_S_PARAM_FOLDER_FIRSTCHILD 2003 ///< @c void* Pointer to the first child LayerShaderLayer, read-only. /// @} /// @addtogroup LAYER_S_PARAM_SHADER /// @ingroup group_containerid /// @{ /// Parameters for @ref TypeShader layers. #define LAYER_S_PARAM_SHADER_MODE 2000 ///< ::Int32 Blend mode: @enumerateEnum{BlendMode} #define LAYER_S_PARAM_SHADER_BLEND 2001 ///< ::Float Blend parameter. #define LAYER_S_PARAM_SHADER_LINK 2002 ///< @c void* Pointer to a BaseLink that contains the shader, read-only. /// @} /// @addtogroup LAYER_S_PARAM_BC /// @ingroup group_containerid /// @{ /// Parameters for @ref TypeBrightnessContrast layers. #define LAYER_S_PARAM_BC_BRIGHTNESS 2000 ///< ::Float Brightness. #define LAYER_S_PARAM_BC_CONTRAST 2001 ///< ::Float Contrast. #define LAYER_S_PARAM_BC_GAMMA 2002 ///< ::Float Gamma. /// @} /// @addtogroup LAYER_S_PARAM_HSL /// @ingroup group_containerid /// @{ /// Parameters for @ref TypeHSL layers. #define LAYER_S_PARAM_HSL_HUE 2000 ///< ::Float Hue. #define LAYER_S_PARAM_HSL_SATURATION 2001 ///< ::Float Saturation. #define LAYER_S_PARAM_HSL_LIGHTNESS 2002 ///< ::Float Lightness. #define LAYER_S_PARAM_HSL_COLORIZE 2003 ///< ::Int32 Colorize. /// @} /// @addtogroup LAYER_S_PARAM_POSTER /// @ingroup group_containerid /// @{ /// Parameters for @ref TypePosterize layers. #define LAYER_S_PARAM_POSTER_LEVELS 2000 ///< ::Int32 Poster levels. #define LAYER_S_PARAM_POSTER_WIDTH 2001 ///< ::Float Poster width. /// @} /// @addtogroup LAYER_S_PARAM_COLORIZE /// @ingroup group_containerid /// @{ /// Parameters for @ref TypeColorize layers. #define LAYER_S_PARAM_COLORIZE_INPUT 2000 ///< ::Int32 @em [0..6] Input. (See dialog.) #define LAYER_S_PARAM_COLORIZE_GRADIENT 2001 ///< Gradient Colorization gradient. #define LAYER_S_PARAM_COLORIZE_OPEN 2002 ///< ::Bool Full settings. #define LAYER_S_PARAM_COLORIZE_CYCLE 2003 ///< ::Bool Cycle. /// @} /// @addtogroup LAYER_S_PARAM_CLAMP /// @ingroup group_containerid /// @{ /// Parameters for @ref TypeClamp layers. #define LAYER_S_PARAM_CLAMP_LOW_CLIP 2000 ///< ::Float Clamp low clip. #define LAYER_S_PARAM_CLAMP_HIGH_CLIP 2001 ///< ::Float Clamp high clip. /// @} /// @addtogroup LAYER_S_PARAM_CLIP /// @ingroup group_containerid /// @{ // Parameters for @ref TypeClip layers. #define LAYER_S_PARAM_CLIP_LOW_CLIP 2000 ///< ::Float Low clipping. #define LAYER_S_PARAM_CLIP_HIGH_CLIP 2001 ///< ::Float High clipping. /// @} /// @addtogroup LAYER_S_PARAM_DISTORT /// @ingroup group_containerid /// @{ // Parameters for @ref TypeDistorter layers. #define LAYER_S_PARAM_DISTORT_NOISE 2000 ///< ::Int32 Noise type. (See dialog.) #define LAYER_S_PARAM_DISTORT_STRENGTH 2001 ///< ::Float Strength. #define LAYER_S_PARAM_DISTORT_OCTACES 2002 ///< ::Float Octaves. #define LAYER_S_PARAM_DISTORT_TIME_SCALE 2003 ///< ::Float Time scale. #define LAYER_S_PARAM_DISTORT_NOISE_SCALE 2004 ///< ::Float Noise scale. #define LAYER_S_PARAM_DISTORT_3D_NOISE 2005 ///< ::Bool 3D noise. #define LAYER_S_PARAM_DISTORT_WRAP 2006 ///< ::Int32 @em [0..3] Wrapping. (See dialog.) /// @} /// @addtogroup LAYER_S_PARAM_TRANS /// @ingroup group_containerid /// @{ // Parameters for @ref TypeTransform layers. #define LAYER_S_PARAM_TRANS_ANGLE 2000 ///< ::Float Angle. #define LAYER_S_PARAM_TRANS_MIRROR 2001 ///< ::Bool Mirror. #define LAYER_S_PARAM_TRANS_FLIP 2002 ///< ::Bool Flip. #define LAYER_S_PARAM_TRANS_SCALE 2003 ///< ::Vector Scale. #define LAYER_S_PARAM_TRANS_MOVE 2004 ///< ::Vector Move. /// @} """
-
@ferdinand
hey ferdinand , thanks for all of this information !
i also noticed that definitions are missing in the python SDK
(specifically the BlendModes) -
-