Shader System

As previously described, RC has support for a variety of renderer backends. Each of these can have vastly different underlying systems for handling shaders. RC tries to incorporate a fairly simple and uniform way to handle shading functionality from the applications perspective.

A new shader program can be created using SceneGraph::createShaderProgram(). The main parameter to this function call is a simple string, the shader_name. The shader_name will be passed to the active Renderer which is responsible for interpreting the string and make something useful of it. Depending on the Renderer's underlying shading system, this interpretation can vary.

Let's consider the OpenGL 2.0 renderer as an example. This Renderer will look for the shader_name.gl20.vs and shader_name.gl20.fs (vertex- and fragment shader source) in the res/shaders/gl20/ folder. If the files exists, it will compile and link these two shaders in to a shader program, and then it's ready for use.

The ShaderProgram resource that results from the create-call is applied to Geometry nodes and used when those nodes are rendered.

Once the shader program is properly set up, there must be some means of populating the variables in the shader program from the application side. The communication is done through uniform variables.

In RC two classes can carry uniform values - the ShaderProgram resource and the Geometry node. The reason for this is that some uniforms should be applied on a shader program-basis, and others on a mesh-basis.

Take a look at the Uniform class to see which uniform types that can be used. (The Geometry- and ShaderProgram classes both have the same set of functions found in Uniform, so you don't have to fetch the any Uniform-object to set the uniform values.)

When a Geometry node is sent for rendering, it will first relay all of the attached ShaderProgram's uniform values, and then the uniforms carried by the Geometry node itself. This means that Geometry uniform variables override those of the ShaderProgram.

We argued whether more nodes and resources should have the capability to carry uniform values, but decided against it, as the complexity vs. usefulness is too poor. You'll just have to apply your uniform values to multiple Geometry nodes.

A Geometry node can be part of multiple rendering passes involving different shaders. For example, shadow maps require a rendering of the scene using one ShaderProgram from a light sources point of view, and another from the camera using a second ShaderProgram.

To quickly switch between these two shaders, you can use the render pass- functions found in the Geometry class. In the setup, first name two render passes ("from light" and "from camera" for instance) using the Geometry::addRenderPass() function. Second, set the ShaderPrograms for each object in the scene using Geometry::setShaderProgram() (the one with the render_pass argument.) Now, for each frame, set the current render pass to the first pass name "from light" using Geometry::setRenderPass() and render. Switch to the other render pass, "from camera", and render again - voila!

 All Classes Functions