Materials encapsulate the textures, shaders, shader-constants, and render-states that are needed to draw geometry in Torque3D. Materials are defined in script files and have a wide variety of possible data fields, which tie directly to members of the C++ class Material (found in Engine/source/materials/materialDefinition.h). These values are then used to create a subclass of ProcessedMaterial. This document will focus on ProcessedShaderMaterial (found in Engine/source/materials/processedShaderMaterial.h) but familiarity with the ProcessedMaterial base class is recommended. Here is an example of a Material defined in script:
When a ProcessedShaderMaterial is initialized, it will first get handles for the textures defined in the Material, by calling ProcessedMaterial::_setStageData(). This method associates the source textures with a stage, and a FeatureType. Feature types are prefixed with MFT_, for example MFT_DiffuseMap. These feature types can be found in Engine/source/materials/materialFeatureTypes.h. To declare a new feature type use the DeclareFeatureType() macro. Use the ImplementFeatureType() macro to specify how and in-what-order the feature should be used (this will be discussed in greater detail later).
Once textures have been loaded, the ProcessedShaderMaterial initialization code determines the material features which should be enabled for each stage, based on what texture handles have been successfully created, and the values on the members of the Material. This is first performed in ProcessedShaderMaterial::_determineFeatures() and is then optionally validated/modified by a delegate. ProcessedShaderMaterial::_createPasses() is then called to create the shaders and constant-buffer handles for each pass defined by the Material.
During shader creation is where the ShaderGen system comes into play. The command SHADERGEN->getShader() is invoked, with parameters specifying the features requested, and the format of the vertex stream. ShaderGen uses implementations of the ShaderFeature class to create HLSL and GLSL shaders (ShaderFeatureHLSL and ShaderFeatureGLSL). When ShaderGen is initialized, it will call all registered ShaderGenInitDelegate and allow them to associate a ShaderFeature with a FeatureType (see Engine/source/shaderGen/hlsl/shaderGenHLSLInit.cpp). Some of these features have shader code assocated with them, such as MFT_LightMap and its implementation, LightmapFeatHLSL. Some features do not have code associated, and are used as flags for changing the behavior of other feature implementations, such as, MFT_IsDXTnm which is a flag indicating that the normal map data needs to be expanded before use.