The Flexible Rendering Pipeline

Introduction

The rendering pipeline defines the steps which are necessary to bring the abstract 3d data to a visible result on the screen. Up to version 0.9, Horde3D used deferred shading with lighting as a post processing step as the primary rendering technique. The subsequent version 0.10 introduces a new flexible rendering pipeline which makes it possible to employ a plenty of different rendering techniques, including standard forward rendering and deferred shading. The system allows to define several render targets and to specify render commands to fill the targets with data. This gives much power and flexibility to the engine and enables the creation of most post processing effects like HDR, motion blur or depth of field as well as the usage of different rendering algorithms.


System overview

Horde is heavily based on shaders which are small programs that are executed on the graphics card at different stages of the hardware pipeline. Horde uses vertex and fragment shaders. Vertex shaders influence directly the geometry which is rendered and determine e.g. the position and texture coordinates of the vertices. The fragment shaders are used for calculating the pixel colors in the rasterization process. Shader code in Horde is specified in the OpenGL Shading Language (GLSL). The engine has a XML based shader format which makes it possible to define different contexts. A context of a Horde shader is defined for a situation in the rendering process where the shader is executed. For example a shader usally has a shadowmap context which is used when shadows are generated and a lighting context which is responsible for interactions of an object with light sources. For the rendering process shaders usually require some input data. This consists on the one hand of the geometric data of a model like the vertex positions, normals and texture coordinates. On the other hand there are textures used for rendering and arbitrary variables, so called uniforms, which can be defined by the user. For example a uniform could be used to define a force vector to do some wind physics for a tree model in the vertex shader. This mutable data is bound to the shader via the concept of materials. A material in Horde consists of a shader and a list of texture maps and uniforms which are assigned to that shader.


Predefined GLSL attributes and uniforms

Horde defines some standard uniforms and attributes which can be used by shaders. The engine automatically detects which input data is required and binds it to the shader programs.

Vector uniforms

uniform vec3 viewer position of the viewer (virtual camera)
uniform vec4 lightPos position of the light source in xyz-components and radius in w-component
uniform vec3 lightDir direction vector of the light source
uniform vec3 lightColor (diffuse) color of the light source
uniform float lightCosCutoff cosine of the light's field of view (FOV) presumed it is a spotlight
uniform float bias bias used for shadow mapping to reduce precision issues
uniform mat4 skeleton[59] skinning matrices for skeletal animation


Sampler uniforms

uniform sampler2D shadowMap shadow map texture
uniform sampler[2D/Cube] tex0 texture unit 0
uniform sampler[2D/Cube] tex1 texture unit 1
uniform sampler[2D/Cube] tex2 texture unit 2
uniform sampler[2D/Cube] tex3 texture unit 3
uniform sampler[2D/Cube] tex4 texture unit 4
uniform sampler[2D/Cube] tex5 texture unit 5
uniform sampler[2D/Cube] tex6 texture unit 6
uniform sampler[2D/Cube] tex7 texture unit 7
uniform sampler2D buf0 first buffer of currently bound render target
uniform sampler2D buf1 second buffer of currently bound render target
uniform sampler2D buf2 third buffer of currently bound render target
uniform sampler2D buf3 fourth buffer of currently bound render target


Vertex attributes

attribute vec2 texCoords0 first set of texture mapping coordinates
attribute vec2 texCoords1 second set of texture mapping coordinates
attribute vec2 texCoords2 third set of texture mapping coordinates
attribute vec2 texCoords3 fourth set of texture mapping coordinates
attribute vec3 normal normal vector of vertex
attribute vec3 tangent tangent vector of vertex
attribute vec3 bitangent bitangent vector of vertex
attribute vec4 bones four joint indices referencing to skinning matrices
attribute vec4 weights four vertex weights for the four joint indices


Other data available in vertex shader

The vertex position is stored in the attribute gl_Vertex. The camera transformation is saved within the projection matrix (gl_ProjectionMatrix). Although that's generally no good style, it is very practical here since the world transformation of the currently rendered node can be stored in the ModelView matrix, accessible through gl_ModelViewMatrix and gl_NormalMatrix.


Pipeline configuration

The flexible rendering pipeline allows to define render targets and commands which determine the steps taken to render the scene. The commands are specified within a XML file.

Pipeline syntax

The following XML elements and attributes are supported.

Pipeline root element of the document {1}
Init initialization section of pipeline {0,1}
RenderTarget definition of a render target; child of Init element {*}
id name of the render target {required}
format pixel format of render target {required}; possible values: RGBA8, RGBA16F, RGBA32F
depth depth buffer is used for target {optional}; possible values: true, false; default: true
numBuffers number of color buffers {optional}; possible values: 1, 2, 3, 4; default: 1
scale size of the target calculated by multiplying the current viewport size with the scale factor {optional}; default: 1.0
Stage definition of a set of render commands {*}
SetTarget sets the currently active render target to which data is rendered; child of Stage element {*}
target name of the render target which was defined in the Init section or empty string to bind main framebuffer {required}
BindBuffers binds the buffers of a render target as texture maps; child of Stage element {*}
target name of the render target {required}
Clear clears the currently bound render target; child of Stage element {*}
depth depth buffer is cleared {optional}; possible values: true, false; default: false
buf0 first color buffer is cleared {optional}; possible values: true, false; default: false
buf1 second color buffer is cleared {optional}; possible values: true, false; default: false
buf2 third color buffer is cleared {optional}; possible values: true, false; default: false
buf3 fourth color buffer is cleared {optional}; possible values: true, false; default: false
r red component of clear color {optional}; default: 0.0
g green component of clear color {optional}; default: 0.0
b blue component of clear color {optional}; default: 0.0
a alpha component of clear color {optional}; default: 0.0
DrawGeometry renders the scene geometry; child of Stage element {*}
context name of the shader context used for rendering {required}
DrawOverlays renders all overlays; child of Stage element {*}
context name of the shader context used for rendering {required}
DrawFSQuad draws a fullscreen quad to the screen; child of Stage element {*}
material material resource used for rendering {required}
context name of the shader context used for rendering {required}
ForEachLight_DrawGeometry iterates through all active light sources and renders the scene geometry; child of Stage element {*}
ForEachLight_DrawShape iterates through all active light sources and draws the shapes of the light sources in a post processing step (used for deferred shading); child of Stage element {*}


Sample showing simple deferred shading pipeline

<Pipeline>

    <Init>
        <RenderTarget id="G-BUFFER" depth="true" numBuffers="3" format="RGBA16F" scale="1.0" />
    </Init>
        
    <Stage id="Setup">
        <SetTarget target="G-BUFFER" />
        <Clear depth="true" />
        <DrawGeometry context="G-BUFFER" />
    </Stage>
    
    <Stage id="Lighting">
        <SetTarget target="" />
        <Clear Clear buf0="true" />
        <BindBuffers target="G-BUFFER" />
        
        <ForEachLight_DrawShape />
    </Stage>
    
    <Stage id="Overlays">
        <DrawOverlays context="OVERLAY" />
    </Stage>
    
</Pipeline>


Copyright © 2006-2007 Nicolas Schulz