GLSLFX Shaders


GLSLFX files make the bridge between the application and the glsl shader files.
It allows to use any glsl shader without having to modify the code.



File Format

GLSLFX file format is a XML file.
Comments are supported: <!-- This is a comment -->

Header and Root node

The Xml root node Element is named 'glslfx'.

Example:

<?xml version="1.0" encoding="UTF-8"?>
<glslfx version="1.0.0" author="allegorithmic.com">
    <!-- BODY -->
    <!-- ... -->
</glslfx>


Body

1. Techniques

XML Element that describes a technique.
A technique is a variation of the current FX.
A GLSLFX can contains multiples techniques but at least one technique has to be defined.
The geometry will be rendered with one of the techniques defined by the application.


XML Element Definition:

    • Name: 'technique'
    • Attributes:
      • 'name': The value is any string used to name the technique

Example:

<!-- TECHNIQUES -->
<technique name="LowResShader">
    <!-- ... -->
</technique>
<!-- ... -->
<technique name="HighResShader">
    <!-- ... -->
</technique>


The XML element can have multiples children.
The elements defined in a techniques override the elements defined globally.
For example, it is used to override some uniforms values and obtain FX variation for this technique.


Render Passes

XML Element that describes a render pass.
A render pass describes the rendering of the geometry.
A technique can contain multiple render passes that will be executed sequentially.
A technique containing no render pass is equivalent to a technique containing an 'onscreen' render pass.
The elements defined in a render pass override the elements defined in the parent technique.

XML Element Definition:

    • Name: 'pass'
    • Attributes:
      • 'output':
        • 'offscreen': The rendering will be done into user defined render targets
        • 'onscreen': The rendering will be done into the default render target

Exemple:

<!-- TECHNIQUES -->
<technique name="MultipassTechnique">
    <!-- RENDER PASSES -->
    <pass output="offscreen">
        <!-- ... -->
    </pass>
    <!-- ... -->
    <pass output="onscreen">
        <!-- ... -->
    </pass>
</technique>


Shaders

Set the glsl shader files for each type.

XML Element Definition:

      • Name: 'shader'
      • Attributes:
        • 'type': The glsl shader type.

          'type' ValueDescription
          vertexVertex shader
          geometryGeometry shader
          tess_controlTessellation Control shader
          tess_evalTessellation Evaluation shader
          fragmentFragment shader
        • 'filename': The path of the glsl shader file. Can be absolute or relative to the glslfx file
        • 'primitiveType': The method to render the primitive

          'primitiveType' ValueDescription
          pointRender as points
          lineloopRender as line loop
          patch[1..N]Render as patches with [1..N] vertices

Example:

<!-- TECHNIQUES -->
<technique name="Tessellation">
    <!-- SHADERS -->
    <shader type="vertex" filename="tessellation_parallax/tessellation/vs.glsl" primitiveType="patch3"/>
    <shader type="tess_control" filename="tessellation_parallax/tessellation/tcs.glsl"/>
    <shader type="tess_eval" filename="tessellation_parallax/tessellation/tes.glsl"/>
    <shader type="fragment" filename="tessellation_parallax/fs.glsl"/>
</technique>


Properties

Allow to set up some part of the OpenGL state.

XML Element Definition:

      • Name: 'property'
      • Attributes:
        • 'name': The name of the property to set. The name are based on the OpenGL function or glEnum name:
        • enum:
          • without the 'GL_' prefix, in lower case.
          • Ex:
            • glEnable(GL_BLEND_ENABLE) => "<property name="blend_enabled" value="true"/>""
            • glDisable(GL_CULL_FACE) => "<property name="cull_face_enabled" value="false"/>""
        • functions:
          • without the 'gl' prefix, in lower case and with all words separated with '_' character.
          • Ex:
            • glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) => "<property name="blend_func" value="src_alpha,one_minus_src_alpha"/>"
            • 'value': The value of the property
        • Allowed properties are:

          'name' Values'value' ValuesDescription
          blend_enabledbooleanEnable/disable the blending mode

          true

          false
          blend_funcstring, stringSet the sources and destination blending functions

          zerofor OpenGL enum GL_ZERO

          onefor OpenGL enum GL_ONE

          src_colorfor OpenGL enum GL_SRC_COLOR

          one_minus_src_colorfor OpenGL enum GL_ONE_MINUS_SRC_COLOR

          dst_colorfor OpenGL enum GL_DST_COLOR

          one_minus_dst_colorfor OpenGL enum GL_ONE_MINUS_DST_COLOR

          src_alphafor OpenGL enum GL_SRC_ALPHA

          one_minus_src_alphafor OpenGL enum GL_ONE_MINUS_SRC_ALPHA

          dst_alphafor OpenGL enum GL_DST_ALPHA

          one_minus_dst_alphafor OpenGL enum GL_ONE_MINUS_DST_ALPHA

          constant_colorfor OpenGL enum GL_CONSTANT_COLOR

          one_minus_constant_colorfor OpenGL enum GL_ONE_MINUS_CONSTANT_COLOR

          constant_alphafor OpenGL enum GL_CONSTANT_ALPHA

          one_minus_constant_alphafor OpenGL enum GL_ONE_MINUS_CONSTANT_ALPHA

          src_alpha_saturatefor OpenGL enum GL_SRC_ALPHA_SATURATE

          src1_colorfor OpenGL enum GL_SRC1_COLOR

          one_minus_src1_colorfor OpenGL enum GL_ONE_MINUS_SRC1_COLOR

          src1_alphafor OpenGL enum GL_SRC1_ALPHA

          one_minus_src1_alphafor OpenGL enum GL_ONE_MINUS_SRC1_ALPHA
          cull_face_enabledbooleanEnable/disable the face culling

          true

          false
          cull_face_modestringSet the face culling mode

          frontfor OpenGL enum GL_FRONT

          backfor OpenGL enum GL_BACK

          front_and_backfor OpenGL enum GL_FRONT_AND_BACK
          depth_funcstringSet the depth compare function

          neverfor OpenGL enum GL_NEVER

          lessfor OpenGL enum GL_LESS

          lequalfor OpenGL enum GL_LEQUAL

          equalfor OpenGL enum GL_EQUAL

          notequalfor OpenGL enum GL_NOTEQUAL

          gequalfor OpenGL enum GL_GEQUAL

          greaterfor OpenGL enum GL_GREATER

          alwaysfor OpenGL enum GL_ALWAYS

Example:

<!-- TECHNIQUES -->
<technique name="LowResShader">
    <!-- PROPERTIES -->
    <property name="blend_enabled" value="true"/>
    <property name="blend_func" value="src_alpha,one_minus_src_alpha"/>
    <property name="cull_face_enabled" value="true"/>
    <property name="cull_face_mode" value="back"/>
    <property name="depth_func" value="lequal"/>
 </technique>


Uniforms

Allow to override some uniforms defined globally or in the parent technique.
This allow to change shader behavior for this technique or render pass.
See the Uniforms definition chapter for more details about their definition.

Example:

<!-- TECHNIQUES -->
<technique name="Tesselation">
    <!-- SHADERS -->
    <shader type="vertex" filename="tessellation_parallax/tessellation/vs.glsl" primitiveType="patch3"/>
    <shader type="tess_control" filename="tessellation_parallax/tessellation/tcs.glsl"/>
    <shader type="tess_eval" filename="tessellation_parallax/tessellation/tes.glsl"/>
    <shader type="fragment" filename="tessellation_parallax/fs.glsl"/>

    <!-- UNIFORMS -->
    <uniform name="parallax_mode" guiName="Parallax Mode" min="0" max="0" />
    <uniform name="enableTilingInFS" guiName="Tiling Enabled In FS" min="0" max="0" />
    <uniform name="tessellationFactor" guiName="Tessellation Factor" default="4" min="1" max="64" guiStep="1" guiWidget="slider"/>
</technique>

<technique name="Parallax">
    <!-- RENDER PASSES -->
    <pass output="onscreen">
        <!-- SHADERS -->
        <shader type="vertex" filename="tessellation_parallax/parallax/vs.glsl"/>
        <shader type="fragment" filename="tessellation_parallax/fs.glsl"/>

        <!-- UNIFORMS -->
        <uniform name="parallax_mode" guiName="Parallax Mode" min="1" max="1" />
        <uniform name="enableTilingInFS" guiName="Tiling Enabled In FS" min="1" max="1" />
    </pass>
</technique>


Render Targets

For 'offscreen' render passes, render targets must be defined in the render pass.

XML Element Definition:

      • Name: 'output'
      • Attributes:
        • 'attachment': The OpenGL attachment point, inspired by the OpenGL names:
          GL_COLOR_ATTACHMENT[0..3] => 'color[0..3]'
          GL_DEPTH_ATTACHMENT => 'depth'

        • 'name': the name of the render target.
          It can be used in a later render pass to bind this render target as a sampler.

        • 'format': the internal format of the render target.

          • For color formats, the name is based on OpenGL enum names, without the 'GL_' prefix, in lower case.
            Three channel formats (RGB) are not supported, use an RGBA format instead.
            Bit depth per channel supported:
                    - Normalized unsigned integer: 8, 16
                    - Floating point: 16, 32
            An exception to these rules is the GL_R11F_G11F_B10F format which is supported.
            Ex:
            GL_RGBA8 => 'rgba8'
            GL_RGBA16F => 'rgba16f'
            GL_SRGB8_ALPHA8 => 'srgb8_alpha8'
            GL_R11F_G11F_B10F => 'r11f_g11f_b10f'
            GL_RG16 => "rg16"

          • For depth formats, all depth-only (no stencil) OpenGL formats are supported:
            GL_DEPTH_COMPONENT16 => 'depth16'
            GL_DEPTH_COMPONENT24 => 'depth24'
            GL_DEPTH_COMPONENT32 => 'depth32'
            GL_DEPTH_COMPONENT32F => 'depth32f'

        • 'clear': optional attribute that defines a clear value.
          If present, the render target will be cleared to this value at the beginning of the render pass.
          If missing, the render target will keep its previous content.

Exemple:

<!-- TECHNIQUES -->
<technique name="Parallax Occlusion">
    <!-- RENDER PASSES -->
    <pass output="offscreen">
        <!-- ... -->
        <!-- RENDER TARGETS -->
        <output attachment="color0" name="sssDiffuse" format="rgba16f"  clear="0.0,0.0,0.0,0.0"/>
        <output attachment="depth"  name="sssDepth"  format="depth32f" clear="1.0"/>
    </pass>
</technique>

Color render targets are forbidden in an 'onscreen' render pass, but a depth render target can be shared with
any render pass (but it's likely to break rendering when mixing multiple materials in the scene).


Samplers

Allow to override some samplers defined globally, they cannot be defined in a technique.
This allow to define a sampler usage for this render pass, or to read from a render target of a previous render pass.
See the Samplers definition chapter for more details about their definition.

Exemple:

<!-- TECHNIQUES -->
<technique name="Parallax Occlusion">
    <!-- RENDER PASSES -->
    <pass output="offscreen">
        <!-- ... -->
        <!-- RENDER TARGETS -->
        <output attachment="color0" name="sssDiffuse" format="rgba16f"/>
        <output attachment="depth" name="sssDepth" format="depth32f"/>
    </pass>
    <pass output="onscreen">
        <!-- ... -->
        <!-- SAMPLERS -->
        <sampler name="baseColorMap" usage="basecolor,diffuse"/>
        <sampler name="sssDiffuseMap" outputName="sssDiffuse"/>
        <sampler name="sssDepthMap" outputName="sssDepth" />
    </pass>
</technique>


2. Input Vertex Format

This allow to define the semantic of each attributes define in the vertex shader.

XML Element Definition:

    • Name: 'vertexformat'
    • Attributes:
      • 'name': The name of the attribute as defined in the vertex shader.
      • 'semantic': The semantic of the attribute.

        'semantic' ValueDescription
        positionVertex position (float3)
        normalVertex normal (float3)
        texcoord[0..N]Vertex texture coordinate buffer N (float2)
        tangent[0..N]Vertex tangent buffer N (float4)
        binormal[0..N]Vertex binormal buffer N (float4)

Example:

<?xml version="1.0" encoding="UTF-8"?>
<glslfx version="1.0.0" author="allegorithmic.com">
     <!-- BODY -->
     <!-- ... -->

     <!-- INPUT VERTEX FORMAT -->
     <vertexformat name="iVS_Position" semantic="position"/>
     <vertexformat name="iVS_Normal" semantic="normal"/>
     <vertexformat name="iVS_UV" semantic="texcoord0"/>
     <vertexformat name="iVS_Tangent" semantic="tangent0"/>
     <vertexformat name="iVS_Binormal" semantic="binormal0"/>
</glslfx>


3. Samplers

This allow to define the usage of each samplers.
It is used by the application to known which texture to set in the specified samplers.

XML Element Definition:

    • Name: 'sampler'
    • Attributes:
      • 'name': The name of the sampler variable in the shader file.
      • 'usage': The usage of the sampler. It matches the usage specified in the Ouput node of the graph.

        'usage' ValueDescription
        diffuseDiffuse map
        opacityOpacity map
        emissiveEmissive map
        ambientocclusionAmbient occlusion map
        ambientAmbient map
        maskMask map
        detailnormalDetail Normal map
        normalNormal map
        bumpBump map
        heightHeight map
        displacementDisplacement map
        specularlevelSpecular level map
        specularcolorSpecular color map
        specularSpecular map
        glossinessGlossiness map
        roughnessRoughness map
        anisotropylevelAnisothropy level map
        anisotropyangleAnisothropy angle map
        transmissiveTransmissive map
        reflectionReflection map
        refractionRefraction map
        environmentEnvironment map (cube map)
        panoramaThe Panorama Map (Latitude/Longitude Map)
        bluenoisemaskA 256x256 dithering texture


        • Multiple usages are supported. 
          • Example:

                 <!-- SAMPLERS -->
                <sampler name="baseColorMap" usage="basecolor,diffuse"/>
                 <!-- ... -->

      • 'isHidden': Boolean that indicates if the sampler should appear in the GUI
        • Example:

               <!-- SAMPLERS -->
              <sampler name="bluenoiseMask" usage="bluenoisemask" ishidden="true"/>
               <!-- ... -->

      • Wrapping Mode:

        NameValue
        texture_wrap_s, texture_wrap_t, texture_wrap_r


        clamp_to_edge
        clamp_to_border
        mirrored_repeat
        repeat

      • Texture Filter

        NameValue
        texture_min_filter, texture_mag_filter


        nearest
        linear
        nearest_mipmap_nearest
        linear_mipmap_nearest
        nearest_mipmap_linear
        linear_mipmap_linear


Example:

<?xml version="1.0" encoding="UTF-8"?>
<glslfx version="1.0.0" author="allegorithmic.com">
     <!-- BODY -->
     <!-- ... -->

     <!-- SAMPLERS -->
     <sampler name="baseColorMap" usage="basecolor,diffuse"/>
     <sampler name="heightMap" usage="height"/>
     <sampler name="normalMap" usage="normal"/>
     <sampler name="detailNormalMap" usage="detailNormal"/>
     <sampler name="environmentMap" usage="environment"/>
     <sampler name="bluenoiseMask" usage="bluenoisemask" ishidden="true"/>
     <sampler name="sssDiffuseMap" usage="sssDiffuse"/>

</glslfx>


4. Uniforms

This allow to add additional information on each shader uniforms.

XML Element Definition:

    • Name: 'uniform'
    • Attributes:
      • 'name': The name of the uniform in the shader file.
      • 'semantic': The semantic of the uniform. (All matrices are float16).

        'semantic' ValueDescription
        worldWorld Matrix (float16)
        worldinversetransposeWorld Inverse Transpose Matrix (float16)
        worldviewprojectionWorld View Projection Matrix (float16)
        viewinverseWorld Inverse Matrix (float16)
        worldviewWorld View Matrix (float16)
        modelviewModel View Matrix (float16)
        projectionProjection Matrix (float16)
        ambientScene Ambient Color (float3)
        lightposition[0..N]Position of the scene's Nth light (float3)
        lightcolor[0..N]Color of the scene's Nth light (float3)
        lightintensity[0..N]Intensity of the scene's Nth light (float)
        globaltimeCurrent time in secs (float)
        resolutionViewport resolution (int2)
        mouseMouse position (int2)
        samplespostablesizeNumber of samples to use to compute the environment lighting (int)
        irradianceshcoefsThe array of spherical harmonics vectors (float3[10])
        panoramamipmapheightNumber of mipmap levels in the panorama map (float)
        panoramarotationAngle Rotation angle of the panorama map (float)
        panoramaintensityIntensity of the panorama map (float)
        computebinormalinfragmentshaderDoes the binormal be computedt per fragment ? (if not then per vertex) (bool)
        isdirectxnormalIs the normal map format DirectX ? (bool)
        uvwscaleScale values of u, v, w (float3)
        renderuvtileRender only 1 UV tile ? (bool)
        uvtilecoordsUV tile coordinate to render (int2)

Example:

<?xml version="1.0" encoding="UTF-8"?>
<glslfx version="1.0.0" author="allegorithmic.com">
     <!-- BODY -->
     <!-- ... -->

     <!-- MATRICES -->
     <uniform name="worldMatrix" semantic="world"/>
     <uniform name="worldViewProjMatrix" semantic="worldviewprojection"/>
     <uniform name="worldViewMatrix" semantic="worldview"/>
     <uniform name="worldInverseTransposeMatrix" semantic="worldinversetranspose"/>
     <uniform name="viewInverseMatrix" semantic="viewinverse"/>
     <uniform name="modelViewMatrix" semantic="modelview"/>
     <uniform name="projectionMatrix" semantic="projection"/>
</glslfx>

Example:

<?xml version="1.0" encoding="UTF-8"?>
<glslfx version="1.0.0" author="allegorithmic.com">
    <!-- BODY -->
    <!-- ... -->

    <!-- SCENE PARAMETERS -->
    <uniform name="AmbiColor" semantic="ambient"/>
    <uniform name="Lamp0Pos" semantic="lightposition0"/>
    <uniform name="Lamp0Color" semantic="lightcolor0"/>
    <uniform name="Lamp1Pos" semantic="lightposition1"/>
    <uniform name="Lamp1Color" semantic="lightcolor1"/>
</glslfx>


Other parameters

Other additional information can be add to each uniforms to:

    • define the default value
    • clamp values
    • control the way the uniform will be display in the application:
    • set the label
    • set the widget info used to edit the value in the application:
    • widget name, min, max, increment/decrement step
    • group uniforms in group widgets

As the Uniforms can be override for each techniques, it allows to display a specific gui setup for each techniques.

XML Element Definition:

    • Name: 'uniform'
    • Attributes:
      • 'name': The name of the uniform in the shader file.
      • 'default': The uniform default value
      • 'min': The min value of the validity range
      • 'max': The max value of the validity range
      • 'guiName': The name of the uniform in the GUI of the application
      • 'guiGroup': The name of the group to put the uniform in the GUI of the application
      • 'guiWidget': The name of the widget used to edit the uniform value in the GUI of application

        'guiWidget' ValueDescription
        sliderSlider widget for floatN
        angleAngle widget for float
        colorColor widget for float3, float4 color
        checkboxCheckBox widget for bool
      • 'guiMin': The min value of the widget
      • 'guiMax': The max value of the widget


Example: Tessellation/Parallax

Parallax Vertex Shader File

Located in .\tessellation_parallax\parallax\vs.glsl

Content:

#version 120

attribute vec4 iVS_Position;
attribute vec4 iVS_Normal;
attribute vec2 iVS_UV;
attribute vec4 iVS_Tangent;
attribute vec4 iVS_Binormal;

varying vec3 iFS_Normal;
varying vec2 iFS_UV;
varying vec3 iFS_Tangent;
varying vec3 iFS_Binormal;
varying vec3 iFS_PointWS;

uniform mat4 worldMatrix;
uniform mat4 worldViewProjMatrix;

void main()
{
    gl_Position = worldViewProjMatrix * iVS_Position;
    iFS_Normal = iVS_Normal.xyz;
    iFS_UV = iVS_UV;
    iFS_Tangent = iVS_Tangent.xyz;
    iFS_Binormal = iVS_Binormal.xyz;
    iFS_PointWS = (worldMatrix * iVS_Position).xyz;
}


Tessellation Vertex Shader File

Located in .\tessellation_parallax\tessellation\vs.glsl

Content:

#version 120

attribute vec4 iVS_Position;
attribute vec4 iVS_Normal;
attribute vec2 iVS_UV;
attribute vec4 iVS_Tangent;
attribute vec4 iVS_Binormal;

varying vec4 oVS_Normal;
varying vec2 oVS_UV;
varying vec4 oVS_Tangent;
varying vec4 oVS_Binormal;

void main()
{
    gl_Position = iVS_Position;
    oVS_Normal = iVS_Normal;
    oVS_UV = iVS_UV;
    oVS_Tangent = iVS_Tangent;
    oVS_Binormal = iVS_Binormal;
}


Tessellation Control Shader File

Located in .\tessellation_parallax\tessellation\tcs.glsl

Content:

#version 400 core
#extension GL_ARB_tessellation_shader : enable

layout(vertices = 3) out;

in vec4 oVS_Normal[];
in vec2 oVS_UV[];
in vec4 oVS_Tangent[];
in vec4 oVS_Binormal[];

out vec4 oTCS_Normal[];
out vec2 oTCS_UV[];
out vec4 oTCS_Tangent[];
out vec4 oTCS_Binormal[];

uniform float tessellationFactor;

void main()
{
    gl_TessLevelOuter[0] = tessellationFactor;
    gl_TessLevelOuter[1] = tessellationFactor;
    gl_TessLevelOuter[2] = tessellationFactor;
    gl_TessLevelInner[0] = tessellationFactor;
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

    oTCS_Normal[gl_InvocationID] = oVS_Normal[gl_InvocationID];
    oTCS_UV[gl_InvocationID] = oVS_UV[gl_InvocationID];
    oTCS_Tangent[gl_InvocationID] = oVS_Tangent[gl_InvocationID];
    oTCS_Binormal[gl_InvocationID] = oVS_Binormal[gl_InvocationID];
}


Tessellation Evaluation Shader File

Located in .\tessellation_parallax\tessellation\tcs.glsl

Content:

#version 400 core

layout(triangles, equal_spacing, ccw) in;

in vec4 oTCS_Normal[];
in vec2 oTCS_UV[];
in vec4 oTCS_Tangent[];
in vec4 oTCS_Binormal[];

uniform mat4 worldMatrix;
uniform mat4 worldViewProjMatrix;

uniform sampler2D heightMap;

uniform float tiling = 1.0f;
uniform float heightMapScale = 1.0f;

out vec3 iFS_Normal;
out vec2 iFS_UV;
out vec3 iFS_Tangent;
out vec3 iFS_Binormal;
out vec3 iFS_PointWS;

vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2, vec3 uvw)
{
    return uvw.x * v0 + uvw.y * v1 + uvw.z * v2;
}

vec2 interpolate2D(vec2 v0, vec2 v1, vec2 v2, vec3 uvw)
{
    return uvw.x * v0 + uvw.y * v1 + uvw.z * v2;
}

void main()
{
    vec3 uvw = gl_TessCoord.xyz;

    vec3 newPos = interpolate3D(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz, uvw);
    vec3 newNormal = normalize(interpolate3D(oTCS_Normal[0].xyz, oTCS_Normal[1].xyz, oTCS_Normal[2].xyz, uvw));
    vec3 newTangent = normalize(interpolate3D(oTCS_Tangent[0].xyz, oTCS_Tangent[1].xyz, oTCS_Tangent[2].xyz, uvw));
    vec3 newBinormal = normalize(interpolate3D(oTCS_Binormal[0].xyz, oTCS_Binormal[1].xyz, oTCS_Binormal[2].xyz, uvw));
    vec2 newUV = interpolate2D(oTCS_UV[0], oTCS_UV[1], oTCS_UV[2], uvw);

    float heightTexSample = texture(heightMap, newUV * tiling).x * 2.0 - 1.0;
    newPos += newNormal * heightTexSample * heightMapScale;

    vec4 obj_pos = vec4(newPos, 1);
    gl_Position = worldViewProjMatrix * obj_pos;

    iFS_UV = newUV * tiling;
    iFS_Tangent = newTangent;
    iFS_Binormal = newBinormal;
    iFS_Normal = newNormal;
    iFS_PointWS = (worldMatrix * obj_pos).xyz;
}


Fragment Shader File

Located in .\tessellation_parallax\fs.glsl

Content:

#version 120

// #define ALG_NORMAL_DIRECTX
#define ALG_NORMAL_OPENGL

#ifdef ALG_NORMAL_DIRECTX
    // #define FLIP_NORMAL_X
#define FLIP_NORMAL_Y
    // #define FLIP_NORMAL_Z
#endif //#ifdef ALG_NORMAL_DIRECTX

#ifdef ALG_NORMAL_OPENGL
    // #define FLIP_NORMAL_X
#define FLIP_NORMAL_Y
    // #define FLIP_NORMAL_Z
#endif //#ifdef ALG_NORMAL_OPENGL

varying vec3 iFS_Normal;
varying vec2 iFS_UV;
varying vec3 iFS_Tangent;
varying vec3 iFS_Binormal;
varying vec3 iFS_PointWS;

uniform vec3 Lamp0Pos = vec3(0.0f,0.0f,70.0f);
uniform vec3 Lamp0Color = vec3(1.0f,1.0f,1.0f);
uniform vec3 Lamp1Pos = vec3(70.0f,0.0f,0.0f);
uniform vec3 Lamp1Color = vec3(0.198f,0.198f,0.198f);
uniform bool flipNormal = true;
uniform float TilingDetail = 3.0f;
uniform float SpecExpon = 50.0;
uniform float Ks = 1.0;
uniform int parallax_mode = 0;
uniform float tessellationFactor = 4.0;
uniform float heightMapScale = 1.0f;
uniform float Depth_detail = 0.5f;
uniform float Kr = 0.5f;
uniform int KF_on = 1;
uniform float KFs = 1.0f;
uniform vec3 AmbiColor = vec3(0.07f,0.07f,0.07f);
uniform float tiling = 1.0f;
uniform int enableTilingInFS = 0;

uniform sampler2D heightMap;
uniform sampler2D normalMap;
uniform sampler2D detailNormalMap;
uniform sampler2D emissiveMap;
uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2D opacityMap;
uniform samplerCube environmentMap;

uniform mat4 worldMatrix;
uniform mat4 worldInverseTransposeMatrix;
uniform mat4 viewInverseMatrix;

vec4 litFct(float NdotL, float NdotH, float specExp)
{
    float ambient = 1.0;
    float diffuse = max(NdotL, 0.0);
    float specular = step(0.0, NdotL) * pow(max(0.0, NdotH), specExp);
    return vec4(ambient, diffuse, specular, 1.0);
}

vec3 lerpFct(vec3 v0, vec3 v1, float percent)
{
    return v0 + (v1-v0) * percent;
}

// Phong Shading
void phong_shading(
in vec3 LightColor,
in vec3 normalWS,
in vec3 pointToLightDirWS,
in vec3 pointToCameraDirWS,
inout vec3 DiffuseContrib,
inout vec3 SpecularContrib)
{
    vec3 Hn = normalize(pointToCameraDirWS + pointToLightDirWS);
    vec4 litV = litFct(dot(normalWS, pointToLightDirWS), dot(normalWS, Hn), SpecExpon);
    DiffuseContrib = litV.y * LightColor;
    SpecularContrib = litV.y * litV.z * Ks * LightColor;
}

vec3 fixNormalSample(vec3 v)
{
    vec3 result = v - vec3(0.5,0.5,0.5);

#ifdef FLIP_NORMAL_X
    result.x = -result.x;
#endif // ifdef FLIP_NORMAL_X
#ifdef FLIP_NORMAL_Y
    result.y = -result.y;
#endif // ifdef FLIP_NORMAL_Y
#ifdef FLIP_NORMAL_Z
    result.z = -result.z;
#endif // ifdef FLIP_NORMAL_Z

    return result;
}

vec3 normalVecOSToWS(vec3 normal)
{
    return normal;
}

void main()
{
    vec3 cameraPosWS = viewInverseMatrix[3].xyz;
    vec3 pointToLight0DirWS = normalize(Lamp0Pos - iFS_PointWS);
    vec3 pointToLight1DirWS = normalize(Lamp1Pos - iFS_PointWS);
    vec3 pointToCameraDirWS = normalize(cameraPosWS);
    vec3 normalOS = normalize(iFS_Normal);
    vec3 tangentOS = normalize(iFS_Tangent);
    vec3 binormalOS = normalize(iFS_Binormal);

    // ------------------------------------------
    // Make sure the TBN is Orthonormalized
    binormalOS = normalize(cross(normalOS, tangentOS));
    tangentOS = normalize(cross(binormalOS, normalOS));

    vec3 cumulatedNormalOS = normalOS;

    // ------------------------------------------
    // Update UV
    float a = dot(normalOS,-pointToCameraDirWS);
    vec3 s = vec3(dot(pointToCameraDirWS,tangentOS), dot(pointToCameraDirWS,binormalOS), a);
    vec2 uv = enableTilingInFS == 0 ? iFS_UV : (iFS_UV * tiling);
    float height = texture2D(heightMap,uv).x * 2.0 - 1.0 ;
    float parallax = parallax_mode == 0 ? (tessellationFactor / 100000.f + heightMapScale / 500.f) : (heightMapScale / 50.f);
    uv += (height * s.xy * parallax) ;

    // ------------------------------------------
    // Add Normal from normalMap
    vec3 normalTS = texture2D(normalMap,uv).xyz;
    normalTS = fixNormalSample(normalTS);
    vec3 normalMapOS = normalTS.x*tangentOS + normalTS.y*binormalOS;
    cumulatedNormalOS = cumulatedNormalOS + normalMapOS;
    cumulatedNormalOS = normalize(cumulatedNormalOS);

    // ------------------------------------------
    // Add detail normalmap
    vec3 normalDetailTS = texture2D(detailNormalMap,uv*TilingDetail).xyz;
    normalDetailTS = fixNormalSample(normalDetailTS);
    vec3 variableNormalDetailTS = lerpFct(vec3(0.0,0.0,0.5),normalDetailTS,Depth_detail);
    vec3 normalDetailOS = variableNormalDetailTS.x*tangentOS + variableNormalDetailTS.y*binormalOS;
    cumulatedNormalOS = cumulatedNormalOS + normalDetailOS;
    cumulatedNormalOS = normalize(cumulatedNormalOS);

    if (length(normalTS)<0.0001)
        cumulatedNormalOS = normalOS;

    vec3 cumulatedNormalWS = normalVecOSToWS(cumulatedNormalOS);

    // ------------------------------------------
    // Compute Diffuse & Specular

    // Light 0 contribution
    vec3 diffContrib = vec3(0, 0, 0);
    vec3 specContrib = vec3(0, 0, 0);
    phong_shading(Lamp0Color, cumulatedNormalWS, pointToLight0DirWS, pointToCameraDirWS, diffContrib, specContrib);

    // Light 1 contribution
    vec3 diffContrib2 = vec3(0, 0, 0);
    vec3 specContrib2 = vec3(0, 0, 0);
    phong_shading(Lamp1Color, cumulatedNormalWS, pointToLight1DirWS, pointToCameraDirWS, diffContrib2, specContrib2);

    diffContrib += diffContrib2;
    specContrib += specContrib2;

    vec4 diffuseColor = texture2D(diffuseMap,uv);

    vec3 specularColor = texture2D(specularMap,uv).rgb;
    vec3 R = reflect(pointToCameraDirWS,cumulatedNormalWS);
    vec3 reflColor = Kr * textureCube(environmentMap,R.xyz).bgr;

    float FallofRefl;

    if (KFs >= 0.0)
        FallofRefl = max((1-dot(pointToCameraDirWS/(KFs),cumulatedNormalWS)),0)*KF_on;
    else
        FallofRefl = (1-max(((1-dot(pointToCameraDirWS/(-KFs),cumulatedNormalWS))),0))*KF_on;

    if (KF_on == 0)
        FallofRefl=1.0;

    vec3 Ambiant_final = diffuseColor.rgb*AmbiColor;

    // ------------------------------------------
    vec3 emissive = texture2D(emissiveMap,uv).xyz;

    vec3 finalcolor = Ambiant_final
        + specularColor*specContrib
        + diffuseColor.rgb*diffContrib
        + (reflColor*specularColor*FallofRefl)
        + emissive;

    // Final Color
    vec4 finalColor4 = vec4(finalcolor, texture2D(opacityMap,uv));

    gl_FragColor = finalColor4;
}


GLSLFX File

The glslfx file defines two techniques to render the geometry:

  • One uses the hardware tessellation technique
  • The other based on a parallax effect that will be used as a fall-back if the user hardware don't support the Tessellation.

Located in .\tessellation_parallax\fs.glsl


Content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sbsbatchnode SYSTEM "glslfx.dtd">
<glslfx version="1.0.0" author="allegorithmic.com">

    <!-- TECHNIQUES -->
    <technique name="Tesselation">
        <!-- PROPERTIES -->
        <property name="blend_enabled" value="true"/>
        <property name="blend_func" value="src_alpha,one_minus_src_alpha"/>
        <property name="cull_face_enabled" value="true"/>
        <property name="cull_face_mode" value="back"/>

        <!-- SHADERS -->
        <shader type="vertex" filename="tessellation_parallax/tessellation/vs.glsl" primitiveType="patch3"/>
        <shader type="tess_control" filename="tessellation_parallax/tessellation/tcs.glsl"/>
        <shader type="tess_eval" filename="tessellation_parallax/tessellation/tes.glsl"/>
        <shader type="fragment" filename="tessellation_parallax/fs.glsl"/>

        <!-- UNIFORMS -->
        <uniform name="parallax_mode" guiName="Parallax Mode" min="0" max="0" />
        <uniform name="enableTilingInFS" guiName="Tiling Enabled In FS" min="0" max="0" />
        <uniform name="tessellationFactor" guiName="Tessellation Factor" default="4" min="1" max="64" guiStep="1" guiWidget="slider"/>
    </technique>

    <technique name="Parallax">
        <!-- PROPERTIES -->
        <property name="blend_enabled" value="true"/>
        <property name="blend_func" value="src_alpha,one_minus_src_alpha"/>
        <property name="cull_face_enabled" value="true"/>
        <property name="cull_face_mode" value="back"/>

        <!-- SHADERS -->
        <shader type="vertex" filename="tessellation_parallax/parallax/vs.glsl"/>
        <shader type="fragment" filename="tessellation_parallax/fs.glsl"/>

        <!-- UNIFORMS -->
        <uniform name="parallax_mode" guiName="Parallax Mode" min="1" max="1" />
        <uniform name="enableTilingInFS" guiName="Tiling Enabled In FS" min="1" max="1" />

    </technique>

    <!-- INPUT VERTEX FORMAT -->
    <vertexformat name="iVS_Position" semantic="position"/>
    <vertexformat name="iVS_Normal" semantic="normal"/>
    <vertexformat name="iVS_UV" semantic="texcoord0"/>
    <vertexformat name="iVS_Tangent" semantic="tangent0"/>
    <vertexformat name="iVS_Binormal" semantic="binormal0"/>

    <!-- SAMPLERS -->
    <sampler name="diffuseMap" usage="diffuse"/>
    <sampler name="heightMap" usage="height"/>
    <sampler name="normalMap" usage="normal"/>
    <sampler name="detailNormalMap" usage="detailNormal"/>
    <sampler name="emissiveMap" usage="emissive"/>
    <sampler name="specularMap" usage="specular"/>
    <sampler name="opacityMap" usage="opacity"/>
    <sampler name="environmentMap" usage="environment"/>

    <!-- MATRICES -->
    <uniform name="worldMatrix" semantic="world"/>
    <uniform name="worldViewProjMatrix" semantic="worldviewprojection"/>
    <uniform name="worldViewMatrix" semantic="worldview"/>
    <uniform name="worldInverseTransposeMatrix" semantic="worldinversetranspose"/>
    <uniform name="viewInverseMatrix" semantic="viewinverse"/>
    <uniform name="modelViewMatrix" semantic="modelview"/>
    <uniform name="projectionMatrix" semantic="projection"/>

    <!-- SCENE PARAMETERS -->
    <uniform name="AmbiColor" semantic="ambient"/>
    <uniform name="Lamp0Pos" semantic="lightposition0"/>
    <uniform name="Lamp0Color" semantic="lightcolor0"/>
    <uniform name="Lamp1Pos" semantic="lightposition1"/>
    <uniform name="Lamp1Color" semantic="lightcolor1"/>

    <!-- UNIFORMS -->
    <uniform name="tiling" guiName="Tiling" default="1" min="1" guiWidget="slider" guiMax="10"/>
    <uniform name="heightMapScale" guiGroup="Height" guiName="Scale" default="1" min="0" guiWidget="slider" guiMin="-50" guiMax="50" />
    <uniform name="TilingDetail" guiGroup="Detail Normal" guiName="Tiling" default="3" min="1" guiWidget="slider" guiMax="10"/>
    <uniform name="Depth_detail" guiGroup="Detail Normal" guiName="Intensity" default="0.5" min="0" max="1" guiStep="0.05" guiWidget="slider"/>
    <uniform name="SpecExpon" guiGroup="Specular" guiName="Power" default="50" min="1" guiWidget="slider" guiMax="128"/>
    <uniform name="Ks" guiGroup="Specular" guiName="Intensity" default="1" min="0" guiWidget="slider" guiMax="3"/>
    <uniform name="Kr" guiGroup="Reflection" guiName="Intensity" default="0.5" min="0" max="1" guiStep="0.01" guiWidget="slider"/>
    <uniform name="KF_on" guiGroup="Reflection" guiName="Falloff" default="1" min="0" max="1" guiStep="1" guiWidget="slider"/>
    <uniform name="KFs" guiGroup="Reflection" guiName="Falloff Size" default="1" min="-1" max="1" guiStep="0.05" guiWidget="slider"/>

</glslfx>