Kambi VRML game engine
← Users Developers →
 
Intro and News
 
view3dscene
 
The Castle
 
All Programs
 
Forum
 
Engine
 
VRML/X3D
 
Other
 

Programmable shaders component

This component defines nodes for using high-level shading languages available on modern graphic cards.

See also X3D specification of Programmable shaders component.

Teapot VRML model rendered with toon shading in GLSL
This movie shows GLSL shaders by our engine. You can also get AVI version with much better quality

ComposedShader and ShaderPart nodes allow you to write shaders in the OpenGL shading language (GLSL).

  • Basic example.

    Add inside Appearance node VRML code like

    shaders ComposedShader {
    language "GLSL"
    parts [
      ShaderPart { type "VERTEX" url "glsl_phong_shading.vs" }
      ShaderPart { type "FRAGMENT" url "glsl_phong_shading.fs" }
    ]
    }
    

    See Kambi VRML test suite, directory x3d/shaders/ for working demos of this.

  • Inline shader source code.

    You can directly place shader source code inside of an URL. We recognize URL as containing direct shader source if it has any newlines and doesn't start with any URL protocol, example: shaders_inlined.x3dv.

    This is a non-standard extension (although compatible at least with InstantPlayer).

  • Passing values to to GLSL shader uniform variables.

    You can also set uniform variables for your shaders from VRML, just add lines like

    inputOutput SFVec3f UniformVariableName 1 0 0
    
    to your ComposedShader node. These uniforms may also be modified by VRML events (when they are inputOutput or inputOnly), for example here's a simple way to pass current VRML time (in seconds) to your shader:
    # ......
    # somewhere within Appearance:
    shaders DEF MyShader ComposedShader {
    language "GLSL"
    parts [
      ShaderPart { type "VERTEX" url "my_shader.vs" }
      ShaderPart { type "FRAGMENT" url "my_shader.fs" }
    ]
    inputOnly SFTime time
    }
    
    # ......
    # somewhere within grouping node (e.g. at top-level of VRML file)
    DEF MyTimer TimeSensor { loop TRUE }
    ROUTE MyTimer.time TO MyShader.time
    

    Setting uniform values this way, from VRML fields/events, is supported for all required by spec types. So you can use VRML/X3D vector/matrix types to set GLSL vectors/matrices, you can use VRML/X3D multiple-value fields to set GLSL array types and such.

    TODO: SFImage, MFImage field types are not supported yet.

  • Passing textures to to GLSL shader uniform variables.

    You can also specify texture node (as SFNode field, or an array of textures in MFNode field) as a uniform field value. Engine will load and bind the texture and pass to GLSL uniform variable bound texture unit. This means that you can pass in a natural way VRML texture node to a GLSL sampler2D, sampler3D, samplerCube, sampler2DShadow and such.

    shaders ComposedShader {
    language "GLSL"
    parts [
      ShaderPart { type "FRAGMENT" url
      "  uniform sampler2D texture_one;
         uniform sampler2D texture_two;
    
         void main()
         {
           gl_FragColor = gl_Color *
             max(
               texture2D(texture_one, gl_TexCoord[0].st),
               texture2D(texture_two, gl_TexCoord[1].st));
         }
      " }
    ]
    initializeOnly SFNode texture_one ImageTexture { url "one.png" }
    initializeOnly SFNode texture_two ImageTexture { url "two.png" }
    }
    

    A full working version of this example can be found in Kambi VRML test suite (look for file x3d/shaders/simple_multitex_shaders.x3dv), or see it here.

    When using GLSL shaders in X3D you should pass all needed textures to them this way. Normal appearance.texture is ignored when using shaders. However, in our engine, we have a special case to allow you to specify textures also in traditional appearance.texture field: namely, when ComposedShader doesn't contain any texture nodes, we will still bind appearance.texture. This e.g. allows you to omit declaring texture nodes in ComposedShader field if you only have one texture, it also allows renderer to reuse OpenGL shader objects more (as you will be able to DEF/USE in X3D ComposedShader nodes even when they use different textures). But this feature should not be used or depended upon in the long run.

    Note that for now you have to pass textures in VRML/X3D events. Using inputOnly event to pass texture node to GLSL shader will not work.

  • TODO

    TODO: attributes for shaders in VRML are not yet passed. They are implemented in the engine classes of course, it's only a matter of implementing link between VRML and them. If you have some interesting VRML / X3D models that use these programmable shaders features, feel free to contact me and I'll implement them in our engine.

    (I mean, I will implement them anyway some day, but it's always much more interesting to implement features when you actually have a real use for them... In other words, I'm just dying to see some beautiful VRML/X3D models that heavily use programmable shaders :).

    TODO: activate event doesn't work to relink the GLSL program now. (isSelected and isValid work perfectly for any X3DShaderNode.)