| status | work-in-progress |
| authors | Stephan Palmer, Christian Rieder |
| package | MeVisLab/Standard |
| dll | SoGVR |
| definition | SoGVRShaderPipeline.def |
| see also | SoGVRVolumeRenderer, SoGVRShaderDiagnosis, SoGVRShaderInclude |
| keywords | GVR, shader, pipeline, function |
The SoGVRShaderFunction allows for adding of custom GLSL shader code into the shader pipeline of the SoGVRVolumeRenderer module.
Connect the module before the SoGVRVolumeRenderer module in the scene graph and implement custom shader code to be added.
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.
For most steps, the GVR only uses one shader pipeline function at a time. This function is named like the step. For some steps, multiple functions are active at a time (e.g. in shading light for multiple lights). In this case, each function is considered to be a substep, and the function has a suffix in its name to reflect this. Example: For lighting, the step is named ShadingLight, and the substeps are named ShadingLight_Light1, ShadingLight_Light2 and so on.
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 SoGVRShaderFunction 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 and texture samplers using the GLSL shader framework of MeVisLab, e.g. SoShaderParameter3f, SoGVRShaderParameterPosition and SoMLSampler3D.
For shader development, it is important to understand the different coordinate systems:
GVR state variables and their coordinate systems:
| Variable | Coordinate System | Usage |
|---|---|---|
| state.primaryVolumePosition_tex | Tex | Texture sampling of primary volume |
| state.maskVolumePosition_tex | Tex | Texture sampling of mask volume |
| state.tagVolumePosition_tex | Tex | Texture sampling of tag volume |
| state.gradientVolumePosition_tex | Tex | Texture sampling of gradient volume |
| state.[*]Position_tex | Tex | Texture sampling of secondary/transformed volume ([*] = name of volume) |
| state.viewingDirection_scaledVoxel | ScaledVoxel | Used for light/silhouette calculations |
| state.primaryVolumePosition_eye | Eye | The primary sampling position in eye coordinates |
| state.primaryVolumePosition_world | World | The primary sampling position in world coordinates |
| state.primaryVolumePosition_voxel | Voxel | The primary sampling position in voxel coordinates |
| state.primaryVolumePosition_scaledVoxel | ScaledVoxel | The primary sampling position in scaled voxel coordinates |
The GVR provides transformation matrices for the common transformations that might be required. The matrices follow the following convention:
sourceName_sourceSystem_to_targetName_targetSystem
where sourceName and targetName are only given for voxel/scaledVoxel and tex matrices. The matrices are given as mat4, except for the inverse transformed, which are given as mat3.
| Name | Usage |
|---|---|
| world_to_eye | Transforms world to eye |
| world_to_primaryVolume_voxel | Transforms world to primaryVolume voxel |
| eye_to_world | Transforms eye to world |
| eye_to_primaryVolume_voxel | Transforms eye to primaryVolume voxel |
| primaryVolume_voxel_to_world | Transforms primaryVolume voxel to world |
| primaryVolume_voxel_to_eye | Transforms primaryVolume voxel to eye |
| primaryVolume_scaledVoxel_to_eye_inverseTransposed | Used to transform normals from scaledVoxel to eye (mat3) |
| primaryVolume_voxel_to_[*]_tex | Transforms primaryVolume voxel to [*] mask/transformed volume tex coordinates |
Have a look at the SoGVRShaderDiagnosis module for a complete overview. The following table list some useful uniforms:
| Type | Name | Usage |
|---|---|---|
| float | sliceDistance_voxel | Rendered slice distance in voxel units |
| ivec3 | primaryVolumeSize | The size of the primary volume |
| vec3 | primaryVolumeVoxelSize | The voxel size (in mm) of the primary volume |
| vec3 | primaryVolumeVoxelSizeInv | The inverse voxel size |
| vec3 | primaryVolumeTextureSize | The texture size (depended on the render mode) |
| vec4 | primaryVolumeTextureSizeInv | The inverse texture size and 0. in w (dependend on the render mode, useful as gradient offset) |
| vec3 | centralViewingDirection_scaledVoxel | The viewing direction at the center of the screen (as opposed to the correct viewing direction at each pixel that is given by state.viewingDirection_scaledVoxel) |
| vec3 | eyePosition_scaledVoxel | The eye position |
| float | lutTextureHeightInv | The inverse of the height of the LUT texture (for 2D LUTs) |
| sampler3D | primaryVolumeTexture | The primary volume texture |
| sampler3D | tagVolumeTexture | The tag volume texture |
| sampler3D | gradientVolumeTexture | The gradient volume texture |
| sampler3D | maskVolumeTexture | The mask volume texture |
| samplerXD | lutTexture | The main LUT texture (1D-3D) |
Although varyings are fully supported and can be passed from vertex program to fragment program, they only make sense for a pure slicing rendermode, since a GPU ray caster does not use the vertex program for interpolation of sampling positions. All builtin GVR varyings start with varying_ and it is common practice to make use of the positions privided by the state instead of directly using the varyings. This allows shader code to work on both the slicer and the ray caster. In some situations, it still makes sense to add own varyings to the vertex shader and use them in the fragment shader, e.g. to implement preintegrated rendering with the slicer.
The GVR has a number of builtin includes which are listed in the SoGVRShaderDiagnosis panel. The includes all start with the gvr_ prefix.
Depending on the settings of the SoGVRVolumeRenderer and its extensions, different pipeline steps become activated and different uniforms and texture samplers are available. Your best friend in introspecting the current shader pipeline is the SoGVRShaderDiagnosis module, which lists all active uniforms.
The best way to start using the SoGVRShaderFunction is to build the GVR scene that you wish to modify and adding a SoGVRShaderDiagnosis to inspect the resulting pipeline state and uniforms.
a node that should be put in front of the SoGVRVolumeRenderer
| Enabled: Bool | Program: Enum |
| Fragment Step: Enum | Replaced1: String |
| Function Body: String | Replacement1: String |
| Function Display: String | Substep (optional): String |
| Function Name: String | Vertex Step: Enum |
| Modification Type: Enum | |
| Needs Active Step: Bool | |
| Parameter Declaration: String |
Defines the modification type of the shader pipeline by the custom function.
Values:
| Title | Name | Description |
|---|---|---|
| Add After | ADD_AFTER | adds the custom function after the selected pipeline (sub)step |
| Add Before | ADD_BEFORE | adds the custom function before the selected pipeline (sub)step |
| Replace | REPLACE | the custom function replaces the selected pipeline (sub)step |
| Remove | REMOVE | the selected pipeline (sub)step will be removed from the shader pipeline |
Select the fragment or the vertex program.
Values:
| Title | Name |
|---|---|
| Fragment Program | Fragment Program |
| Vertex Program | Vertex Program |
Select the pipeline step of the vertex pipeline to be modified. Like the fragment shader, the vertex shader is structured as a pipeline. The vertex shader currently does not use the state struct, or substeps.
Values:
| Title | Name |
|---|---|
| Start | START |
| Raycast Vertex Setup | RAYCAST_VERTEX_SETUP |
| Clip Vertex | CLIP_VERTEX |
| Vertex Transform | VERTEX_TRANSFORM |
| Coordinates Primary | COORDINATES_PRIMARY |
| Coordinates Gradient | COORDINATES_GRADIENT |
| Coordinates Mask | COORDINATES_MASK |
| Coordinates Voxel | COORDINATES_VOXEL |
| Transformed Volume | TRANSFORMED_VOLUME |
| End | END |
Select the pipeline step of the fragment pipeline to be modified. The following table shows which values a step reads from and writes to the state struct, and which substeps exist.
Values:
| Title | Name |
|---|---|
| Start | START |
| Raycast Direction Fetch | RAYCAST_DIRECTION_FETCH |
| Raycast Clip Planes | RAYCAST_CLIP_PLANES |
| Raycast Ray Setup | RAYCAST_RAY_SETUP |
| Raycast Jittering | RAYCAST_JITTERING |
| First Hit Loop Start | FIRST_HIT_LOOP_START |
| First Hit Loop Check Ray Stop | FIRST_HIT_LOOP_CHECK_RAY_STOP |
| First Hit Loop Sample Position Setup | FIRST_HIT_LOOP_SAMPLE_POSITION_SETUP |
| First Hit Loop Sampling | FIRST_HIT_LOOP_SAMPLING |
| First Hit Loop Advance | FIRST_HIT_LOOP_ADVANCE |
| First Hit Loop End | FIRST_HIT_LOOP_END |
| First Hit Refinement | FIRST_HIT_REFINEMENT |
| First Hit Sampling Gradient | FIRST_HIT_SAMPLING_GRADIENT |
| First Hit Sampling End | FIRST_HIT_SAMPLING_END |
| First Hit Classification | FIRST_HIT_CLASSIFICATION |
| First Hit Shading Light | FIRST_HIT_SHADING_LIGHT |
| First Hit Shading Enhancement | FIRST_HIT_SHADING_ENHANCEMENT |
| First Hit Shading Tone | FIRST_HIT_SHADING_TONE |
| First Hit Shading End | FIRST_HIT_SHADING_END |
| First Hit Compositing Color | FIRST_HIT_COMPOSITING_COLOR |
| First Hit Compositing Shading | FIRST_HIT_COMPOSITING_SHADING |
| First Hit Result | FIRST_HIT_RESULT |
| Raycast Loop Start | RAYCAST_LOOP_START |
| Raycast Loop Check Ray Stop | RAYCAST_LOOP_CHECK_RAY_STOP |
| Raycast Loop Sample Position Setup | RAYCAST_LOOP_SAMPLE_POSITION_SETUP |
| Sampling Depth Peel | SAMPLING_DEPTH_PEEL |
| Sampling Primary | SAMPLING_PRIMARY |
| Sampling Mask | SAMPLING_MASK |
| Sampling Tag | SAMPLING_TAG |
| Sampling Additional | SAMPLING_ADDITIONAL |
| Sampling Gradient | SAMPLING_GRADIENT |
| Sampling End | SAMPLING_END |
| Classification Primary | CLASSIFICATION_PRIMARY |
| Classification Additional | CLASSIFICATION_ADDITIONAL |
| Classification End | CLASSIFICATION_END |
| Shading Light | SHADING_LIGHT |
| Shading Enhancement | SHADING_ENHANCEMENT |
| Shading Tone | SHADING_TONE |
| Shading End | SHADING_END |
| Compositing Color | COMPOSITING_COLOR |
| Compositing Shading | COMPOSITING_SHADING |
| Compositing Apply Alpha | COMPOSITING_APPLY_ALPHA |
| Compositing Additional | COMPOSITING_ADDITIONAL |
| Compositing End | COMPOSITING_END |
| Raycast Loop Composite | RAYCAST_LOOP_COMPOSITE |
| Raycast Loop Advance | RAYCAST_LOOP_ADVANCE |
| Raycast Loop End | RAYCAST_LOOP_END |
| Raycast Ray Result | RAYCAST_RAY_RESULT |
| First Hit Combine Result | FIRST_HIT_COMBINE_RESULT |
| End | END |
Specify a substep of the current pipeline step via suffix of the function name. E.g. chose the string Light1 in Shading Light to modify the shading substep of Light 1.
The pipeline will be modified only if the selected step is active in the current rendering configuraton of the GVR.
Allows to declare parameters which are used in the custom function body. Possible parameters:
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;
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 GVR builtin includes (see Tips and Tricks), or define your own includes with the SoGVRShaderInclude module.
Displays an overview over the function described by the current settings. Can e.g. be used to check the defined replacements.