Shaders in Oolite: uniforms

From Elite Wiki
Revision as of 15:26, 7 June 2007 by Ahruman (talk | contribs)

Uniforms in Oolite Shaders

The information presented on this page applies to Oolite test release 1.69 and later.

A uniform in a shader is a variable whose value is specified by the host application – in this case, Oolite. Oolite allows arbitrary uniforms to be specified for shaders applied to ships, and these may either take constant values specified in shipdata.plist, or be “bound” to an attribute of the ship. This allows shader authors to access numerous properties of a game entity without having to ask for them and wait for an updated version of Oolite.

Basic syntax

Uniforms are specified in the materials or shaders dictionary of a ship’s shipdata.plist entry:

"ahruman_shady_cobra_example" =
{
    like_ship = "cobra3-player";
    shaders =
    {
        "cobra3_redux.png" =
        {
            textures = ( "cobra3_redux.png" );
            fragment_shader = "ahruman_shady_cobra_example.fragment";
            uniforms =
            {
                shininess =
                {
                    type = float;
                    value = 42.0;
                }
                withinAegis =
                {
                    type = binding;
                    value = "within_station_aegis";
                }
            }
        }
    }
}

This contrived example declares two uniforms, shininess and withinAegis. shininess is a constant float – it is always 42 – while withinAegis is bound to the ship’s within_station_aegis property. (See below for information on available properties.) This is a boolean, that is, a number whose value is either 0 (meaning no) or 1 (meaning yes). To use the uniforms within a shader (either a vertex shader or a fragment shader), they are declared as follows:

uniform float shininess;
uniform int withinAegis;
...
void main(void)
{
    if (withinAegis)
    {
         // Do aegis-specific effect here
    }
    ...
}

Uniform property types

Every bindable property has a type. The simplest types, int and float, correspond directly to the same types in GLSL. Both represent numbers, with the difference that a float can represent fractional values and very large values, but always has the same level of precision (about six digits), while ints can represent any integer (non-fractional value) in a limited range. (FIXME: what are the precision and range guarantees for GLSL?)

The vector type is translated to a GLSL vec4, whose x, y and z components correspond to those of the Oolite vector, and whose w component is always 1.0.

The quaternion type can be translated to a mat4x4 representing a rotation matrix, or to a vec4 whose x, y, z and w components correspond to those of the Oolite quaternion. IMPORTANT: in contexts such as property lists, quaternions are presented in the order w, x, y, z. However, GLSL vec4s use the order x, y, z, w. This doesn't matter if you access the components by name (as in myQuat.y or myQuat.wxyz), but does matter if you use indices (as in myQuat[1]). (FIXME: is this even valid in GLSL?)

The matrix type is translated into a GLSL mat4x4.

The colour type is translated into a GLSL vec4 type, whose r, g, b and a components correspond to those of the Oolite colour object.

Conversions

Several types of binding can be modified by conversion options, specified in the uniforms dictionary, for example:

haveFuel =
{
    type = binding;
    value = "fuel";
    clamped = true;
}

The clamped conversion option, when applied to a property of type float, causes the value to be clamped to the range [0, 1]. When applied to an int propertie, any value other than 0 (including negative values) is converted to 1. The default value is false.

The normalized option causes vector properties to be normalized, that is, scaled so they have the same direction but length 1. The default value is false.

The toMatrix option causes quaternion properties to be converted to rotation matrix, rather than having their components packed into a vec4. The default value is true.

Bindable property reference

The following sections list all properties of entities which can be used in a uniform binding, regardless of apparent usefullness. Note, however, that many of these names will change before the next stable release – in particular, it is intended that by Oolite 1.70 properties using underscores (a_property_name) will be converted to CamelCase (aPropertyName). This reflects ongoing clean-up activity within the Oolite code.

Entity

FIXME: fill in

Ship

Ships have all the properties of entities, and several others: FIXME: fill in

Player ship

The player ship has all the properties of entities and ships, and several others: FIXME: fill in