Skip to content
On this page

Shading network

An alternate way to define a specific material channel is by using a shading network. If a shading network is set for a material channel, this will be used instead of the legacy layered texture system.

Material nodes are systems that are used to generate a color for each surface element on a model. Some nodes will solely be used to create colors from pre-defined values or from the sampling of textures. Some nodes are designed to modify the values generated by other nodes. The nodes that modify color values have one or multiple input slots.

Every node outputs the same type of RGBA data, so every node can be plugged into any input slot. If an input slot doesn't have a node plugged into it, the slot will evaluate to a default value. This value can be set for every node's specific slot.

A node may appear multiple times in the same node tree but may not be an ancestor to itself. The material node network is identified by the last node in the network, which is referred to as the exit node. When each surface element is evaluated (for casting/rendering etc.) the entire node tree will be traversed from the exit node.

To use a node network as a material, the exit node is assigned to a selected channel in the IMaterial object using SetShadingNetwork() for the IMaterial.

Node listing

  • ShadingTextureNode
    No input slots. Contains a texture name and a UV-set. The name set here is supposed to be a uniquely identifying name that is also present in the scenes texture table.

  • ShadingColorNode
    No input slots. Contains a color.

  • ShadingVertexColorNode
    No input slots. Contains an index to a vertex color.

  • ShadingInterpolateNode
    Three input slots. Will interpolate between the colors (pointwise) of slot0/slot1 using slot3.

  • ShadingClampNode
    Three input slots. Will clamp the color (pointwise) of slot0 using the slot1/slot2.

  • ShadingAddNode
    Two input slots. Will add the colors (pointwise) of slot0 and slot1.

  • ShadingSubtractNode
    Two input slots. Will subtract the color (pointwise) of slot0 with slot1.

  • ShadingMultiplyNode
    Two input slots. Will multiply the colors (pointwise) of slot0 and slot1.

  • ShadingDivideNode
    Two input slots. Will divide the color (pointwise) of slot0 with slot1.

  • ShadingNormalize3Node
    One input slot. Will normalize the color of slot0.

  • ShadingPowNode
    Two input slots. Will give slot0 (base) raised with slot1 (exponent).

  • ShadingSqrtNode
    One input slot. Will give the root of slot0.

  • ShadingSwizzlingNode
    Four input slots. Four output slots. Re-routes the input to the specified output.

  • ShadingDot3Node
    Two input slots. Returns the Dot of slot0 and slot1 (dot, dot, dot, 1.0f).

  • ShadingCross3Node
    Two input slots. Returns the Cross of slot0 and slot1 (cross.x, cross.y, cross.z, 1.0f).

  • ShadingCosNode
    One input slot. Returns Cos of the values of slot0.

  • ShadingSinNode
    One input slot. Returns Sin of the values of slot0.

  • ShadingMaxNode
    Two input slots. Returns the largest value of slot0 and slot1.

  • ShadingMinNode
    Two input slots. Returns the smallest value of slot0 and slot1.

  • ShadingEqualNode
    Two input slots. Returns 1.0f if value in slot0 equals the value in slot1, otherwise 0.0f.

  • ShadingNotEqualNode
    Two input slots. Returns 1.0f if value in slot0 does not equal the value in slot1, otherwise 0.0f.

  • ShadingGreaterThanNode
    Two input slots. Returns 1.0f if value in slot0 is greater than the value in slot1, otherwise 0.0f.

  • ShadingLessThanNode
    Two input slots. Returns 1.0f if value in slot0 is smaller than the value in slot1, otherwise 0.0f.

Example - Create and set shading network

cpp
spShadingNode CreateGroundMaterialNetwork()
{
    spTextureNode DirtMap = sg->CreateTextureNode();
    DirtMap->SetTextureLevel( 0 );
    DirtMap->SetTexturePath( "dirt.png" );
    spTextureNode NoiseMap = sg->CreateTextureNode();
    DirtMap->SetTextureLevel( 1 );
    DirtMap->SetTexturePath( "noise.png" );
    SpInterpolateNode Ground = sg->CreateInterpolateNode();
    Ground->SetInput( 0, DirtMap );
    Ground->SetDefaultParameter( 1, 0.45f, 0.32f, 0.04f );
    Ground->SetInput( 2, NoiseMap );
   
    // Return the exit node
    return spShadingNode( Ground );
}
void AddMaterialNodeNetworkToMaterial( spMaterial ground_material )
{
    // Create a material node network consisting of an arbitrary
    // amount of shading nodes
    spShadingNode exit_node = CreateGroundMaterialNetwork();
   
    // Assign the exit node of the material node network to the
    // diffuse channel in the ground_material
    ground_material->SetShadingNetwork( SG_MATERIAL_CHANNEL_DIFFUSE, exit_node );
}
csharp
spShadingNode CreateGroundMaterialNetwork()
{
    spShadingTextureNode DirtMap = sg.CreateShadingTextureNode();
    DirtMap.SetTextureLevel(0);
    DirtMap.SetTextureName("dirt");
    spShadingTextureNode NoiseMap = sg.CreateShadingTextureNode();
    DirtMap.SetTextureLevel(1);
    DirtMap.SetTextureName("noise");
    spShadingInterpolateNode Ground = sg.CreateShadingInterpolateNode();
    Ground.SetInput(0, DirtMap);
    Ground.SetDefaultParameter(1, 0.45f, 0.32f, 0.04f, 0.0f);
    Ground.SetInput(2, NoiseMap);

    // Return the exit node
    return Ground;
}
void AddMaterialNodeNetworkToMaterial(spMaterial ground_material)
{
    // Create a material node network consisting of an arbitrary
    // amount of shading nodes
    spShadingNode exit_node = CreateGroundMaterialNetwork();

    // Assign the exit node of the material node network to the
    // diffuse channel in the ground_material
    ground_material.SetShadingNetwork(Simplygon.Simplygon.SG_MATERIAL_CHANNEL_DIFFUSE, exit_node);
}
python
def CreateGroundMaterialNetwork():
    DirtMap = sg.CreateTextureNode()
    DirtMap.SetTextureLevel( 0 )
    DirtMap.SetTexturePath( "dirt.png" )
    NoiseMap = sg.CreateTextureNode()
    DirtMap.SetTextureLevel( 1 )
    DirtMap.SetTexturePath( "noise.png" )
    Ground = sg.CreateInterpolateNode()
    Ground.SetInput( 0, DirtMap )
    Ground.SetDefaultParameter( 1, 0.45, 0.32, 0.04 )
    Ground.SetInput( 2, NoiseMap )
    return Ground 

def AddMaterialNodeNetworkToMaterial( ground_material ):

    #  Create a material node network consisting of an arbitrary
    #  amount of shading nodes
    exit_node = CreateGroundMaterialNetwork()
   
    #  Assign the exit node of the material node network to the
    #  diffuse channel in the ground_material
    ground_material.SetShadingNetwork( Simplygon.SG_MATERIAL_CHANNEL_DIFFUSE, exit_node )

Node concept diagram

The following figure shows two textures nodes plugged into an interpolating node. The texture nodes don't have input slots, but they have settable paramaters.

Node concept

Generating HLSL/GLSL shader code from material nodes

When a material node network has been created and assigned to a channel of a material. Simplygon can generate a shader used to render the material.

cpp
void GenerateShaderCode( spMaterial island_material )
{
    // We create a shader data object
    spShaderData island_shader = sg->CreateShaderData();
    
	// We add the material to it
    island_shader->SetMaterial( island_material );
    
	// We tell the shader data object to traverse the material node tree
    // and gather the information needed to create a shader from the nodes.
    island_shader->GenerateShaderData();
    
    // Get the entire shader code for HLSL and GLSL.
    spString hlsl_code = island_shader->GetHLSLCode();
    spString glsl_vertex_code = island_shader->GetGLSLVertexCode();
    spString glsl_fragment_code = island_shader->GetGLSLFragmentCode();
}
csharp
void GenerateShaderCode(spMaterial island_material)
{
    // We create a shader data object
    spShaderGenerator island_shader = sg.CreateShaderGenerator();

    // We add the material to it
    island_shader.SetMaterial(island_material);

    // We tell the shader data object to traverse the material node tree
    // and gather the information needed to create a shader from the nodes.
    island_shader.GenerateShaderData();

    // Get the entire shader code for HLSL and GLSL.
    string hlsl_code = island_shader.GetHLSLCode();
    string glsl_vertex_code = island_shader.GetGLSLVertexCode();
    string glsl_fragment_code = island_shader.GetGLSLFragmentCode();
}
python
def GenerateShaderCode( island_material )
    # We create a shader data object
    island_shader = sg.CreateShaderGenerator()
	
    # We add the material to it
    island_shader.SetMaterial( island_material )
	
    # We tell the shader data object to traverse the material node tree
    # and gather the information needed to create a shader from the nodes.
    island_shader.GenerateShaderData()

    # Get the entire shader code for HLSL and GLSL.
    hlsl_code = island_shader.GetHLSLCode()
    glsl_vertex_code = island_shader.GetGLSLVertexCode()
    glsl_fragment_code = island_shader.GetGLSLFragmentCode()