ShaderNode is already defined

Hello,

so here is a simple example of duplicate shadernode names causing an error
condition is NormalsMap texture being present ot not

MaterialDef Simple {
    MaterialParameters {
        Texture2D NormalsMap
    }
    Technique {
        Defines {
        }
        WorldParameters {
        }
        VertexShaderNodes {
            ShaderNode NormalsMapVert {
                Definition : NormalsMapVert : Shaders/NormalsMap/NormalsMapVert.j3sn
                Condition : NormalsMap
                InputMappings {
                }
                OutputMappings {
                }
            }
            ShaderNode NormalsMapVert {
                Definition : NormalsMapVert : Shaders/NormalsMap/NormalsMapVert.j3sn
                Condition : !NormalsMap
                InputMappings {
                }
                OutputMappings {
                }
            }
        }
}
Caused by: com.jme3.material.plugins.MatParseException: Error On line 19 : ShaderNode NormalsMapVert
->ShaderNode NormalsMapVert is already defined

bug? not supported? let me know :smile:

thanks

[edit : maybe CSS should be changed cos light gray on dark gray ā€¦ need a good pair of googles]

Well thatā€™s intended.You canā€™t have 2 shader nodes with the same name.
Note that the node name can be different from the definition name.
So this is a valid code :

MaterialDef Simple {
    MaterialParameters {
        Texture2D NormalsMap
    }
    Technique {
        Defines {
        }
        WorldParameters {
        }
        VertexShaderNodes {
            ShaderNode NormalsMapVert1 {
                Definition : NormalsMapVert : Shaders/NormalsMap/NormalsMapVert.j3sn
                Condition : NormalsMap
                InputMappings {
                }
                OutputMappings {
                }
            }
            ShaderNode NormalsMapVert2 {
                Definition : NormalsMapVert : Shaders/NormalsMap/NormalsMapVert.j3sn
                Condition : !NormalsMap
                InputMappings {
                }
                OutputMappings {
                }
            }
        }
}

but if I have another node taking different parameters input (from either NormalsMapVert1 or NormalsMapVert2), it is going to bedefined twice too

If I want another texture map condition, I get 4 definitions, and so one and so forth, that spoils the whole advantage of using nodes

I am having the issue right now, every time there is a new case, I have to create a complete different material definition
I tried using #ifdef branches on input variables but it does not work

[edit : just found out that I could not use an already defined node name even in a different techniqueā€¦come onā€¦]

gonna have to give up on shader nodes

it seems definitions from the first technique appear in another technique for the same materials, then causing undefined variable errorsā€¦what a mess

so far shader nodes is more something I fight against intead of something helping in any way

below, one can see that itā€™s like a whole shader has been created from two diferent techniques

WARNING: Bad compile of:
1    #version 150 core
2    
3    uniform vec3 m_LightPosition;
4    uniform mat3 g_NormalMatrix;
5    uniform mat4 g_ViewMatrix;
6    uniform mat4 g_WorldViewMatrix;
7    uniform mat4 g_WorldMatrix;
8    uniform vec3 g_CameraPosition;
9    uniform mat4 g_WorldViewProjectionMatrix;
10    
11    in vec3 inNormal;
12    in vec4 inTangent;
13    in vec2 inTexCoord;
14    in vec4 inPosition;
15    
16    out vec3 NormalsMapVert_modelPosition;
17    out vec2 MetalVert_texCoord;
18    out vec4 NormalsMapVert_lightDir;
19    out vec3 NormalsMapVert_eyeVec;
20    out vec4 NormalsMapVert_debug;
21    out vec4 NormalsMapVert_v;
22    out vec3 NormalsMapVert_normal;
23    
24    uniform vec4 g_LightPosition; // hack
25    uniform vec4 g_LightColor; // hack
26    
27    // this funciton does some math tricks to compute the light dirrection and attenuation. 
28    // Attenuation just resolves to 0 if it's a directional light or a spot light.
29    // Then in the lighting.frag, we compute the spotfalloff for the spot light. 
30    // The angle cosines are packed into the 4th channel of the lightDirection. 
31    // The spot falloff also resolves to 0 for a directional light.
32    
33    void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
34        // 0 = Directional, 1 = Point, 2 = Spot
35        float posLight = step(0.5, color.w);    //Returns 0.0 if w < 0.5, otherwise it returns 1.0.
36        // sign : Returns 1.0 if x > 0, 0.0 if x = 0, or ā€“1.0 if x < 0.
37        vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
38        vec3 lightVec = tempVec;  
39        #ifdef ATTENUATION
40         float dist = length(tempVec);
41         lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
42         lightDir.xyz = tempVec / vec3(dist);
43        #else
44         lightDir = vec4(normalize(tempVec), 1.0);
45        #endif
46    }
47    
48    
49    
50    void main(){
51        vec4 Global_position = inPosition;
52    
53        //NormalsMapVert : Begin
54        vec3 NormalsMapVert_normalIn = inNormal;
55        vec4 NormalsMapVert_tangentIn = inTangent;
56        NormalsMapVert_modelPosition = Global_position.xyz;
57    
58        NormalsMapVert_normal = normalize(g_NormalMatrix * NormalsMapVert_normalIn); 
59        vec3 tangent = normalize(g_NormalMatrix * NormalsMapVert_tangentIn.xyz);
60        vec3 binormal = cross(NormalsMapVert_normal, tangent);
61    
62        //tbnMat matrix (view space to tangent space)
63        // The multiplication of the binormal is because some binormals need to be inverted depending on the triangle.
64        mat3 tbnMat = mat3(tangent, binormal * NormalsMapVert_tangentIn.w, NormalsMapVert_normal);
65    
66        // Get the position in eye coordinates
67        NormalsMapVert_v = g_WorldViewMatrix * vec4(NormalsMapVert_modelPosition,1.0);
68    
69        //vec4 _lightColor=vec4(1,1,1,1);
70        //vec4 _lightPosition=vec4(m_LightPosition,1);
71        vec4 _lightColor=g_LightColor;
72        vec4 _lightPosition=g_LightPosition;
73    
74        // light pos (world->view)
75        vec4 vLightPosition=vec4(g_ViewMatrix*vec4(_lightPosition.xyz,clamp(_lightColor.w,0.0,1.0)));
76        vLightPosition.w=_lightColor.w;
77        
78        lightComputeDir(NormalsMapVert_v.xyz, _lightColor, vLightPosition, NormalsMapVert_lightDir);
79    
80        //we actually need to mult by the invert the matrix, to go from tangent space to view space
81        //with a normalized rotation matrix one can actually just transpose it instead of inverting it. 
82        //=> mat * vec = vec * transpose(mat)
83        NormalsMapVert_lightDir = vec4(NormalsMapVert_lightDir.xyz*tbnMat,1);
84        NormalsMapVert_eyeVec = normalize(-NormalsMapVert_v.xyz)*tbnMat;
85    
86        //NormalsMapVert : End
87    
88        //MetalVert : Begin
89        vec3 MetalVert_modelPosition = Global_position.xyz;
90        MetalVert_texCoord = inTexCoord;
91        vec4 MetalVert_projPosition;
92    
93        MetalVert_projPosition = g_WorldViewProjectionMatrix * vec4(MetalVert_modelPosition, 1.0); //g_WorldViewProjectionMatrix=gl_ModelViewProjectionMatrix
94        Global_position = MetalVert_projPosition;
95        //MetalVert : End
96    
97        //MetalVertGlow : Begin
98        vec3 MetalVertGlow_modelPosition = Global_position.xyz;
99        MetalVertGlow_texCoord = inTexCoord;
100        vec4 MetalVertGlow_projPosition;
101    
102        MetalVertGlow_projPosition = g_WorldViewProjectionMatrix * vec4(MetalVertGlow_modelPosition, 1.0); //g_WorldViewProjectionMatrix=gl_ModelViewProjectionMatrix
103        Global_position = MetalVertGlow_projPosition;
104        //MetalVertGlow : End
105        gl_Position = Global_position;
106    }

avr. 13, 2015 6:34:34 PM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
com.jme3.renderer.RendererException: compile error in:ShaderSource[name=Default.vert, defines, type=Vertex, language=GLSL150] error:0(99) : error C1008: undefined variable "MetalVertGlow_texCoord"
MaterialDef Simple {
    MaterialParameters {
        Texture2D GlowMap
        Texture2D DiffuseMap
        Texture2D ReflectionMap
        Texture2D NormalsMap
        TextureCubeMap RefractionMap

        Vector3 LightPosition

        Color SceneAmbient
        Color Ambient
        Color LightAmbient
        Color LightDiffuse
        Color Specular
        Color LightSpecular
        Float Shininess
        Boolean Blinn
        Float ReflectionAmount
        Vector3 Time
        Vector3 NoiseScale
        Int NoiseOctaves
        Float TransitionPercent
        Float GlobalAlpha
    }
    Technique {
        LightMode MultiPass
        Defines {
        }
        WorldParameters {
            WorldViewProjectionMatrix
            NormalMatrix
            WorldViewMatrix
            WorldMatrix
            ViewMatrix
            CameraPosition
        }
        VertexShaderNodes {

            ShaderNode NormalsMapVert {
                Definition : NormalsMapVert : Shaders/NormalsMap/NormalsMapVert.j3sn
                //Condition : NormalsMap
                InputMappings {
                    lightPosition = MatParam.LightPosition
                    normalIn = Attr.inNormal
                    tangentIn = Attr.inTangent
                    modelPosition = Global.position.xyz
                    normalMatrix = WorldParam.NormalMatrix
                    viewMatrix= WorldParam.ViewMatrix
                    worldViewMatrix = WorldParam.WorldViewMatrix
                    worldMatrix=WorldParam.WorldMatrix
                    cameraPosition=WorldParam.CameraPosition  
                }
                OutputMappings {
                    // normal, lightDir, eyeVec
                }
            }
            ShaderNode MetalVert {
                Definition : MetalVert : Shaders/Metal/MetalVert.j3sn
                InputMappings {
                    worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
                    modelPosition = Global.position.xyz
                    texCoord = Attr.inTexCoord
                }
                OutputMappings {
                    Global.position = projPosition
                }
            }
        }
        FragmentShaderNodes {
            ShaderNode Simplex3GrayFrag {
                Definition : Simplex3GrayFrag : Shaders/Simplex/Simplex3GrayFrag.j3sn
                InputMappings {
                    texCoord = NormalsMapVert.modelPosition.xyz
                    time = MatParam.Time
                    scale = MatParam.NoiseScale
                    octaves = MatParam.NoiseOctaves
                }
            }
            ShaderNode PrePhongTransientFragNormals {
                Definition : PrePhongTransientFrag : Shaders/NormalsMap/PrePhongTransientFrag.j3sn
                //Condition : NormalsMap
                InputMappings {
                    simplexColor = Simplex3GrayFrag.simplexColor
                    transitionPercent = MatParam.TransitionPercent
                    texCoord = MetalVert.texCoord
                    normalsMap = MatParam.NormalsMap
                    lightDirIn = NormalsMapVert.lightDir
                    eyeVecIn = NormalsMapVert.eyeVec
                }
            }
            ShaderNode PhongFragNormals {
                Definition : PhongFrag : Shaders/Phong/PhongFrag.j3sn
                //Condition : NormalsMap
                InputMappings {
                    normal = PrePhongTransientFragNormals.normal
                    lightDir = PrePhongTransientFragNormals.lightDir
                    eyeVec = PrePhongTransientFragNormals.eyeVec
                    blinn = MatParam.Blinn
                    sceneAmbient = MatParam.SceneAmbient
                    ambient = MatParam.Ambient
                    diffuseMap = MatParam.DiffuseMap
                    specular = MatParam.Specular
                    shininess = MatParam.Shininess
                    lightAmbient = MatParam.LightAmbient
                    lightDiffuse = MatParam.LightDiffuse
                    lightSpecular = MatParam.LightSpecular
                    texCoord = MetalVert.texCoord
                    debug=NormalsMapVert.debug
                }
            }
            ShaderNode ReflectionFrag {
                Definition : ReflectionFrag : Shaders/Reflection/ReflectionFrag.j3sn
                InputMappings {
                    v = NormalsMapVert.v
                    normal = NormalsMapVert.normal
                    lambertTerm = PhongFragNormals.lambertTerm
                    reflectionMap = MatParam.ReflectionMap
                }
            }
            ShaderNode MetalFragNormals {
                Definition : MetalFrag : Shaders/Metal/MetalFrag.j3sn
                //Condition : NormalsMap
                InputMappings {
                    lightingColor = PhongFragNormals.outColor
                    reflectionColor = ReflectionFrag.outColor
                    reflectionAmount = MatParam.ReflectionAmount
                }
                OutputMappings {
                    Global.color = outColor
                }
            }
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    Technique Glow
    {
        Defines {
        }
        WorldParameters {
            WorldViewProjectionMatrix
            NormalMatrix
            WorldViewMatrix
            WorldMatrix
            ViewMatrix
            CameraPosition
        }
        VertexShaderNodes {
            ShaderNode MetalVertGlow {
                Definition : MetalVert : Shaders/Metal/MetalVert.j3sn
                InputMappings {
                    worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
                    modelPosition = Global.position.xyz
                    texCoord = Attr.inTexCoord
                }
                OutputMappings {
                    Global.position = projPosition
                }
            }
        }
        FragmentShaderNodes {
            ShaderNode Simplex3GrayFrag2 {
                Definition : Simplex3GrayFrag : Shaders/Simplex/Simplex3GrayFrag.j3sn
                InputMappings {
                    texCoord = NormalsMapVert.modelPosition.xyz
                    time = MatParam.Time
                    scale = MatParam.NoiseScale
                    octaves = MatParam.NoiseOctaves
                }
            }
            ShaderNode GlowTransientFrag {
                Definition : GlowTransientFrag : Shaders/Unshaded/GlowTransientFrag.j3sn
                //Condition : NormalsMap
                InputMappings {
                    simplexColor = Simplex3GrayFrag2.simplexColor
                    transitionPercent = MatParam.TransitionPercent
                    glowMap = MatParam.GlowMap
                    texCoord = MetalVertGlow.texCoord
                    globalAlpha= MatParam.GlobalAlpha
                }
                OutputMappings {
                    Global.color = outColor
                }
            }
        }
    }
}

Well Iā€™m sorry to hear that, but, itā€™s especially complicated when you donā€™t use the editor like you do.
Iā€™ll look into the same name in another technique issue.

Shader Nodes in 3.0 are experimental, and not a lot of people stepped up to test them. Iā€™m glad you did because you helped me fix a lot of issues. Now Iā€™d understand you stop there.

this part has been fixed in 3.1

Now about the conditional approach it seems you duplicate a lot of Nodes for some reason. Not sure why, you can definitely use defines in the code.

(well I totaly subscribe to shader nodes, cant wait for 3.1 to come out)

??? what ? the editor just shows a graph of nodes, but I cant do anything with it, so, itā€™s all text editing

as I said, I only duplicate the first node, but as it is a chain of nodes, I need to duplicate the subsequent nodes

node1_a defined from ā€œconditionā€
node1_b defined from ā€œ!conditionā€

node2_a parameters linked to node1_a parameters and
node2_b parameters linked to node1_b parameters

ā€¦ all the way to the bottom, so I split the declaration in two different materials otherwise it is unmanagable (check the archive I provided in previous post)

unless there is a syntax I am not aware, it is inevitable and the forking is logarithmic
1 conditions => 2 chains
2 conditions => 4 chains ā€¦

to avoid that, one should be able to define two twin nodes with the same name and different conditions
or find another way than these ā€œconditionsā€

or even better : CONDITIONAL PARAMETERS MAPPING

VertexShaderNodes {
    ShaderNode SomeNode {
        Definition:....
        InputMappings : Condition1
        {
        }
        InputMappings : Condition2 
        {
        }
...

or a special kind of node thatt does these kind of conditional mappings

fun fact is that I only try to have a shader node material that can deal with having or not a normal map provided by the ā€œuserā€, so easy to do with regular material definitions

so if you could enlight me on how to do that with shader nodes

Well, itā€™s a bit more than that. iā€™ll try to make a video of whatā€™s the 3.1 node editor is capable of.

well you can put a condiftion on the normal map input itself, not on the entire node and then test in your shader node code

#ifdef  NormalMap // <- this is the name of the mat param
   do thing with the normal map
#else
  do things without the normal map
#endif

but you told me in another post shader nodes had to use conditions
ok Iā€™ll check that out :slight_smile:

Wellā€¦I meant in a general way, you can use conditions for nodes, but also for input mappings.

well it does not seem to work with jme3

MaterialDef Simple {
    MaterialParameters {
        Texture2D NormalsMap
...
void main(){
#ifdef NormalsMap
    normal=normalize(texture2D( normalsMap, texCoord).rgb* 2.0 - 1.0);
    lightDir = normalize(lightDirIn.xyz);
    eyeVec = normalize(eyeVecIn).xyz; 
#else
    normal= normalize(normalIn);
    lightDir = normalize(lightDirIn.xyz);
    eyeVec = normalize(eyeVecIn).xyz; 
#endif

}

generated fragment shader


uniform sampler2D m_NormalsMap;
uniform bool m_Blinn;
uniform vec4 m_SceneAmbient;
uniform vec4 m_Ambient;
uniform sampler2D m_DiffuseMap;
uniform vec4 m_Specular;
uniform float m_Shininess;
uniform vec4 m_LightAmbient;
uniform vec4 m_LightDiffuse;
uniform vec4 m_LightSpecular;
uniform sampler2D m_ReflectionMap;
uniform float m_ReflectionAmount;

varying vec3 NormalsMapVert_normal;
varying vec2 MetalVert_texCoord;
varying vec4 NormalsMapVert_lightDir;
varying vec3 NormalsMapVert_eyeVec;
varying vec4 NormalsMapVert_debug;
varying vec4 NormalsMapVert_v;

void main(){
        vec4 Global_color = vec4(1.0);

    //PrePhongFragNormals : Begin
    vec3 PrePhongFragNormals_normalIn = NormalsMapVert_normal;
    vec2 PrePhongFragNormals_texCoord = MetalVert_texCoord;
    vec4 PrePhongFragNormals_lightDirIn = NormalsMapVert_lightDir;
    vec3 PrePhongFragNormals_eyeVecIn = NormalsMapVert_eyeVec;
    vec3 PrePhongFragNormals_lightDir;
    vec3 PrePhongFragNormals_normal;
    vec3 PrePhongFragNormals_eyeVec;

#ifdef NormalsMap
    PrePhongFragNormals_normal=normalize(texture2D( m_NormalsMap, PrePhongFragNormals_texCoord).rgb* 2.0 - 1.0);
    PrePhongFragNormals_lightDir = normalize(PrePhongFragNormals_lightDirIn.xyz);
    PrePhongFragNormals_eyeVec = normalize(PrePhongFragNormals_eyeVecIn).xyz; 
#else
    PrePhongFragNormals_normal= normalize(PrePhongFragNormals_normalIn);
    PrePhongFragNormals_lightDir = normalize(PrePhongFragNormals_lightDirIn.xyz);
    PrePhongFragNormals_eyeVec = normalize(PrePhongFragNormals_eyeVecIn).xyz; 
#endif
...

here NormalsMap does not seem to be defined cos the ā€œ#elseā€ part of the branch is executed no matter I provide a normal map or not

1 Like

Iā€™m gonna test it on master, I think Iā€™ve fix an issue with defines.

ok, but if it is not fixed in jme3 , then I gonna have to find another solution

let me try and Iā€™ll tell you what options you have.

Ok thatā€™s definitely a bug, or something that is not as straight forward as it shouldā€¦
But there is a workaround even for 3.0

You have to refer to the define in upper case in the shader (NORMALSMAP instead of NormalsMap). Note that it should work with the same case as the material param, thatā€™s the bug.
In addition to that you ahve to add a condition to the normal map mapping in the j3md file :

normalsMap = MatParam.NormalsMap : NormalsMap

That also shouldnā€™t be necessary but thatā€™s more a use case I overlooked. iā€™ll fix this for 3.1. In the meantime you can use the work around.

Once again, thanks a bunch for testing all this!

I am glad I can help :slight_smile:

ok Waitā€¦Now I remember how it was supposed to work
Actually thatā€™s not a bug. Itā€™sjust that I mislead you in my previous post.

In your shader code you can actually use this :

#ifdef normalsMap

Note the lower case ā€˜nā€™. Thatā€™s actually the name of the shader node definition input, not the material param name.
you stil have to add the condition to the mapping :

normalsMap = MatParam.NormalsMap : NormalsMap

The idea behind this is that you donā€™t know the name of the material parameter, when writing the shader node code, so thatā€™s best to base your define on the inputs of your shader node.

So thatā€™s basically saying : ā€œif my normalMap input is fed, do somethingā€, then the condition on the input mapping is there to say : ā€œIf my NormalMap parameter is fed, feed the normalMap inputā€.

Not sure if Iā€™m clear.
So thatā€™s actually working as intended.

ok, more modulable that way, thanks :smile:

but the vertex shader needs to check the normalsmap condition (for the tbn matrix)
as I provide the same sampler2d variable to the vertex shader, I get some errors

the error message itself dont make any sens

 normalsMap = MatParam.NormalsMap : NormalsMap ->Type mismatch, cannot convertsampler2D to sampler2D|sampler2DShadow

I just copied things from the fragment shader (there it doesā€™nt lead to that error)

now why is it not working for vertex shaders ā€¦? another bug ?

MaterialDef Simple {
    MaterialParameters {
        Texture2D GlowMap
        Texture2D DiffuseMap
        Texture2D ReflectionMap
        Texture2D NormalsMap
        TextureCubeMap RefractionMap
        Color SceneAmbient
        Color Ambient
        Color LightAmbient
        Color LightDiffuse
        Color Specular
        Color LightSpecular
        Float Shininess
        Boolean Blinn
        Float ReflectionAmount
        Vector2 TextureOffset
    }
    Technique {
        LightMode MultiPass
        Defines {
        }
        WorldParameters {
            WorldViewProjectionMatrix
            NormalMatrix
            WorldViewMatrix
            WorldMatrix
            ViewMatrix
            CameraPosition
        }
        VertexShaderNodes {
            ShaderNode NormalsMapVert {
                Definition : NormalsMapVert : Shaders/NormalsMap/NormalsMapVert.j3sn
                InputMappings {
                    normalsMap = MatParam.NormalsMap : NormalsMap
                    normalIn = Attr.inNormal
                    tangentIn = Attr.inTangent
                    modelPosition = Global.position.xyz
                    normalMatrix = WorldParam.NormalMatrix
                    viewMatrix = WorldParam.ViewMatrix
                    worldViewMatrix = WorldParam.WorldViewMatrix
                    worldMatrix = WorldParam.WorldMatrix
                    cameraPosition = WorldParam.CameraPosition
                }
                OutputMappings {
                }
            }
            ShaderNode MetalVert {
                Definition : MetalVert : Shaders/Metal/MetalVert.j3sn
                InputMappings {
                    worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
                    modelPosition = Global.position.xyz
                    texCoord = Attr.inTexCoord
                }
                OutputMappings {
                    Global.position = projPosition
                }
            }
        }
        FragmentShaderNodes {
            ShaderNode PrePhongFragNormals {
                Definition : PrePhongFrag : Shaders/NormalsMap/PrePhongFrag.j3sn
                InputMappings {
                    normalIn = NormalsMapVert.normal
                    texCoord = MetalVert.texCoord
                    normalsMap = MatParam.NormalsMap : NormalsMap
                    lightDirIn = NormalsMapVert.lightDir
                    eyeVecIn = NormalsMapVert.eyeVec
                    textureOffset = MatParam.TextureOffset : TextureOffset
                }
            }
            ShaderNode PhongFragNormals {
                Definition : PhongFrag : Shaders/Phong/PhongFrag.j3sn
                InputMappings {
                    normal = PrePhongFragNormals.normal
                    lightDir = PrePhongFragNormals.lightDir
                    eyeVec = PrePhongFragNormals.eyeVec
                    blinn = MatParam.Blinn
                    sceneAmbient = MatParam.SceneAmbient
                    ambient = MatParam.Ambient
                    diffuseMap = MatParam.DiffuseMap
                    specular = MatParam.Specular
                    shininess = MatParam.Shininess
                    lightAmbient = MatParam.LightAmbient
                    lightDiffuse = MatParam.LightDiffuse
                    lightSpecular = MatParam.LightSpecular
                    texCoord = MetalVert.texCoord
                    debug = NormalsMapVert.debug
                    textureOffset = MatParam.TextureOffset : TextureOffset
                }
            }
            ShaderNode ReflectionFrag {
                Definition : ReflectionFrag : Shaders/Reflection/ReflectionFrag.j3sn
                InputMappings {
                    v = NormalsMapVert.v
                    normal = NormalsMapVert.normal
                    lambertTerm = PhongFragNormals.lambertTerm
                    reflectionMap = MatParam.ReflectionMap
                }
            }
            ShaderNode MetalFragNormals {
                Definition : MetalFrag : Shaders/Metal/MetalFrag.j3sn
                InputMappings {
                    lightingColor = PhongFragNormals.outColor
                    reflectionColor = ReflectionFrag.outColor
                    reflectionAmount = MatParam.ReflectionAmount
                }
                OutputMappings {
                    Global.color = outColor
                }
            }
        }
    }
   
    Technique Glow {
        VertexShader GLSL100:   Common/MatDefs/Misc/Unshaded.vert
        FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag

        WorldParameters {
            WorldViewProjectionMatrix
        }

        Defines {
            NEED_TEXCOORD1
            HAS_GLOWMAP : GlowMap
            HAS_GLOWCOLOR : GlowColor

            NUM_BONES : NumberOfBones
        }
    }

}
ShaderNodesDefinitions
{
    ShaderNodeDefinition NormalsMapVert
    {
        Type: Vertex
        Shader GLSL100: Shaders/NormalsMap/NormalsMap.vert
        Documentation 
        {
           @input normalMatrix
           @input worldViewMatrix
           @input modelPosition
           @input normal
        }                
        Input
        {
            sampler2D normalsMap
            vec3 cameraPosition
            mat4 viewMatrix  
            mat4 worldMatrix
            mat3 normalMatrix
            mat4 worldViewMatrix
            vec3 modelPosition
            vec3 normalIn
            vec4 tangentIn
        }
        Output
        {
            vec4 lightDir
            vec3 normal
            vec4 v
            vec3 eyeVec
            vec4 debug
            vec3 modelPosition
        }
    }
}
ShaderNodesDefinitions
{
    ShaderNodeDefinition PrePhongFrag 
    {      
        Type: Fragment
        Shader GLSL100: Shaders/NormalsMap/PrePhong.frag
        Documentation
        {
            NormalsMap shader
        }
        Input
        {
            vec2 textureOffset
            vec3 normalIn
            vec2 texCoord
            sampler2D normalsMap
            vec4 lightDirIn
            vec3 eyeVecIn
        }
        Output 
        {
            vec3 lightDir
            vec3 normal;
            vec3 eyeVec
        }
   }
}