-
Notifications
You must be signed in to change notification settings - Fork 14
Shader Builders (.shader_builder)
Many shaders in Spore are not coded in a single .hlsl file directly. Instead, they are generated by combining different pieces of code, known as Shader Fragments. These fragments are then combined under certain conditions in the Shader Builder files.
A shader builder contains two lists of references to fragments, with certain conditions that the game must meet for that fragment to be selected. When the game needs a shader, all these conditions are checked, the correct fragments are selected and merged, and a shader is generated.
There are two types of list, both must be included in the same file:
-
vertexShader: Can only use those fragments that end with the.vertex_fragmentextension. -
pixelShader: Can only use those fragments that end with the.pixel_fragmentextension.
For example, a builder list for a vertex shader might look something like this:
vertexShader
add copyVertexColor -elements color
add getAngle
add toClipSpace
end
In this example, there are fragments that are always selected (getAngle and toClipSpace) and other that depend, in this case, on whether the model has vertex colors.
Apart from using add to add fragments, it's also possible to choose one from a group of possible selections. For example:
group 0x1
select applyShadowMapTerrainNest -compareData shadowMapInfo 3
select applyShadowMapTerrain -compareData shadowMapInfo 2
select applyShadowMapNull
end
This will select, at most, only one of those fragments; if applyShadowMapTerrainNest cannot be used, it will try with applyShadowMapTerrain, and so on. It is possible that no fragment in the group is selected at all. Notice that inside a group, you use select instead of add.
When defining a group you must also give it a name.
Both add and select have the same attributes and options:
add fragmentName
select fragmentName
fragmentName is the name of the fragment to be used; if this is inside a vertex shader only vertex fragments can be used, and the same goes for pixel shaders.
Add and select instructions can have certain conditions that define when these will be used. If no conditions are specified, then the fragments are always used.
These conditions are mutually exclusive, meaning that only one of them can be used:
-
hasData dataNames...
Uses the fragment if the game has defined data for the specified Shader Data names; you can use from 1 to 3 names. For example, add myFragment -hasData skinWeights cellStage
-
compareData dataName value
Uses the fragment if the game has defined data for the specified Shader Data, and that has the same value as specified. For example, select myFragment -compareData shadowMapInfo 2
-
array dataName
Uses the fragment if the game has defined data for the specified Shader Data. Furthermore, it will use that data value as an array index, so if the fragment is at index 123 and the shader data has value 5, it will use the fragment 123+5 = 128. For example, select uvTweak_projectXY -array uvTweak: all fragments after uvTweak_projectXY are also related, the one that is sued is determined by the value of uvTweak.
-
objectTypeColor value
Uses the fragment if the game has defined objectTypeColor data and it has the same value as specified. For example, select myFragment -objectTypeColor 2
-
hasSampler index
Uses the fragment if the game has defined a texture sampler for the given inde. For example, select myFragment -hasSampler 0
-
unk12 value1 value2
Unknown usage.