SoShaderPipelineFunction

InventorModule
author MeVis Medical Solutions AG
package MeVisLab/Standard
dll SoShaderPipeline
definition SoShaderPipeline.def

Purpose

The SoShaderPipelineFunction allows to extend the SoShaderPipeline with custom steps.

Based on the SuperShader concept, the rendering shader is subdivided into a dynamic shader pipeline which allows for an interactive addition of custom shader code to the volume rendering. A pipeline step is modeled as a subset of several shader pipeline functions, which contain the GLSL shader code.

Since pipeline functions have no return value, a globally defined struct is used for communication. The struct is passed as input and output parameter (state) to the pipeline functions. Input values are read from the struct, output values are written into the struct.

The module SoShaderPipelineFunction allows to implement a custom pipeline function, where the function body as well as the parameters can be edited. Thus, custom pipeline functions can be attached to a pipeline step in order to add or replace shader code (see modification type).

You can add your own uniforms, texture samplers and vertex attributes using the GLSL shader framework shader framework of MeVisLab, e.g. SoShaderParameter3f, SoGVRShaderParameterPosition and SoMLSampler3D.

Details

The following state is available in a default pipeline shader (with per-fragment shading):

Vertex Shader State

Initial state:

state vec4 vertexPosition
state vec4 vertexColor
state vec3 vertexNormal

After eye transformation:

state vec3 vertexEyeNormal
state vec4 vertexEyePosition

After projection:

state vec4 projectedPosition

Fragment Shader State

Initial state:

state vec4 vertexEyePosition
state vec3 vertexEyeNormal
state vec4 vertexColor
state vec3 eyeViewingDirection

After surface shader setup:

state float surfaceShininess
state vec3  surfaceDiffuse
state float surfaceAlpha
state vec3  surfaceSpecular

After lighting:

state vec4 resultColor

Lighting

The lighting is calculated in eye space. This is so because the OpenGL fixed function lights are in eye space by default and it was straight forward to work in eye space. This means that you should use the vertexEyePosition, vertexEyeNormal and eyeViewingDirection for custom lighting calculations.

Future versions might do lighting in tangent space as well, this would make sense if normal mapping is used in a surface shader. This would mainly be a performance optimization, because if light positions/dirs, view dir etc. would all be in tangent space, the per pixel fetch of the normal would not require to be mapped to eye space.

Shader version and extensions

Inside of the function or the include, you can place a:

#version GLSLVersion

directive to indicate, which GLSL version you want to use. The shader pipeline will parse these and use the highest shader version that is requested.

In addition to that, you can use the the standard #extension directive in your function. All extension directives will be moved to the top of the resulting shader.

Example::
#version 120 #extension GL_EXT_texture_array : enable

The highest GLSL version that can be used with the SoShaderPipeline is 130. Starting with shader version 140, all OpenGL state uniforms in the shader have been removed. A future version of the shader pipeline (and Open Inventor) might set alternative uniforms that match the deprecated OpenGL state, so that using newer GLSL versions become possible.

Transferring state between shaders

To avoid the manual creation of varying variable, there is an automatism that transfers state values from the vertex shader state to the fragment shader state automatically. This works by automatically transferring any vertex state that starts with vertex to the fragment shader. How this happens is transparent to the user. So if you add a new state to the vertex shader, e.g. vertexCurvature, you can just use the same state in the fragment shader, by using the same name.

Vertex attributes can be added manually, but it is also possible to prefix a state variable name with vertexArray_. For instance, adding the state variable vertexArray_NodeCurvature will automatically add a NodeCurvature attribute to the shader and copy its value to the state. If the state is used in the fragment shader, it is automatically transfered as a varying.

Tips

To get started, have a look at the SoShaderPipelineDiagnosis to see how a generated shader looks and what kind of state variables and steps are available by default.

Windows

Default Panel

../../../Modules/Inventor/SoShaderPipeline/mhelp/Images/Screenshots/SoShaderPipelineFunction._default.png

Parameter Fields

Field Index

Enabled: Bool Program: Enum
Fragment Step: Enum Vertex Step: Enum
Function Body: String  
Function Display: String  
Function Name: String  
Modification Type: Enum  
Needs Active Step: Bool  
Parameter Declaration: String  

Visible Fields

Enabled

name: enabled, type: Bool, default: TRUE

Enables the function.

Function Name

name: functionName, type: String

Defines the (optional) function name.

Function Body

name: functionBody, type: String

The implementation of the function body. The state variable contains the current pipeline state.

Parameter Declaration

name: parameterDeclaration, type: String

Allows to declare parameters which are used in the custom function body. Possible parameters:

  • uniform: for a GLSL uniform parameter
  • varying: for a GLSL varying parameter
  • attribute: for a GLSL vertex attribute parameter
  • state: for a input/output pipeline struct parameter
  • include: for a custom shader header or pipeline library function

Using uniform, varying and state will add the declared variable declaration to the header string. Using include will add the declaration of the specified include to the header.

Syntax:

uniform TYPE identifier;
uniform TYPE identifier [size];
varying TYPE identifier;
attribute TYPE identifier;
state TYPE identifier;
state TYPE identifier = DEFAULTVALUE;
include name;

Entries in the parameter declaration field are separated by newline. The ; and = characters can be ommitted. TYPE can be any GLSL type, identifier can be any GLSL identifier (e.g. variable name). DEFAULTVALUE can be a GLSL statement to initialize a variable which matches the respective type and can be called in a struct constructor. For includes, name is a user defined identifier for the include. In every line, character after the expected number of words are ignored, which can e.g. be used for comments.

For includes, you can either use the SoShaderPipeline builtin includes (see Tips and Tricks), or define your own includes with the SoShaderPipelineInclude module.

Function Display

name: functionDisplay, type: String, persistent: no

Shows the complete function.

Modification Type

name: modificationType, type: Enum, default: ADD_AFTER

Defines which operation is applied.

Values:

Title Name Description
Add After ADD_AFTER Add function after the given step.
Add Before ADD_BEFORE Add function before the given step.
Replace REPLACE Replace the given step with this function.
Remove REMOVE Remove the given step.
Add Before Inorder ADD_BEFORE_INORDER Like ADD_BEFORE, but keeps order of functions

Program

name: program, type: Enum, default: Fragment Program

Selects the shader program type of the function.

Values:

Title Name
Fragment Program Fragment Program
Vertex Program Vertex Program

Vertex Step

name: vertexStep, type: Enum, default: START

Selects the vertex step.

Values:

Title Name
Start START
Calculate Eye Position CALCULATE_EYE_POSITION
Calculate Texture Coord CALCULATE_TEXTURE_COORD
Vertex Surface Shader VERTEX_SURFACE_SHADER
Vertex Lighting VERTEX_LIGHTING
Project Vertex PROJECT_VERTEX
Calculate Point Sprite Size CALCULATE_POINT_SPRITE_SIZE
End END
Vertex Add Ambient VERTEX_ADD_AMBIENT
Vertex Add Emissive VERTEX_ADD_EMISSIVE

Fragment Step

name: fragmentStep, type: Enum, default: START

Selects the fragment step.

Values:

Title Name
Start START
Point Sprite Setup POINT_SPRITE_SETUP
Depthpeel Discard DEPTHPEEL_DISCARD
Fragment Surface Setup FRAGMENT_SURFACE_SETUP
Fragment Surface Shader FRAGMENT_SURFACE_SHADER
Fragment Lighting FRAGMENT_LIGHTING
Texturing TEXTURING
Fog FOG
Write Fragment WRITE_FRAGMENT
End END
Fragment Add Ambient FRAGMENT_ADD_AMBIENT
Fragment Add Emissive FRAGMENT_ADD_EMISSIVE

Needs Active Step

name: needsActiveStep, type: Bool, default: FALSE

If enabled, the function is only added if the given step is active.