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
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 );
}
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);
}
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.
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.
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();
}
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();
}
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()