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).
When defining a geometry shader, it is mandatory to define also a vertex shader. |
Example 21.2. Writing a geometry shader:
Contents of GeometryShader.cxx
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 ); ... }
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(); } } /******************************************************************************/
Figure 21.9. Shader usage for image base lighting and HDRI reflection (Data set courtesy DaimlerChrysler AG)