ISSUE TRACKER LINK
Make sure to vote for this feature.
[HR][/HR]
In my efforts to bring down landscape render times, dynamic shader branching has proven to be insanely useful.
However, I can’t get it to work as expected using material node networks only.
As an example, this network:
http://image.prntscr.com/image/5f680c891f2b43969be0a809722a7f8a.png
looks like that in HLSL:
// Now the rest of the inputs
MaterialFloat Local0 = min(max(Parameters.TangentToWorld[2].b,0.00000000),1.00000000);
MaterialFloat3 Local1 = (GetWorldPosition(Parameters) / 512.00000000);
MaterialFloat2 Local2 = DDY(Local1.rg);
MaterialFloat2 Local3 = DDX(Local1.rg);
MaterialFloat4 Local4 = ProcessMaterialColorTextureLookup(Texture2DSampleGrad(Material.Texture2D_0,Material.Texture2D_0Sampler,Local1.rg,Local3,Local2));
MaterialFloat3 Local5 = (GetWorldPosition(Parameters) / 2048.00000000);
MaterialFloat2 Local6 = DDY(Local5.rg);
MaterialFloat2 Local7 = DDX(Local5.rg);
MaterialFloat4 Local8 = ProcessMaterialColorTextureLookup(Texture2DSampleGrad(Material.Texture2D_0,Material.Texture2D_0Sampler,Local5.rg,Local7,Local6));
MaterialFloat3 Local9 = ((Local0 >= 0.50000000) ? Local4.rgb : Local8.rgb);
Which is branch flattening pretty much. Both textures will be sampled, and one of values will not be used.
Now the same node network, but using a custom node:
http://image.prntscr.com/image/9c06de2c688e4b7ea4cee0279f5fac5c.png
Custom node code:
float4 result=0;
if(VertexNormalB>=0.5)
{
result=FirstTex.SampleGrad(FirstTexSampler,FirstUVs,FirstDDX,FirstDDY);
}
else
{
result=SecondTex.SampleGrad(SecondTexSampler,SecondUVs,SecondDDX,SecondDDY);
}
return result;
Compiled code looks as follows, in this case:
// Now the rest of the inputs
MaterialFloat3 Local0 = (GetWorldPosition(Parameters) / 512.00000000);
MaterialFloat3 Local1 = (GetWorldPosition(Parameters) / 2048.00000000);
MaterialFloat2 Local2 = DDX(Local0.rg);
MaterialFloat2 Local3 = DDY(Local0.rg);
MaterialFloat2 Local4 = DDX(Local1.rg);
MaterialFloat2 Local5 = DDY(Local1.rg);
MaterialFloat Local6 = min(max(Parameters.TangentToWorld[2].b,0.00000000),1.00000000);
MaterialFloat4 Local7 = **CustomExpression0**(Parameters,Local0.rg,Local1.rg,Local2,Local3,Local4,Local5,Material.Texture2D_0,Material.Texture2D_0Sampler,Material.Texture2D_0,Material.Texture2D_0Sampler,Local6);
CustomExpression0 is pretty much our custom node code, and looks like that:
// Uniform material expressions.
MaterialFloat4 CustomExpression0(FMaterialPixelParameters Parameters,MaterialFloat2 FirstUVs,MaterialFloat2 SecondUVs,MaterialFloat2 FirstDDX,MaterialFloat2 FirstDDY,MaterialFloat2 SecondDDX,MaterialFloat2 SecondDDY,Texture2D FirstTex, SamplerState FirstTexSampler ,Texture2D SecondTex, SamplerState SecondTexSampler ,MaterialFloat VertexNormalB)
{
float4 result=0;
if(VertexNormalB>=0.5)
{
result=FirstTex.SampleGrad(FirstTexSampler,FirstUVs,FirstDDX,FirstDDY);
}
else
{
result=SecondTex.SampleGrad(SecondTexSampler,SecondUVs,SecondDDX,SecondDDY);
}
return result;
}
In latter case, there is a proper dynamic branching, resulting in one texture sampling being skipped for corresponding pixels. It may be insignificant for one texture lookup, but if this is used to skip a block of code, for example distance blended tri-plannar cliff layer in case for landscape, it proves to be major performance win.
My question: Is it possible to get dynamic branching using material nodes only? If yes, then how.
My thanks for any assistance rendered.