Commit 3ee62319 authored by Jan Möbius's avatar Jan Möbius
Browse files

Added documentation for dshader generator

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@18238 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 09720add
......@@ -17,5 +17,6 @@ If you build OpenFlipper, the library will be automatically build and integrated
\li \subpage compiling_ACG
\li \subpage pickingDocumentation
\li \subpage NonFixedPipelinePage
\li \subpage ShaderGenPage
*/
/** \page ShaderGenPage Dynamic shader assembly overview
ACG supports shader generation at runtime and offers a modular shader assembly method.
The main class of interest is ShaderProgGenerator, which generates a complete GLSL program with a vertex, fragment and eventually geometry shader.
This page documents the assembly process of generated shaders and how ShaderModifers and templates will affect the process.
Supported GLSL versions are 1.5 and higher.
\section shaderFixed Fixed shader code
Some parts of shader code are fixed and will be available in any generated shader.
These include, but are not limited to:
- essential input uniforms (model-view-projection matrix, global lights..)
- essential input/output between two shader stages (ie. normal, texcoord)
- vertex transformation
- default lighting functions
- default texturing
\section namingConvention Naming convention
The following naming conventions for uniforms, stage input/output and local variables are used:
- Defines: prefix "SG_", all uppercase
- Uniforms: prefix "g_"
- Local variables: prefix "sg_"
- vertex shader input: prefix "in"
- vertex shader output: prefix "outVertex"
- geometry shader input: prefix "outVertex"
- geometry shader output: prefix "outGeometry"
- fragment shader input: prefix either "outVertex" or "outGeometry", depends if a geometry shader is active.
- fragment shader output: prefix "outFragment"
Modifiers and templates can not actually control any shader code provided by the ShaderGenerator,
but they can add additional code lines that may overwrite or extend the results of the generated code.
\section shaderUniforms Default defines
The ShaderGenerator writes the current configuration given in ShaderGenDesc to a shader with the help of defines.
These defines in the generated shader reflect the state of the active ShaderGenDesc.
Shading mode: defines in which stage lighting should be performed.
One of the following defines is generated based on the state of ShaderGenDesc::shadeMode.
\code
#define SG_GOURAUD 1 // only added iff shadeMode == SG_SHADE_GOURAUD
#define SG_FLAT 1 // only added iff shadeMode == SG_SHADE_FLAT
#define SG_UNLIT 1 // only added iff shadeMode == SG_SHADE_UNLIT
#define SG_PHONG 1 // only added iff shadeMode == SG_SHADE_PHONG
\endcode
If textures, vertex colors and or lighting is enabled in the descriptor, these defines are specified in the shader.
\code
#define SG_TEXTURED 1 // only added iff textured
#define SG_VERTEX_COLOR 1 // only added iff vertex colors are used
#define SG_NORMALS 1 // only added iff lighting is enabled ( shadeMode != SG_SHADE_UNLIT )
\endcode
Additionally the light setup is passed to the shader with the following defines.
\code
#define SG_NUM_LIGHTS N // N = numLights
#define SG_LIGHT_TYPE_X Y // type of light X where X = 0,...,N-1 and Y = SG_LIGHT_DIRECTIONAL,SG_LIGHT_POINT,SG_LIGHT_SPOT
\endcode
\section shaderUniforms Default uniforms
The following default uniforms are guaranteed to be added to any generated shader:
\code
mat4 g_mWVP; // proj * view * world matrix
mat4 g_mWV; // modelview matrix
mat3 g_mWVIT; // inverse transpose of modelview, used to transform direction vectors such as normals
mat4 g_mP; // projection matrix
vec3 g_vCamPos; // camera position in world space
vec3 g_vCamDir; // camera view direction in world space
vec3 g_cDiffuse; // diffuse color of material
vec3 g_cAmbient; // ambient color of material
vec3 g_cEmissive; // emissive color of material
vec3 g_cSpecular; // specular color of material
vec4 g_vMaterial; // other material parameters: vec4(shininess, alpha, 0, 0)
\endcode
The light configuration is added to a shader if it is supposed to do lighting.
If the shader descriptor defines that lighting has to be done via gouraud or flat shading,
these are added to the vertex shader.
Othwerise, in phong shading these are included in the fragment shader.
\code
vec3 g_cLightDiffuse_X; // diffuse color of light X
vec3 g_cLightAmbient_X; // ambient color of light X
vec3 g_cLightSpecular_X; // specular color of light X
\endcode
additionally for directional lights:
\code
vec3 g_vLightDir_X; // light direction in view space
\endcode
additionally for point lights:
\code
vec3 g_vLightPos_X; // light position in view space
vec3 g_vLightAtten_X; // distance attentuation factors: vec3(linear, quadratic, cubic)
\endcode
additionally for spot lights:
\code
vec3 g_vLightPos_X; // light position in view space
vec3 g_vLightDir_X; // light direction in view space
vec3 g_vLightAtten_X; // distance attentuation factors: vec3(linear, quadratic, cubic)
vec2 g_vLightAngleExp_X; // angle attenuation factors: vec2(cutoff angle, exponent)
\endcode
where X is replaced by the light index in range[0,.., numLight-1].
TextureSampler uniforms for a fragment shader are generated based on the number of specified textures in ShaderGenDesc:
\code
samplerY g_TextureX; // X: texture stage id = 0,...,numTextures-1 Y: samplerType ie. 1D, 2D, Cube, 2DRect..
\endcode
ShaderModifiers can add custom uniforms to a generated shader.
\section vertexIO Vertex shader IO
\code
// inputs from vertex buffer
in vec4 inPosition;
in vec3 inNormal; // only added iff shadeMode != SG_SHADE_UNLIT
in vecX inTexcoord; // only added iff textured, X = texture dimension
in vec4 inColor; // only added iff vertexColors were enabled in the ShaderGenDesc
// outputs
out vec4 outVertexPosCS; // position in clip space
out vecX outVertexTexcoord; // only added iff textured, X = texture dimension
out vec4 outVertexColor; // only added iff shadeMode == SG_SHADE_GOURAUD or SG_SHADE_FLAT
out vec3 outVertexNormal; // only added iff shadeMode == SG_SHADE_PHONG
out vec3 outVertexPosVS; // position in view space, only added iff shadeMode == SG_SHADE_PHONG
\endcode
ShaderModifers can add custom shader IO to any stage.
\section geometryIO Geometry shader IO
\code
// inputs from vertex shader
in vec4 outVertexPosCS[];
in vecX outVertexTexCoord[]; // only added iff textured, X = texture dimension
in vec4 outVertexColor[]; // only added iff vertexColors were enabled in the ShaderGenDesc, or shadeMode == SG_SHADE_GOURAUD or SG_SHADE_FLAT
in vec3 outVertexNormal[]; // only added iff shadeMode == SG_SHADE_PHONG
in vec3 outVertexPosVS[]; // only added iff shadeMode == SG_SHADE_PHONG
// outputs
out vec4 outGeometryPosCS; // position in clip space
out vecX outGeometryTexCoord; // only added iff textured, X = texture dimension
out vec4 outGeometryColor; // only added iff vertexColors were enabled in the ShaderGenDesc, or shadeMode == SG_SHADE_GOURAUD or SG_SHADE_FLAT
out vec3 outGeometryNormal; // only added iff shadeMode == SG_SHADE_PHONG
out vec3 outGeometryPosVS; // position in view space, only added iff shadeMode == SG_SHADE_PHONG
\endcode
\section fragmentIO Fragment shader IO
\code
// inputs from vertex shader, only if there is no geometry shader
in vec4 outVertexPosCS;
in vecX outVertexTexCoord; // only added iff textured, X = texture dimension
in vec4 outVertexColor; // only added iff vertexColors were enabled in the ShaderGenDesc, or shadeMode == SG_SHADE_GOURAUD or SG_SHADE_FLAT
in vec3 outVertexNormal; // only added iff shadeMode == SG_SHADE_PHONG
in vec3 outVertexPosVS; // only added iff shadeMode == SG_SHADE_PHONG
// if there is a geometry shader, fragment inputs are instead:
in vec4 outGeometryPosCS;
in vecX outGeometryTexCoord; // only added iff textured, X = texture dimension
in vec4 outGeometryColor; // only added iff vertexColors were enabled in the ShaderGenDesc, or shadeMode == SG_SHADE_GOURAUD or SG_SHADE_FLAT
in vec3 outGeometryNormal; // only added iff shadeMode == SG_SHADE_PHONG
in vec3 outGeometryPosVS; // only added iff shadeMode == SG_SHADE_PHONG
// outputs
out vec4 outFragment; // fragment color
\endcode
\section vertShaderGen Vertex shader code generation
Some parts of a generated shader contain fixed code snippets, which are assembled according to specification in ShaderGenDesc.
A vertex shader has the following code layout.
\code
void main(){
// ============================================================
// Generated begin code:
// read inputs from vertex buffer and initialize generated local variables
vec4 sg_vPosPS = g_mWVP * inPosition; // transform pos to projection space
vec4 sg_vPosVS = g_mWV * inPosition; // transform pos to view space
vec4 sg_cColor = vec4(g_cEmissive, ALPHA); // color (ALPHA: #define ALPHA g_vMaterial.y)
vec3 sg_vNormalVS = vec3(0,1,0); // unknown vertex normal at this point
#if SG_NORMALS
sg_vNormalVS = normalize(g_mWVIT * inNormal); // transform normal to view space
#endif
#if SG_TEXTURED
vecX sg_vTexCoord = inTexCoord;
#endif
#if SG_VERTEX_COLOR
sg_cColor = inColor;
#endif
#if SG_GOURAUD or SG_FLAT
sg_cColor += lightingCode();
#endif
// ============================================================
// Your ShaderModifier adds vertex shader code here.
// The modifier may overwrite any local variables from the shader generator.
for each modifier:
modifier->modifyVertexBeginCode();
// ============================================================
// Generated end code: pass local variables to next shader stage
gl_Position = sg_vPosPS;
outVertexPosCS = sg_vPosPS;
#if SG_TEXTURED
outVertexTexCoord = sg_vTexcoord;
#endif
#if SG_GOURAUD or SG_FLAT or SG_VERTEX_COLOR
outVertexColor = sg_cColor;
#endif
#if SG_PHONG
outVertexNormal = sg_vNormalVS;
outVertexPosVS = sg_vPosVS;
#endif
// ============================================================
// Shader modifiers are called again for the end code snippet.
// The modifers may write to gl_Position, outVertexNormal etc. and/or custom outputs
for each modifier:
modifier->modifyVertexEndCode();
}
\endcode
\note Note that if directives are not generated at all if they do not change the compiled code.
\section geomShaderGen Geometry shader code generation
Geometry shaders have a different layout and due to their complexity, there is no clear begin or end code marker for geometry shaders.
The ShaderProgGenerator does not generate a main() function for a geometry shader.
However, it provides a convenient passthrough mapping function from vertex shader outputs to fragment shader inputs:
The sg_MapIO function can be called in a geometry shader template.
\code
void sg_MapIO(const int inIdx)
{
gl_Position = gl_in[inIdx].gl_Position;
outGeometryPosCS = outVertexPosCS[inIdx];
#if SG_TEXTURED
outGeometryTexCoord = outVertexTexCoord[inIdx];
#endif
#if SG_SHADE_GOURAUD or SG_SHADE_FLAT
outGeometryColor = outVertexColor[inIdx];
#endif
#if SG_SHADE_PHONG
outGeometryNormal = outVertexNormal[inIdx];
outGeometryPosVS = outVertexPosVS[inIdx];
#endif
}
\endcode
The rest of geometry shader including the main() body has to be provided in the ShaderGenDesc in form of a template.
\section fragShaderGen Fragment shader generation
Fragment shaders are assembled similar to vertex shaders:
\code
void main(){
// ============================================================
// Generated begin code:
// read inputs from vertex/geometry shader:
vec4 sg_vPosCS = outVertexPosCS; // or outGeometryPosCS
vec2 sg_vScreenPos = sg_vPosCS.xy / sg_vPosCS.w * 0.5 + vec2(0.5, 0.5); // projective texture coordinates
vec4 sg_cColor = vec4(g_cEmissive, ALPHA); // color (ALPHA: #define ALPHA g_vMaterial.y)
#if SG_GOURAUD or SG_FLAT or SG_VERTEX_COLOR
sg_cColor += outVertexColor; // or outGeometryColor
#endif
#if SG_PHONG
vec4 sg_vPosVS = outVertexPosVS;
vec3 sg_vNormalVS = outNormal;
sg_cColor += lightingCode();
#endif
#if SG_TEXTURED
vec4 sg_cTex = 0;
for each texture stage X:
sg_cTex += texture(g_TextureX, outVertexTexCoord); // additive combine texture stages
#if SG_UNLIT
sg_cColor += sg_cTex; // additive blending
#else
sg_cColor *= sg_cTex; // multiplicative blending
#endif
#endif
#if
sg_cColor = inColor;
#endif
// ============================================================
// Your ShaderModifier adds fragment shader code here.
// The modifier may overwrite any local variables from the shader generator.
for each modifier:
modifier->modifyFragmentBeginCode();
// ============================================================
// Generated end code: pass color to output
outFragment = sg_cColor;
// ============================================================
// Shader modifiers are called again for the end code snippet.
// The modifers may write to outFragment, and/or custom outputs
for each modifier:
modifier->modifyFragmentEndCode();
}
\endcode
\section lightingCode Lighting code generation
The ShaderGenerator implements a forward lighting routine that supports any number of lights (within hardcoded SG_MAX_SHADER_LIGHTS limit) and any combination of light types.
However, it is possible to extend or even completely replace the default lighting routine with ShaderModifiers.
The default lighting routine performs the following steps.
\code
#for each light X:
#if X is directional:
sg_cColor += LitDirLight(sg_vPosVS, sg_vNormalVS, g_vLightDir_X, ..);
#else if X is point light:
sg_cColor += LitPointLight(sg_vPosVS, sg_vNormalVS, g_vLightPos_X, ..);
#else if X is spot light:
sg_cColor += LitSpotLight(sg_vPosVS, sg_vNormalVS, g_vLightPos_X, g_vLightDir_X, ..);
\endcode
A ShaderModifier can now choose to keep, extend or completely replace the lighting routine provided by the generator.
Keep in mind that since modifiers simply add more shader code to the existing routine, only commutative operations are supported correctly.
The modifyLightingCode function of a modifier receives a light index [0,...,numLights-1] and a light type [directional,point,spot] as arguments
and is supposed to compute a lighting color based on the uniforms provided by the generator.
Refer to the toon renderer plugin for an example, that implements custom cel lighting functions with a modifier.
*/
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment