![]() |
![]() |
![]() |
![]() |
We’ve done a number of improvements to our shaders support, and it starts with one big thing:
We have a new documentation how to use shaders with Castle Game Engine. Recommended reading! This documentation shows the most recommended way to use shaders in Castle Game Engine, combining simplicity with power:
- It starts with up-to-date explanation of why we recommend to use “shader effects” (
TEffectNode
) to express your shaders. -
It goes through simple practical examples: the most trivial shader, passing time to shader, passing texture to shader, converting eye<->world space (and what does it even mean).
-
Points interested readers to all the “advanced” topics and alternative ways to use shaders (sometimes more complicated).
We’ve also improvements to our engine API around shaders, to actually enable everything documented above:
- We added new
SetEffects
methods to easily connectTEffectNode
with higher-level components that are core of our engine (likeTCastleScene
) in the simplest possible way. These are: - We have improved our examples:
- grouped shader-related examples in examples/shaders/ subdirectory
- Added shader_effects_simple example (corresponds to the code we create in a tutorial-like sections of the docs).
- Added shader_effects_on_primitives example (simple test of
SetEffects
on primitives andTCastleImageTransform
). - Added shader_effects_on_background example (effects on
TCastleBackground
).
- We added property
shaderLibraries
(string list) to ourTEffectNode
. In Pascal you set it like this:1MyEffectNode.SetShaderLibraries(['castle-shader:/EyeWorldSpace.glsl']);Right now, the
castle-shader:/EyeWorldSpace.glsl
is the only possible value you can put there. But the system may be more flexible in the future, allowing us to expose more GLSL libraries (from the engine, usingcastle-shader:/
; other ideas may appear; note that you don’t need this to reuse shader setup in your own application, since you can just reuse ownTEffectPartNode
multiple times).Each “shader library” may define additional GLSL functions. It can also use
PLUG_xxx
of the shader, thus augmenting the rendering or computation. The uniform values necessary for the library are automatically passed by the engine, so you don’t need to know/do anything more to use it.The
castle-shader:/EyeWorldSpace.glsl
, in particular, defines 4 new GLSL functions, available in both fragment and vertex stages:12345vec4 position_world_to_eye_space(vec4 position_world);vec4 position_eye_to_world_space(vec4 position_eye);vec3 direction_world_to_eye_space(vec3 direction_world);vec3 direction_eye_to_world_space(vec3 direction_eye);Use them in your own shader code. Just make “forward declaration” for them first, like this (effect makes fog depending on point height in world space):
12345678910111213141516171819202122232425262728vec4 position_eye_to_world_space(vec4 position_eye);// Save value obtained in PLUG_fragment_eye_space to use in PLUG_fragment_modify.vec4 vertex_world;// Get the vertex position in world space.void PLUG_fragment_eye_space(const vec4 vertex_eye,inout vec3 normal_eye){vertex_world = position_eye_to_world_space(vertex_eye);}// Make lower things enveloped in fog (turn into gray).void PLUG_fragment_modify(inout vec4 fragment_color){const float fog_y_start = 0.5;const float fog_y_max = -5.0;if (vertex_world.y < fog_y_start) {const vec4 bottom_fog_color = vec4(0.1, 0.1, 0.5, 1);float factor = max(0.0,(vertex_world.y - fog_y_max) /(fog_y_start - fog_y_max));fragment_color = mix(bottom_fog_color, fragment_color, factor);}}The X3D file demonstrating this feature is here.
The Pascal example demonstrating this feature is here. The “Effect: cube map” is using this to get 3D direction from camera to rendered point, in world space, and then use this direction to query a cubemap (loaded from DDS).
This deprecates: our
Viewpoint.camera*Matrix
events. Their usage in practice was only to pass new uniforms to the shaders, but they were complicated to use, needed X3D Viewpoint node, routes, passing events… The new thing is trivial to setup if you already have code dealing with shaders usingTEffectPartNode
, in Pascal or in X3D. And it is trivial to implement too, it just does literally what you expect, i.e. adds extra GLSL code and makes sure it receives proper input (uniforms).
Have fun using shaders! And if you like it, please consider donating to support the engine development.
Start the discussion at Castle Game Engine Forum