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.)