Often times, the simplest and most elegant algorithms are obvious, but take the longest to figure out. In one level for an Infernal Engine game, we wanted to fully displacement map every pixel in our scenery, but we couldn’t afford the complexity of the shader on each and every pixel. One solution would be to have two sets of shaders – for the near polygons, use a displacement map shader, and for the far polygons, use the non-displacement map shader. An easier way was to add an HLSL static branch hint, based upon the screen depth of the input pixel as follows:
struct PS_INPUT {
float2 uv : TEXCOORD0;
float4 clipPos : TEXCOORD1;
.
.
.
};
struct PS_OUTPUT {
float4 color;
};
sampler2D map;
sampler2D displacementMap;
.
.
.
PS_OUTPUT displacementMapShader(PS_INPUT input) {
PS_OUTPUT output;
.
.
.
float2 uvDisp = input.uv;
[branch]
if (clipPos.z < 20.0F) {
// Expensive code follows to perform the actual displacement mapping
.
.
.
}
// Perform displaced or non-displaced texture lookup(s)
float4 color = tex2D(map,uvDisp);
.
.
.
return(output);
}
There are some different rules for the PC and the consoles when you are allowed to use a static branch, but you should be able to make this little trick work for your specific case!
. Read the rest at Intel.com.