Last year I was given time by my company (TNO) to look at building a shader generation framework for OpenSceneGraph. This submission is the result of that work and of the extra spare time I put in.
The submission includes three major parts: -shader composition; shader generation in the OSG backed implementing most of the FFP -osgshadermodetester; an example for interactive comparison of FFP with the generated shader -parameter tweaker; used by above example for tweaking state variables My design goals were these: -easy transition from FFP to shader based pipeline for front-en users --use OSG paradigms --support complete Fixed Function Pipeline in shaders --allow mixing of FFP functionality with OSG features (skinning, shadows etc.) --allow custom shader functionality to be hooked into existing shader (FFP with wind deflection, new types of lighting) -allow scaling between many small specific shaders and more generic shaders that branch dynamically (optimal shaders vs. many switches) -allow visual shader debugging (depth only, normals only, light only etc.) -allow completely new (non-visual) shaders (infrared, nvg simulation etc.) -support multipass and multiple rendertargets -allow custom renderer implementation (forward rendering vs deferred) OSGSHADERMODETESTER This example enables you to test how state changes will affect the FFP and the shader based window. When started you will see two windows next to eachother. Initially both windows will be showing FFP based rendering. -Press 'u' to show a HUD with the current parameter that can be tweaked. -The right arrow and left arrow keys will select the next parameter or part of a parameter (between <> signs) -The up and down arrow keys will increase or decrease the value of the active parameter (or part of it) -Note that parts of the parameters may be skipped if other parameters are disabled. For instance disabling texture coordinate generation will also prevent you from tweaking parameters related to texture coordinate generation. -When switching to parameter "1 Shader generation" you can enable or disable shader generation for the left window -If a state is needed that can not be solved by using a shader available in the shader cache, a new shader will be generated (see console for test output). I added a few screenshots of this application as attachment. The application allows you to switch between a few of the standard OSG models. Another feature is switching between debug shaders for displaying normals and depth. SHADER COMPOSITION DESIGN & IMPLEMENTATION The basic idea: ShaderMode In analogy to how the OpenGL FFP uses modes, ShaderModes are introduced that implement a piece of shader based functionality. StateAttributes are still used for controlling the pieces of functionality inside a ShaderMode. However this may now include setting specific uniforms instead of talking directly to the OpenGL API for setting state variables. The State class will know which ShaderModes are needed if State::apply is called. The collection of enabled ShaderModes form the set of wanted shader program functionality. It is the task of the ShaderGenerator class to process the given set of ShaderModes and produce a valid Shader Program. Each ShaderMode contains a list of input parameters that it needs to performs it's job and a list of output parameters that it will produce or modify. These lists will be used by the ShaderGenerator to link the ShaderModes and determine in what order their code will be written. A ShaderMode will typically not be used by front end users of OpenSceneGraph, because the modes will be enabled or disabled based on the usesMode mechanism available inside StateAttributes. A MultiShaderMode is a specialization of ShaderMode to handle multiple instances. This is used for instance for multiple textures or multiple clipping planes. It only adds an index value as member. In some cases it needs to care of things that only need to be done only once per class type (for instance function generation). ShaderGenerator: how it works * Shader Cache The shadergenerator is given a set of needed ShaderModes for a certain shader program. It first looks if this set of ShaderModes already exists in cache and immediately returns a previously generated shader program if found. * Building a shadermode tree The generator then gathers a collection of rootmodes. A rootmode is a ShaderMode that only has inputs and no outputs. Typically this will be the part of the shader that writes to gl_FragColor. A minimum of one rootnode is needed to be able to generate a ShaderMode tree. If none are found a default purple shader is returned for debugging purposes. If one or more valid root nodes are available the tree is built by searching for ShaderModes that can provide the inputs requested by the shadermode being processed. ShaderModes that provide the needed inputs will be added as a child node to the ShaderMode being processed. If no valid ShaderMode is found that can provide the input variable a constant value is used. * Building the vertex, geometry and fragment shaders Once the shadermode tree is complete the shader generation process is started. The shadermode tree is traversed several times for each of the defined shader blocks below. This occurs in a depth first order. There's a flag to prevent endless looping through the generated ShaderMode tree. These are the code generation phases that currently are implemented: vertexfunction vertexvars vertexinit vertexmain geometryfunction geometryvars geometryinit geometrymain fragmentfunction fragmentvars fragmentinit fragmentmain This will allow all ShaderModes in the tree to inject their code into the correct place. The generated Shader Program will be inserted in the cache and returned as an answer to the requested set of ShaderModes. Note that some ShaderModes may end up as orphans and will not be a part of the ShaderMode tree. This may happen for instance if lighting is disabled, but lights are requested. This is also the case if a debugging ShaderMode is used as root (for instance showing the color coded Eye space normal) instead of the common visual output ShaderMode. Of course there are a lot of things that are left to be desired, but hopefully this will be a good start for integration of shader composition in OpenSceneGraph. kind regards, Roland Smeenk ------------------ Read this topic online here: http://forum.openscenegraph.org/viewtopic.php?p=26536#26536 Attachments: http://forum.openscenegraph.org//files/truckdepth_671.jpg http://forum.openscenegraph.org//files/trucknormal_202.jpg http://forum.openscenegraph.org//files/truckvisual_159.jpg http://forum.openscenegraph.org//files/textureenv_487.jpg http://forum.openscenegraph.org//files/cowlightmaterial_898.jpg http://forum.openscenegraph.org//files/shader_composition_162.zip _______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
