The effect framework makes it easy to write custom shader code that combines with existing shaders. There is no need to re-implement the entire shader pipeline anymore (vertex transformation, lighting, fog, etc..). You just write a few lines of code and Vizard will automatically combine it with existing effects to generate the full shader.
Shader effects are defined using a simple syntax (sections within brackets [] are optional):
This is an optional string that allows assigning an arbitrary name to the effect. The name does not affect the functionality, but can be accessed in the script using the <effect>.getName command.
This section allows defining optional properties and input uniforms of the effect.
This declares the type of the effect. The type name can be an arbitrary string. When Vizard generates the full shader code using all the applied effects, it will only use one effect per unique type name. This allows both the use of multiple effects by using different type names and the ability to override existing effects by using the same type name. If no type is specified, then default will be used. The built-in generated material effects use the default type name, so it is recommended to use the default type if you want to use the effect to set the base material values. The effect type name can be accessed in the script using the <effect>.getTypeName command.
The table below lists some type names used by other built-in effects. You can use these type names if you wish to override the corresponding effect:
Type | Descripton |
AmbientLight | Used by the default ambient light effect. Use this type name if you wish to create a custom ambient lighting model. |
LightingModel | Used by the default lighting model effect. Use this type name if you wish to create a custom lighting model. |
Fog | Used by the default fog effect. Use this type name if you wish to create a custom fog effect. |
Creates a 2D texture property.
name: The name to use for the texture uniform. Must be a valid shader uniform name.
coordUnit: The texture coordinate unit to assign to the texture. If the value is greater than or equal to 0, then the UV coordinates for the texture can be accessed within the shader code using the uv<name> variable, where <name> is the property name. If the value is -1, then no UV coordinates are assigned to the texture, and it is assumed the UV coordinates are dynamically generated within the shader.
unit: The texture unit to assign to the texture property. If the value is greater than or equal to 0, then the effect will use whatever texture is already assigned on that unit. If the value is -1, then the effect will assume that either the texture uniform is manually applied or that the texture is specified using the <effect>.setProperty command.
Creates a cubemap texture property.
name: The name to use for the texture uniform. Must be a valid shader uniform name.
coordUnit: The texture coordinate unit to assign to the texture. If the value is greater than or equal to 0, then the UV coordinates for the texture can be accessed within the shader code using the uv<name> variable, where <name> is the property name. If the value is -1, then no UV coordinates are assigned to the texture, and it is assumed the UV coordinates are dynamically generated within the shader.
unit: The texture unit to assign to the texture property. If the value is greater than or equal to 0, then the effect will use whatever texture is already assigned on that unit. If the value is -1, then the effect will assume that either the texture uniform is manually applied or that the texture is specified using the <effect>.setProperty command.
Creates a float property.
name: The name to use for the float uniform. Must be a valid shader uniform name.
value: A space-delimited list specifying the default float values. The length of the list determines the type of the uniform (1=float, 2=vec2, 3=vec3, 4=vec4). The value can be modified in script using the <effect>.setProperty command. If not specified, it will default to a single value of 0.
Creates an integer property.
name: The name to use for the integer uniform. Must be a valid shader uniform name.
value: A space-delimited list specifying the default integer values. The length of the list determines the type of the uniform (1=int, 2=ivec2, 3=ivec3, 4=ivec4). The value can be modified in script using the <effect>.setProperty command. If not specified, it will default to a single value of 0.
Creates a boolean property.
name: The name to use for the boolean uniform. Must be a valid shader uniform name.
value: A space-delimited list specifying the default boolean values. The length of the list determines the type of the uniform (1=bool, 2=bvec2, 3=bvec3, 4=bvec4). The value can be modified in script using the <effect>.setProperty command. If not specified, it will default to a single value of 0.
Creates a matrix property.
name: The name to use for the matrix uniform. Must be a valid shader uniform name.
value: A space-delimited list specifying the default matrix values. The length depends on the type of matrix specified (Matrix2=4, Matrix3=9, Matrix4=16). The value can be modified in script using the <effect>.setProperty command.
This declares the texture coordinate unit to use to generate tangent/binormal values for bump mapping. This should only be specified if a tangent space normal map is being used by the effect.
This section is where the actual shader code is defined for the effect. Multiple shader units can be defined, allowing an effect to insert code into multiple stages of the shader pipeline. Each shader unit is defined using the following syntax:
The section name of the shader pipeline to insert the code into. The default effect composer created by the vizfx library provides the following sections for inserting code into:
Name | Shader | Description |
FragmentHeader | Fragment | Allows declaring optional functions or varying/uniform inputs for the fragment shader. |
FragmentInit | Fragment | Called at the beginning of the fragment shader. Can be used to discard fragments based on custom clip volumes. |
Material | Fragment |
Material properties of the pixel are applied to the material structure m. The material structure contains the following fields:
|
PostMaterial | Fragment | Post-processing of material properties can be applied to the material structure m. |
Ambient | Fragment | Global ambient color is added to g.ambient variable. |
Lighting | Fragment |
Lighting is applied here to the light structure light. The light structure contains the following fields:
Once the light fields are set, the light must be applied using the following code: vizfx_AddLight(light); |
DiffuseModel | Fragment | Global diffuse light color is added to g.diffuse variable. This is called once for each light within a separate function that takes as input the material structure m, light structure l, and view direction viewDir. |
SpecularModel | Fragment | Global specular light color is added to g.specular variable. This is called once for each light within a separate function that takes as input the material structure m, light structure l, and view direction viewDir. |
FinalColor | Fragment | Called at the end of the fragment shader to allow making adjustments to the final pixel color by modifying the gl_FragColor value. |
VertexHeader | Vertex | Allows declaring optional functions or varying/uniform inputs for the vertex shader. |
PreTransform | Vertex |
Called before the vertex data is transformed by the ModelViewProjection matrix. The following vertex values can be modified:
|
PostTransform | Vertex | Called after vertex data is transformed by the ModelViewProjection matrix. |
The actual shader code to insert into the specified section of the shader pipeline. See the table above for variables that can be accessed/modified for each stage. Additionally, the default effect composer created by the vizfx library provides the following commonly used values:
Name | Type | Description |
viewDir | vec3 | Normalized direction vector of vertex/pixel to view. This will be in the same coordinate system as the material normal vector (m.normal) and the light direction vector (light.direction). The coordinate system may be in eye space or tangent space, depending on whether VIZFX_TANGENT_SPACE is defined. |
vizfx_VertexColor | vec4 | The vertex/material color. |
vizfx_ViewDistance | float |
Distance between the view and vertex/pixel. |
vizfx_WorldViewDir | vec3 | Normalized direction vector of the vertex/pixel to view in world coordinates. |
vizfx_WorldPos | vec3 | Position of vertex/pixel in world coordinates. |
vizfx_WorldNormal | vec3 |
Normalized normal vector of vertex/pixel in world coordinates. |
vizfx_WorldReflect | vec3 | Normalized view/normal reflection vector in world coordinates. |
vizfx_EyeViewDir | vec3 | Normalized direction vector of the vertex/pixel to view in eye coordinates. |
vizfx_EyePos | vec3 | Position of vertex/pixel in eye coordinates. |
vizfx_EyeNormal | vec3 | Normalized normal vector of vertex/pixel in eye coordinates. |
vizfx_EyeReflect | vec3 |
Normalized view/normal reflection vector in eye coordinates. |
vizfx_ScreenPos | vec2 | Position of pixel in normalized screen coordinates. |
vizfx_PixelPos | vec2 | Position of pixel in viewport coordinates. |
vizfx_CubeNormal | vec3 | World normal vector in cubemap texture coordinates. |
vizfx_CubeReflect | vec3 | World reflection vector in cubemap texture coordinates. |
vizfx_SphereReflect | vec2 | 2D sphere map texture coordinates. |
vizfx_TangentWorldMatrix | mat3 | Matrix to convert tangent space vector to world coordinates. |
vizfx_TangentEyeMatrix | mat3 | Matrix to convert tangent space vector to eye coordinates. |
VIZFX_TANGENT_SPACE | #define | Defined when the shader normal is in tangent space coordinates. |
VIZFX_LIGHTING | #define | Defined when lighting is enabled. |
VIZFX_FOG | #define | Defined when fog is enabled. |
The viz.addEffect command is used to load an effect from code or a file. Here we load an effect from code:
Once an effect is created, it can be applied to a model using the <node>.apply command:
The effect can also be added to a composer object. All objects with the composer applied, will also inherit the effect. If an effect of the same type is added to an object and the composer, the effect applied to the object will take precedence over the effect added to the composer. Here we add an effect to the default composer of the vizfx library:
Effects can be dynamically disabled and enabled using the <effect>.setEnabled command. Effects are enabled by default. Here we disable an effect:
The <effect>.setProperty command can be used to dynamically change the value of an effect property. For example, the following effect defines a MyColor property that is initialized to white. After the effect is loaded, the property value is changed to red.
The above code changes the color for all objects using the effect. However, effect properties can be overridden on a per model basis. Using the <node>.setUniformFloat command, we can override the effect property value with a custom value:
An effect can be unapplied from all previous nodes and composers using the <effect>.unapply command: