Unsolved Redshift Standard Material base Properties


I am trying to insert the full_path into "Load texture..." into Redshift Standard Material base color but all I got so far is this code. Could you help me solve this?

full_path = os.path.join(folder_path, file)

rsNodeSpaceID: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.class.nodespace")
textureNodeID: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
textureNodePortID: maxon.String = "com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0"
textureNodePathPortID: maxon.String = "path"textureColorOutPortID: maxon.String = "com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor"

mat: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial)
nodeMaterial: c4d.NodeMaterial = mat.GetNodeMaterialReference()
graph: maxon.GraphModelRef = nodeMaterial.CreateDefaultGraph(rsNodeSpaceID)


result: list[maxon.GraphNode] = []
maxon.GraphModelHelper.FindNodesByAssetId(graph, outputNodeID, True, result)

outputNode: maxon.GraphNode = result[0]

with graph.BeginTransaction() as transaction:
	textureNode: maxon.GraphNode = graph.AddChild(maxon.Id(), textureNodeID)
	pathPort: maxon.GraphNode = textureNode.GetInputs().FindChild(textureNodePortID).FindChild(textureNodePathPortID)
	textureColorOutPort: maxon.GraphNode = textureNode.GetOutputs().FindChild(textureColorOutPortID)
	colorInputPortInOutputNode : maxon.GraphNode = outputNode.GetInputs().FindChild(colorInputPortInOutputNodeId)


Hi @simonator420 ,

You should get the base color port( a maxon.GraphNode ), and connect with a Texture node ( also a maxon.GraphNode ), the texture path is also a port in Texture node, just set it's value is what you need,
I have a little example here which used my api helper renderEngine, I think it is easy to use and less code for general task. but it should be pointed out that use Maxon python sdk is more customized.


import c4d,maxon
from importlib import reload
from renderEngine.redshift import redshift_helper as rs
    from redshift_id import *
    from renderEngine.redshift.redshift_id import *
from renderEngine import node_helper

def AddandModify(name):
    redshiftMaterial =  rs.MaterialHelper.CreateStandardSurface(name)

    # modification has to be done within a transaction
    with rs.RSMaterialTransaction(redshiftMaterial) as transaction:

        # Find brdf node (in this case : standard surface)
        standard_surface = redshiftMaterial.helper.GetRootBRDF()

        # Change a shader name
        redshiftMaterial.helper.SetName(standard_surface,'My BRDF Shader')

        # TexPath
        tex_helper = node_helper.TextureHelper()
        url: maxon.Url = tex_helper.GetAssetStr(maxon.Id("file_5b6a5fe03176444c"))
        tar = redshiftMaterial.helper.GetPort(standard_surface,'com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color')

        # Add a texture to base color
        redshiftMaterial.AddTexture(shadername = 'My texture', filepath = url, raw = True, target_port = tar)
    return redshiftMaterial.material

if __name__ == '__main__':

Hey @simonator420,

Thank you for reaching out to us. And thank you @Dunhou for providing a solution. You should however be aware that Dunhou's solution requires his proprietary library as he states below. I think you should give it a spin because it is quite useful.

When you must remain within the bounds of the Cinema 4D standard library, find an example for how to do that below.


PS: I have added the example below to the code examples of the upcoming release alongside the standard renderer example.



#coding: utf-8
"""Demonstrates setting up a Redshift node material composed out of multiple nodes.

Creates a new node material with a graph in the Redshift material space, containing two texture 
nodes and a mix node, in addition to the default core material and material node of the material.

    * Creating a node material and adding a graph
    * Adding nodes to a graph
    * Setting the value of ports without wires
    * Connecting ports with a wires
    * (Asset API): Using texture assets in a node graph

__author__ = "Ferdinand Hoppe"
__copyright__ = "Copyright (C) 2023 MAXON Computer GmbH"
__date__ = "01/09/2023"
__license__ = "Apache-2.0 License"
__version__ = "2023.2.0"

import c4d
import maxon

doc: c4d.documents.BaseDocument # The active document.

def main() -> None:
    """Runs the example.
    # The asset URLs for the "RustPaint0291_M.jpg" and "Sketch (HR basic026).jpg" texture assets in 
    # "tex/Surfaces/Dirt Scratches & Smudges/". These could also be replaced with local texture URLs,
    # e.g., "file:///c:/textures/stone.jpg". These IDs can be discovered with the #-button in the info
    # area of the Asset Browser.
    urlTexRust: maxon.Url = maxon.Url(r"asset:///file_edb3eb584c0d905c")
    urlTexSketch: maxon.Url = maxon.Url(r"asset:///file_3b194acc5a745a2c")

    # The node asset IDs for the two node types to be added in the example; the texture node and the
    # mix node. These and all other node IDs can be discovered in the node info overlay in the 
    # bottom left corner of the Node Editor. Open the Cinema 4D preferences by pressing CTRL/CMD + E
    # and enable Node Editor -> Ids in order to see node and port IDs in the Node Editor.
    idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
    idMixNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolormix")
    idCoreMaterialNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.material")

    # Instantiate a material, get its node material and the graph for the RS material space.
    material: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial)
    if not material:
        raise MemoryError(f"{material = }")

    nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference()
    graph: maxon.GraphModelRef = nodeMaterial.AddGraph(
    if graph.IsNullValue():
        raise RuntimeError("Could not add RS graph to material.")


    # Attempt to find the core material node contained in the default graph setup.
    result: list[maxon.GraphNode] = []
    maxon.GraphModelHelper.FindNodesByAssetId(graph, idCoreMaterialNode, True, result)
    if len(result) < 1:
        raise RuntimeError("Could not find standard node in material.")
    standardNode: maxon.GraphNode = result[0]

    # Start modifying the graph by opening a transaction. Node graphs follow a database like 
    # transaction model where all changes are only finally applied once a transaction is committed.
    with graph.BeginTransaction() as transaction:
        # Add two texture nodes and a blend node to the graph.
        rustTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
        sketchTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
        mixNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idMixNode)

        # Set the default value of the 'Mix Amount' port, i.e., the value the port has when no 
        # wire is connected to it. This is equivalent to the user setting the value to "0.5" in 
        # the Attribute Manager.
        mixAmount: maxon.GraphNode = mixNode.GetInputs().FindChild(

        # Set the path sub ports of the 'File' ports of the two image nodes to the texture URLs 
        # established above. Other than for the standard node space image node, the texture is 
        # expressed as a port bundle, i.e., a port which holds other ports. The texture of a texture
        # node is expressed as the "File" port, of which "Path", the URL, is only one of the possible
        # sub-ports to set.
        pathRustPort: maxon.GraphNode = rustTexNode.GetInputs().FindChild(
        pathSketchPort: maxon.GraphNode = sketchTexNode.GetInputs().FindChild(

        # Get the color output ports of the two texture nodes and the color blend node.
        rustTexColorOutPort: maxon.GraphNode = rustTexNode.GetOutputs().FindChild(
        sketchTexColorOutPort: maxon.GraphNode = sketchTexNode.GetOutputs().FindChild(
        mixColorOutPort: maxon.GraphNode = mixNode.GetOutputs().FindChild(

        # Get the fore- and background port of the blend node and the color port of the BSDF node.
        mixInput1Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
        mixInput2Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
        coreDiffusePort: maxon.GraphNode = standardNode.GetInputs().FindChild(

        # Wire up the two texture nodes to the blend node and the blend node to the BSDF node.
        rustTexColorOutPort.Connect(mixInput1Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
        sketchTexColorOutPort.Connect(mixInput2Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
        mixColorOutPort.Connect(coreDiffusePort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)

        # Finish the transaction to apply the changes to the graph.

    # Insert the material into the document and push an update event.
if __name__ == "__main__":

MAXON SDK Specialist