21.4. Writing a Geometry shader

The following example computes within a geometry shader the geometry of point field bars from a set of 3D points which specify the X,Y coordinate of the center of each bar and the Z coordinate of the top of each bar. The 3D point set is defined by an SoPointSet( C++ | Java | .NET ) shape.

The example source code is located in $OIVHOME/src/Inventor/examples/Features/Shaders/GeometryShader.

This example is written using GLSL (Open Inventor supports only GLSL geometry shaders).

[Warning]

When defining a geometry shader, it is mandatory to define also a vertex shader.

Point field bars computed within a geometry shader

Figure 21.7. Point field bars computed within a geometry shader


Simplified scene graph of GeometryShader.cxx

Figure 21.8. Simplified scene graph of GeometryShader.cxx


Example 21.2. Writing a geometry shader:

Contents of GeometryShader.cxx


C++
main(int argc, char **argv)
{
  ...`
  // Initialize the vertex and geometry shader
  SoVertexShader *vertexShader = new SoVertexShader;
  SoGeometryShader *geometryShader = new SoGeometryShader;
  
  vertexShader->
  sourceProgram.setValue( "../../../data/Shaders/histoShaderVtx.glsl" );
  geometryShader->
  sourceProgram.setValue( "../../../data/Shaders/histoShaderGeom.glsl" );
  
  // Initialize and set the shader program
  SoShaderProgram *shaderProgram = new SoShaderProgram;
  shaderProgram->shaderObject.set1Value( 0, vertexShader );
  shaderProgram->shaderObject.set1Value( 1, geometryShader );
  // Define the input geometry type which is POINTS because defined by an
  // SoPointSet
  shaderProgram->geometryInputType = SoShaderProgram::POINTS_INPUT;
  // Define the output geometry type generated by the geometry shader which is
  // a triangle strip set
  shaderProgram->geometryOutputType = SoShaderProgram::TRIANGLE_STRIP_OUTPUT;
  
  // Uniform parameter to define the bar width
  HistoGeomShaderWidth = new SoShaderParameter1f;
  HistoGeomShaderWidth->name = "BarWidth";
  geometryShader->parameter.setValue( HistoGeomShaderWidth );
  
  // Input geometry shader primitive (SoPointSet)
  HistoGeomShaderShape = new SoPointSet;
  HistoGeomShaderCoord = new SoCoordinate3;
  
  // Build the scene graph
  SoSeparator *geomShaderSep = new SoSeparator;
  geomShaderSep->boundingBoxIgnoring = true;
  geomShaderSep->addChild( shaderProgram );
  geomShaderSep->addChild( HistoGeomShaderCoord );
  geomShaderSep->addChild( HistoGeomShaderShape );
  ...
}
      

.NET
          
        

Java
          
        

Contents of histoShaderVtx.glsl Vertex Shader:

/* !!GLSL Vertex Shader */

void main()
  {
  // Transform the vertex (ModelViewProj matrix)
  gl_Position = gl_Vertex;
  gl_FrontColor = gl_FrontMaterial.diffuse;
  }

Contents of histoShaderGeom.glsl Geometry Shader:

#version 120
#extension GL_EXT_geometry_shader4 : enable

uniform float BarWidth;

/******************************************************************************/
// Compute the diffuse color according to the normal.
vec4
computeDiffuseColor( vec3 normal )
  {
  vec3 tNormal = normalize( gl_NormalMatrix * normal );
    return ( max( dot( tNormal, vec3( gl_LightSource[0].position ) ), 0. ) *
    gl_FrontColorIn[0] );
  } 
/******************************************************************************/


void main(void)
  {
  int i;

    for ( i=0; i< gl_VerticesIn; i++ )
    {
      vec4 posIn = gl_PositionIn[i];
      vec4 position;
      position.w = posIn.w;

    // 1st face
      position.x = posIn.x - BarWidth;
      position.y = posIn.y - BarWidth;
      position.z = 0.0;
      gl_Position = gl_ModelViewProjectionMatrix * position;
      gl_FrontColor = computeDiffuseColor( vec3( 0, -1, 0 ) );
      EmitVertex();

      position.z = posIn.z;
      gl_Position = gl_ModelViewProjectionMatrix * position;
      EmitVertex();

      position.x = posIn.x + BarWidth;
      position.z = 0.0;
      gl_Position = gl_ModelViewProjectionMatrix * position;
      EmitVertex();

      position.z = posIn.z;
      gl_Position = gl_ModelViewProjectionMatrix * position;
      EmitVertex();
      EndPrimitive();

    // 2nd face
      ...
      ...
      EndPrimitive();

    // 3rd face
      ...
      ...
      EndPrimitive();

    // 4th face ... ...
      EndPrimitive();

    // 5th face ... ...
      EndPrimitive();

    // 6th face ... ...
      EndPrimitive();
    }
  }                                               
/******************************************************************************/

Shader usage for image base lighting and HDRI reflection (Data set courtesy DaimlerChrysler AG)

Figure 21.9. Shader usage for image base lighting and HDRI reflection (Data set courtesy DaimlerChrysler AG)