[[TOC]] The material system contains many components. Artists should just care about telling [wiki:Actors 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. To see the status of various graphics features, see GraphicsFeatureStatus. == Definitions == * '''Models''' are a single mesh with a single material and texture. ([wiki:Actors#ActorXMLformat 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.) * '''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.) * '''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. Unlike attributes, they remain constant while rendering an entire model. * '''Defines''' are name/value strings that modify the behaviour of shader programs, e.g. `USE_SPECULAR=1` to activate the code that computes specular lighting, as with `#define`/`#ifdef` in the C preprocessor. They can also influence the selection of shader techniques. Some defines come from the rendering engine; others from materials. * '''Texture Samplers''' are what define textures in shader programs. They are required by materials using a `` tag and are defined in the actors. * '''Materials''' combine a shader effect with various defines and uniforms that specialize its behavior. * '''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 (with the define `MODE_SHADOWCAST=1`), and later it draws each model in the standard textured lit mode (without any special `MODE_` define). * '''Shader effects''' control which shader technique to use in each different context, depending on rendering mode, hardware capabilities, user-selected graphics options, etc. == Conditionals == 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.: {{{ #!xml }}} == Materials == Located in [source:ps/trunk/binaries/data/mods/public/art/materials art/materials/]. Example: {{{ #!xml }}} Materials can contain: * (rarely used) `` - 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) `` - refers to one of the [source:ps/trunk/binaries/data/mods/public/shaders/effects effect XML files]. * (rarely used) `` - 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) `` - 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) `` - 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"`. * (zero or more times) `` - specifies that this material requires a texture sampler of the same name. The name itself is only a hint at what this texture will be used for. `define` is used as a shortcut if this texture requires a "define" to be used. See existing materials. == Defines == Defines can come from many places: first from the engine, and then from ``s inside ``, ``, ``, ``, and from `#define` in the source files, in that order. At each stage, conditionals can refer to the defines from all earlier stages. If a name is defined that was already defined in an earlier stage, its value will be overridden. There's no way to undefine a name, but defining it to `0` should have the same effect. (Shader source files should use `#if` instead of `#ifdef` to correctly handle values of `0`.) The system of defines and conditionals can support many different ways to implement desired behaviour: to implement two materials, you could have two different shader effects, or one effect with two techniques, or one technique with conditionals to select two paths through the code. Performance is the same with any of those, so good design requires a judgement call to maximise clarity (avoid code duplication, avoid complex conditionals, etc). Current defines: (this is likely to get outdated, so check the code to verify) 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 [source:ps/trunk/binaries/data/mods/public/shaders/effects shaders/effects/]. Example: {{{ #!xml ... }}} An `` contains one or more ``s. Each technique can have a set of requirements: * `` - an arbitrary conditional expression. (This can refer to defines that come from the material, or the current rendering mode, or the global rendering context.) * `` - requires that GLSL shaders are supported and enabled. * `` - requires that ARB shaders are supported and enabled. * `` - requires that fixed-function (OpenGL 1.3ish) 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. `` can also contain: * (zero or more) `` - add a new define which may be used by the technique's shader programs. * (rarely used) `` - 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) `` - 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). `` can also contain: * (zero or more) `` - add a new define which may be used by the pass's shader program. * `` - equivalent to `glAlphaFunc(func, ref)`. `ref` is a float. `func` can be one of `never`, `always`, `less`, `lequal`, `equal`, `gequal`, `greater`, `notequal`. * `` - equivalent to `glBlendFunc(src, dst)`. `src` and `dst` can be one of `zero`, `one`, `(one_minus_)?(src|dst|constant)_(color|alpha)`, `src_alpha_saturate`. * `` - equivalent to `glDepthFunc(func)`. `func` can be the same values as ``. * `` - equivalent to `glDepthMask(mask)`. `mask` can be `true` or `false`. == Shader programs == GLSL shaders are in [source:ps/trunk/binaries/data/mods/public/shaders/glsl shaders/glsl/]. ARB shaders are in [source:ps/trunk/binaries/data/mods/public/shaders/arb shaders/arb/]. Fixed-function 'shaders' are in [source:ps/trunk/source/graphics/ShaderProgramFFP.cpp ShaderProgramFFP.cpp] and will be discussed later. ARB shaders are defined by an XML file like: {{{ #!xml }}} GLSL shaders are defined by an XML file like: {{{ #!xml }}} `` must contain a `` and ``, referring to the ARB/GLSL source files. The vertex and fragment shaders are loaded and linked to create the complete program. `` can contain zero or more ``, which will apply to its vertex/fragment shaders. Any child element of ``/`` may have an `if="..."` attribute. If the conditional expression is false, the whole child element will be ignored entirely. `` can contain: * `` - requests that the engine provide a stream of per-vertex data. `name` can be `pos`, `normal`, `color`, `uv0`, `uv1`, `uv2`, `uv3`. The semantics of the streams (especially the UVs) is controlled by the rendering engine. For performance, shaders should only request streams that they actually use. === ARB shaders === Vertex streams (activated via ``) are automatically bound to the standard ARB-shader attribute symbols: `vertex.position`, `vertex.normal`, `vertex.color`, `vertex.texcoord[0]` etc. `` and `` can both contain: * `` - binds a name to a local parameter location. The ARB program can read these via "`PARAM sunColor = program.local[0];`" etc. `type` can be one of `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, though it doesn't actually do anything since the only type supported by ARB programs is `vec4`. * `` - binds a name to a texture unit. The ARB program can read these as `texture[0]` etc. `type` can be one of `sampler2D`, `sampler2DShadow`, `samplerCube`. Note that local parameters and texture units are totally separate, so the same `loc` may be used for one of each. Also note that `mat4` takes 4 consecutive locations, so if you define a `` then the next free slot is `loc="5"`. === GLSL shaders === Unlike ARB shaders, the uniforms and texture units in GLSL shaders are determined automatically (via `glGetActiveUniform` etc), so you don't need to define them in the XML. We use a subset of GLSL that largely corresponds to GLSL ES 1.00 and non-deprecated GLSL 1.30 - in particular, there is no `gl_Vertex` or `gl_Normal` etc, only generic vertex attributes. Therefore, `` must contain: * `` - defines a binding between a named attribute in the vertex shader, and vertex data semantics. The `semantics` can be one of: * `gl_Vertex` * `gl_Normal` * `gl_Color` * `gl_SecondaryColor` * `gl_FogCoord` * `gl_MultiTexCoord0` to `gl_MultiTexCoord7` * `CustomAttribute0` to `CustomAttribute2` E.g. the XML file says ``, and the GLSL file says "`attribute vec3 a_vertex;`". === Fixed-function shaders === 'Fixed-function' refers to the OpenGL 1.3 era of `glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)` multi-texturing. These aren't really shaders but we use the same API as for the ARB/GLSL shaders, to simplify the rendering code. Unlike ARB/GLSL shaders, these aren't defined by XML files at all. Instead, a shader technique says e.g. `` with the magic "`fixed:`" prefix, and [source:ps/trunk/source/graphics/ShaderProgramFFP.cpp CShaderProgram::ConstructFFP] returns an appropriate hard-coded implementation. == Shader source files == ARB vertex/fragment program source files have extensions `.vp` and `.fp` in [source:ps/trunk/binaries/data/mods/public/shaders/arb shaders/arb/]. GLSL vertex/fragment shader source files have extensions `.vs` and `.fs` in [source:ps/trunk/binaries/data/mods/public/shaders/glsl shaders/glsl/]. All source files are passed through a custom preprocessor before being compiled. This recognises basic C preprocessor syntax (`#if`, `#ifdef`, `#define`, etc; unfortunately not `#elif`), and can refer to the defines from all the earlier XML files (passes, techniques, materials, rendering mode, global renderer context, etc). ARB files should start with "`!!ARBfp1.0`" or "`!!ARBvp1.0`". GLSL files should start with "`#version 120`" (GLSL 1.20 is the lowest version we should bother supporting, and corresponds to GLSL ES 1.00 which should be the highest we require). Otherwise they're just standard ARB/GLSL shaders, so refer to standard shader-writing documentation.