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.
Note: Not all uniforms and attributes are available for every pipeline step, e.g. light source
parameters are only available when doing lighting calculations and particle specific data only when
rendering emitters.
General vector/matrix uniforms
| uniform mat4 worldMat |
matrix used for transforming vertex positions of currently rendered mesh to world space |
| uniform mat3 worldNormalMat |
matrix used for transforming tangent space basis of currently rendered mesh to world space |
| 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 vec4 shadowSplitDists |
split distances determining which of the four shadow maps has to be sampled |
| uniform mat4 shadowMats[4] |
light transformation matrices for individual shadow maps |
| uniform float shadowMapSize |
size of the shadow map texture in pixels |
| uniform float shadowBias |
bias used for shadow mapping to reduce precision issues |
| uniform vec4 skinMatRows[75*3] |
first three rows of skinning matrices for skeletal animation; fourth row is always (0, 0, 0, 1) |
| uniform vec2 frameBufSize |
dimensions (width and height) of the currently active frame buffer |
Particle specific vector/matrix uniforms
| uniform vec3 parCorners[4] |
four corner positions of particle billboard |
| uniform vec3 parPosArray[64] |
position array of particle batch |
| uniform vec2 parSizeAndRotArray[64] |
combined size and rotation array of particle batch |
| uniform vec4 parColorArray[64] |
color array of particle batch |
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 |
General vertex attributes
| attribute vec2 texCoords0 |
first set of texture mapping coordinates |
| attribute vec2 texCoords1 |
second 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 joints |
four joint indices referencing to skinning matrices |
| attribute vec4 weights |
four vertex weights for the four joint indices |
Particle specific vertex attributes
| attribute float parIdx |
index of current particle in position, size and color arrays |
| attribute float parCornerIdx |
index of current particle's corner in corners array |
Other data available in vertex shader
The vertex position is available through the attribute gl_Vertex.
The camera transformation is stored in the modelview matrix (gl_ModelViewMatrix) and the projection
matrix in gl_ProjectionMatrix. All overlays have their texture coordinates stored in
gl_MultiTexCoord0.
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. Most rendering commands use the attributes
class and context. The class is defined in the materials and determines what geometry should be
rendered. It is possible to use the tilde operator ~ as a logical NOT meaning that all geometry except
the one with the specified material class will be drawn. The context is finally available for specifying the
rendering technique which should be used for the current draw call.
Pipeline syntax
The following XML elements and attributes are supported.
| Pipeline |
root element of the document {1}
|
| EngineConfig |
configuration of engine options {1}
| trilinearFiltering |
see EngineOptions {optional}; additional values: false, true |
| anisotropyFactor |
see EngineOptions {optional} |
| texCompression |
see EngineOptions {optional}; additional values: false, true |
| loadTextures |
see EngineOptions {optional}; additional values: false, true |
| fastAnimation |
see EngineOptions {optional}; additional values: false, true |
| occlusionCulling |
see EngineOptions {optional}; additional values: false, true |
| shadowMapSize |
see EngineOptions {optional} |
| debugViewMode |
see EngineOptions {optional}; additional values: false, true |
|
| Setup |
initialization section of pipeline {0,1}
|
| RenderTarget |
definition of a render target; child of Setup element {*}
| id |
unique name of the render target {required} |
| depthBuf |
flag specifying whether depth buffer is used for target {required}; possible values: true, false |
| numColBufs |
number of color buffers {required}; possible values: 0, 1, 2, 3, 4 |
| format |
pixel format of render target {optional}; possible values: RGBA8, RGBA16F, RGBA32F; default: RGBA8 |
| bilinear |
flag specifying whether bilinear filtering is enabled for color buffers {optional}; possible values: true, false; default: false |
| width |
width of render target in pixels where 0 means width of the main framebuffer {optional}; default: 0 |
| height |
height of render target in pixels where 0 means height of the main framebuffer {optional}; default: 0 |
| scale |
scale factor which is multiplied with the size of the render target {optional}; default: 1.0 |
|
| CommandQueue |
ordered list of commands {0, 1}
|
| Stage |
definition of a set of render commands; child of CommandQueue element {*}
|
| SwitchTarget |
command for setting 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 Setup section or empty string to bind main framebuffer {required} |
|
| BindBuffer |
command for binding a color or depth buffer of a render target as texture map; child of Stage element {*}
| shaderIndex |
index of shader uniform (buf0-buf3) to which buffer is assigned {required}; possible values: 0, 1, 2, 3 |
| target |
name of render target {required} |
| bufIndex |
index of color buffer or 32 as special value for binding the depth buffer {required} |
|
| ClearTarget |
command for clearing the currently bound render target; child of Stage element {*}
| depthBuf |
flag specifying whether depth buffer is cleared {optional}; possible values: true, false; default: false |
| colBuf0 |
flag specifying whether first color buffer is cleared {optional}; possible values: true, false; default: false |
| colBuf1 |
flag specifying whether second color buffer is cleared {optional}; possible values: true, false; default: false |
| colBuf2 |
flag specifying whether third color buffer is cleared {optional}; possible values: true, false; default: false |
| colBuf3 |
flag specifying whether fourth color buffer is cleared {optional}; possible values: true, false; default: false |
| col_R |
red component of clear color {optional}; default: 0.0 |
| col_G |
green component of clear color {optional}; default: 0.0 |
| col_B |
blue component of clear color {optional}; default: 0.0 |
| col_A |
alpha component of clear color {optional}; default: 0.0 |
|
| DrawGeometry |
command for rendering the scene geometry; child of Stage element {*}
| context |
name of the shader context used for rendering {required} |
| class |
material class used for including/excluding objects {optional}; default: empty string, meaning all classes |
|
| DrawOverlays |
command for rendering all overlays; child of Stage element {*}
| context |
name of the shader context used for rendering {required} |
|
| DrawQuad |
command for drawing 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} |
|
| DoForwardLightLoop |
command for performing forward lighting by rendering all affected geometry; the shader context
used for rendering is the lighting context attribute of the corresponding light source;
child of Stage element {*}
| class |
material class used for including/excluding objects {optional}; default: empty string, meaning all classes |
|
| DoDeferredLightLoop |
command for performing deferred lighting by drawing screen-space quads; the shader used for rendering
is the one which is stored as attribute of the corresponding light source;
child of Stage element {*}
|
Sample showing simple deferred shading pipeline
<Pipeline>
<Setup>
<RenderTarget id="GBUFFER" depthBuf="true" numColBufs="3" format="RGBA16F" scale="1.0" />
</Setup>
<CommandQueue>
<Stage id="Attribpass">
<SwitchTarget target="GBUFFER" />
<ClearTarget depthBuf="true" colBuf0="true" />
<DrawGeometry context="ATTRIBPASS" class="~Translucent" />
</Stage>
<Stage id="Lighting">
<SwitchTarget target="" />
<ClearTarget colBuf0="true" />
<BindBuffer shaderIndex="0" target="GBUFFER" bufIndex="0" />
<BindBuffer shaderIndex="1" target="GBUFFER" bufIndex="1" />
<BindBuffer shaderIndex="2" target="GBUFFER" bufIndex="2" />
<DrawQuad material="light.material.xml" context="AMBIENT" />
<DoDeferredLightLoop />
</Stage>
<Stage id="Overlays">
<DrawOverlays context="OVERLAY" />
</Stage>
</CommandQueue>
</Pipeline>
Copyright © 2006-2007 Nicolas Schulz