Introduction

Starting with version 10, Open Inventor® provides a GLSL shader API to access various state values from shaders. The classical GLSL built-in uniforms for OpenGL state (e.g. gl_ModelViewMatrix) now have a corresponding Open Inventor GLSL method (e.g. OivModelViewMatrix()).  These methods are documented in the Reference Manual and in $OIVHOME/shaders/include/Inventor/oivShaderState.h.  GLSL built-in constants (e.g. gl_MaxVertexAttribs) and GLSL built-in input/output variables (e.g. gl_FragCoord) are still available.  GLSL functions such as cos, mix, greaterThan, and so on, are still available.
 
Note: Even if some of the built-in GLSL state variables continue to work, you should no longer use them.
Note: Some changes to existing GLSL shader code are mandatory.

Table of content


Converting existing shaders

A script is provided in $OIVHOME\tools\source\Inventor\GLSLConverter\GLSLConverter.py to help converting existing shaders.

It's a simple python script that can be used to replace GLSL built-in uniforms with OIV shader API calls. It provides a simple way to port shaders that work in Open Inventor 9.x to shaders working in Open Inventor 10.

Usage: python GLSLConverter.py filename [--remove-original]

Where filename is the path to a file needing to be converted. It can also be a folder in which case the script will look for every file which name ends in '.glsl' to apply the single-file operation on it. Please note that the conversion process renames the original file filename.origin and the parsed file is saved under filename.
With the '--remove-original' option, filename.origin file is automatically removed by the script.

Note that only built-in uniforms exposed in the Open Inventor Shader API are replaced and others uniforms have to be handled in another way.

The script will automatically do the built-in variable's conversion and add //!oiv_include directive if needed.


GLSL Version

By default, Open Inventor builds GLSL shaders in 410 compatibility mode.  So it is not mandatory to specify #version 410 compatibility in your shader. But if you need a more recent version or some specific extensions, you'll have to specify it in your shader.

If you specify a version older than 410, Open Inventor will override it and compile in 410 anyway.

Even if a shader is built-in compatibility mode, it is good practice to respect the GLSL 410 specification. Otherwise you'll have a lot of messages saying: "Warning deprecated...".

Here is a list of common errors and how to fix them to avoid issues:

  • Using varying keyword instead of in/out:
    • In vertex shader: replace varying float value; by out float value;
    • In fragment shader: replace varying float value; by in float value
  • Using gl_TexCoord[0] to pass texcoord from vertex to fragment shader intead of using in/out varying
  • Using texture2D/3D function instead of generic texture.

Vertex attributes conversion

If your shader uses GLSL built-in vertex attributes like gl_Vertex, you should replace these calls with corresponding OIV calls and add the following include at the top of your shader:

//!oiv_include <Inventor/oivShapeAttribute.h>

Correspondence between built-in GLSL and Oiv methods:

Vertex attributes

Note: Using custom vertex attributes inputs to retrieve vertex positions, normals, colors and texture coordinates will not work.

// This will not work anymore in Vertex Shader
layout(location=0) in vec3 VertexPosition;


Built-in uniforms conversion

If your shader uses GLSL built-in uniforms like gl_ModelViewMatrix, you should replace these calls with corresponding Open Inventor calls and add the following include at the top of your shader:

//!oiv_include <Inventor/oivShaderState.h>

Here is the list of correspondence between built-in GLSL and Open Inventor available methods:

Matrices

Material

Lighting

Misc


Built-in varyings conversion

If your shader uses GLSL built in varyings like glTexCoord, glFrontColor, you should replace these calls with corresponding Open Inventor calls and add the following include at the top of your shader:

//!oiv_include <Inventor/oivShaderVariables.h>

Here is the list of correspondence between built in GLSL and Open Inventor available methods:

Inputs

Vertex Shader

Tessellation Control Shader / Tessellation Evaluation Shader / Geometry Shader

Fragment Shader

Outputs

Vertex Shader / Tessellation Evaluation Shader / Geometry Shader

Tessellation Control Shader

Fragment Shader


Manage transparency

To properly handle transparency, your fragment shader should contains the following function calls:

These methods are accessible by including the <Inventor/oivDepthPeeling_frag.h> header in your shader:

Exemple:

//!oiv_include <Inventor/oivDepthPeeling_frag.h>

void main()
{
if ( OivDepthPeel(gl_FragCoord.xyz) )
{
Vec4 color = vec4(1, 0, 0, 0.5);
OivDepthPeelingOutputColor(color);
}
}

You should also specify SoShaderProgram::generateTransparency = TRUE to indicate that your shader will override current SoMaterial transparency.


Geometry shader

Layout of input and output primitives must be manually specified in your geometry shader. Your geometry shader should contain a header like :

  • layout(input_primitive​) in; where input_primitive is one of
    • points
    • lines
    • triangles

    depending on type of node you use. For example, when applying geometry shader to an SoPointSet, input_primitive should be points.

  • layout(output_primitive, max_vertices = vert_count​) out; vert_count is number of vertices you want to emit and output_primitive is one of
    • points
    • line_strip
    • triangle_strip

    depending on type of primitive you want to emit.
    Ex: If your geometry shader take as input a point and generate a quad formed by two stripped triangles, to create some kind of billboard, your header will look like:

    • layout(points) in;
    • layout(triangle_strip, max_vertices = 4) out;

PassThrough Helpers

Functions are also available to copy all predefined varyings from one stage to the next:

Vertex Shader

gl_FrontColor   = gl_Color;
gl_BackColor    = gl_Color;
gl_TexCoord[0]  = gl_MultiTexCoord0;
gl_TexCoord[1]  = gl_MultiTexCoord1;
gl_TexCoord[2]  = gl_MultiTexCoord2;
gl_TexCoord[3]  = gl_MultiTexCoord3;
gl_FogFragCoord = gl_FogCoord;

can be replaced by OivSetupVertex()

Tessellation Evaluation Shader / Geometry Shader

gl_FrontColor = gl_in[i].gl_FrontColor;
gl_BackColor = gl_in[i].gl_BackColor;
gl_FrontSecondaryColor = gl_in[i].gl_FrontSecondaryColor;
gl_BackSecondaryColor  = gl_in[i].gl_BackSecondaryColor;
gl_TexCoord = gl_in[i].gl_TexCoord;
gl_FogFragCoord = gl_in[i].gl_FogFragCoord;

can be replaced by OivSetupVertex(i)

Tessellation Control Shader

gl_out[gl_InvocationID].gl_FrontColor = gl_in[i].gl_FrontColor;
gl_out[gl_InvocationID].gl_BackColor = gl_in[i].gl_BackColor;
gl_out[gl_InvocationID].gl_FrontSecondaryColor = gl_in[i].gl_FrontSecondaryColor;
gl_out[gl_InvocationID].gl_BackSecondaryColor = gl_in[i].gl_BackSecondaryColor;
gl_out[gl_InvocationID].gl_TexCoord = gl_in[i].gl_TexCoord;
gl_out[gl_InvocationID].gl_FogFragCoord = gl_in[i].gl_FogFragCoord;

can be replaced by OivSetupVertex(i)