|Version 4 (modified by Philip, 14 months ago) (diff)|
The material system contains many components. Artists should just care about telling actors to use appropriate materials, and occasionally creating new material XML files by copying old ones and tweaking the uniforms. Graphical programmers might care about all the various shader files.
- Models are a single mesh with a single material and texture. (Actor XML files define how meshes and materials and textures are combined to make models. Actors can use props to combine multiple models for use by a single unit, but props are completely independent as far as the rendering is concerned, so we don't need to worry about them further.)
- Shader programs contain the low-level GPU code that performs per-vertex and per-fragment computation. (These might be implemented with GLSL, or with ARB assembly programs, or with fixed-function multitexturing code - the choice of implementation language is hidden from the rest of the system.)
- Attributes are the per-vertex data that shader programs use: vertex positions, normal vectors, colors, etc. The rendering engine computes all this data.
- Uniforms are the global or per-model data that shader programs use: camera position, sun color, specular highlight power, player color, etc. Some uniforms are computed by the rendering engine; others are specified by material definitions.
- Defines are name/value strings that control the behaviour of shader programs, e.g. USE_SPECULAR=1 to activate the code that computes specular lighting. Some defines come from the rendering engine; others from materials.
- Materials refer to a shader effect and specify various defines and uniforms.
- Shader techniques define how to combine one or more shader programs and other OpenGL state (e.g. alpha-blending behaviour) to render a model. (Usually a technique only uses a single program, but sometimes it needs to perform multiple passes over each model with a different program each time.)
- Rendering modes are the different ways the renderer processes each model. E.g. first it draws each model in the shadowmap generation mode to compute shadows, and later it draws each model in the standard textured lit mode.
- Shader effects control which shader technique to use in each different context, depending on rendering mode, hardware capabilities, user-selected graphics options, etc.
Various XML files can contain conditionals, which are typically attributes of the form if="...". These are C-preprocessor-style boolean expressions that can use the current set of defines, e.g.:
<alternative ... if="CFG_FORCE_ALPHATEST"/> <require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/> <whatever if="(FOO || !(BAR && BAZ)) && QUX > 100"/>
Located in art/materials/. Example:
<?xml version="1.0" encoding="utf-8"?> <material> <alternative material="alphatest_spec.xml" if="CFG_FORCE_ALPHATEST"/> <shader effect="model_transparent"/> <alpha_blending/> <define name="USE_TRANSPARENT" value="1"/> <define name="USE_SPECULAR" value="1"/> <uniform name="specularPower" value="16.0"/> <uniform name="specularColor" value="1.0 1.0 1.0"/> </material>
Materials can contain:
- (rarely used) <alternative material="..." if="..."/> - if the conditional expression is true, then this material will be replaced by the given alternative. This can be useful so e.g. alpha-blended materials can get replaced with alpha-tested materials depending on some configuration.
- (required) <shader effect="..."/> - refers to one of the effect XML files.
- (rarely used) <alpha_blending/> - required if using a shader effect that uses alpha-blending. (This causes the engine to render the model twice, in ALPHABLEND_PASS_OPAQUE and ALPHABLEND_PASS_BLEND passes, to get correct blending relative to transparent water.)
- (zero or more times) <define name="..." value="..."/> - specifies a name/value define that is used when loading the shader. The value is typically "1" to enable an effect.
- (zero or more times) <uniform name="..." value="..."/> - specifies a uniform value that is used when rendering models using this material. The value is between 1 and 4 space-separated decimal numbers, e.g. value="16" or value="1.0 1.0 0.0 0.5".
Set globally by engine code:
- USE_SHADOW - 1 when shadows are supported by the hardware and enabled by the user.
- USE_FP_SHADOW - 1 when GL_ARB_fragment_program_shadow is supported and enabled.
- USE_SHADOW_PCF - 1 when shadow PCF filtering is enabled.
- USE_SHADOW_SAMPLER - 1 when sampler2DShadow etc is supported in GLSL. (Unavailable on OpenGL ES.)
- SYS_HAS_ARB - 1 when GL_ARB_vertex_program/GL_ARB_fragment_program are supported, and the renderer is in shader mode.
- SYS_HAS_GLSL - 1 when GL_ARB_vertex_shader/GL_ARB_fragment_shader are supported, and the renderer is in shader mode.
- SYS_PREFER_GLSL - 1 when the preferGLSL option is enabled. (On by default on OpenGL ES.)
Set by engine code in different renderer modes:
- MODE_SHADOWCAST - 1 when rendering objects onto the shadow map. Only depth is needed, no color data.
- MODE_SILHOUETTEOCCLUDER - 1 when rendering objects that silhouettes may be displayed behind. Only depth is needed, no color data.
- MODE_SILHOUETTEDISPLAY - 1 when rendering objects that may be displayed as silhouettes. Should draw solid color playerColor.
- MODE_WIREFRAME - 1 when rendering wireframe or edged-face versions of models, for debugging.
- ALPHABLEND_PASS_OPAQUE - 1 when rendering the opaque alpha-tested pass of transparent models before water.
- ALPHABLEND_PASS_BLEND - 1 when rendering the alpha-blended pass of transparent models after water.
Set per model by engine code:
- IGNORE_LOS - 1 when the Vision component has the AlwaysVisible flag, meaning the LOS texture should not be used.
Set by materials:
- USE_OBJECTCOLOR - 1 when the objectColor uniform should be used.
- USE_PLAYERCOLOR - 1 when the playerColor uniform should be used. (Mutually exclusive with USE_OBJECTCOLOR.)
- USE_SPECULAR - 1 when specular lighting should be rendered. Requires the following uniforms:
- float specularPower - sharpness of specular highlights.
- vec3 specularColor - color and brightness (components can be larger than 1.0).
- USE_TRANSPARENT - 1 when the texture's alpha channel should be output by the fragment shader.
- DISABLE_RECEIVE_SHADOWS - 1 when shadows should not be cast onto this object.
Shader effects and techniques
Located in shaders/effects/. Example:
<?xml version="1.0" encoding="utf-8"?> <effect> <technique> <require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/> <require shaders="arb"/> <pass shader="arb/model_solid"/> </technique> <technique> <require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/> <require shaders="glsl"/> <pass shader="glsl/model_solid"/> </technique> <technique> <require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/> <require shaders="fixed"/> <define name="USE_PLAYERCOLOR" value="0"/> <define name="USE_OBJECTCOLOR" value="0"/> <pass shader="fixed:model_solid"/> </technique> ... <technique> <require context="ALPHABLEND_PASS_BLEND"/> <require shaders="fixed"/> <sort_by_distance/> <pass shader="fixed:model"> <define name="USE_TRANSPARENT" value="1"/> <alpha func="gequal" ref="0.05"/> <blend src="src_alpha" dst="one_minus_src_alpha"/> <depth func="less" mask="false"/> </pass> </technique> </effect>
An <effect> contains one or more <technique>s. Each technique can have a set of requirements:
- <require context="..."/> - an arbitrary conditional expression. (This can refer to defines that come from the material, or the current rendering mode, or the global rendering context.)
- <require shaders="glsl"/> - requires that GLSL shaders are supported and enabled.
- <require shaders="arb"/> - requires that ARB shaders are supported and enabled.
- <require shaders="fixed"/> - requires that fixed-function (OpenGL 1.4ish) rendering is supported and enabled.
Whenever a material tries to use an effect, the most preferred technique whose requirements are satisfied will be used. There must always be at least one usable technique in each effect. Typically, techniques that are defined earliest in the XML file will be preferred over techniques defined later. The exception is if the preferglsl config option (or renderer.preferGLSL in the console) is true, techniques requiring GLSL will always be more preferred than others; if preferglsl is false (the default), then ones requiring GLSL will always be less preferred.
<technique> can also contain:
- (zero or more) <define name="..." value="..."/> - add a new define which may be used by the technique's shader programs.
- (rarely used) <sort_by_distance/> - required if the technique includes a pass that uses non-commutative alpha-blending. (This causes the engine to sort models from furthest to nearest before rendering, to get correct alpha-blending behaviour.)
- (one or more) <pass shader="..."> - see below.
A pass is a rendering of a collection of models with a single set of OpenGL state (shader, blending settings, etc). Most techniques only use a single pass, but it's possible to do multi-pass rendering (e.g. do one pass that just writes depth data, and a second pass that writes colour on top of it).
Every pass is rendered with a shader program (via the shader="..." attribute). <pass> can also contain:
- (zero or more) <define name="..." value="..."/> - add a new define which may be used by the pass's shader program.
- <alpha func="..." ref="..."/> - equivalent to glAlphaFunc(func, ref). ref is a float. func can be one of never, always, less, lequal, equal, gequal, greater, notequal.
- <blend src="..." dst="..."/> - equivalent to glBlendFunc(src, dst). src and dst can be one of zero, one, (one_minus_)?(src|dst|constant)_(color|alpha), src_alpha_saturate.
- <depth func="..."/> - equivalent to glDepthFunc(func). func can be the same values as <alpha func>.
- <depth mask="..."/> - equivalent to glDepthMask(mask). mask can be true or false.