Sign in to follow this  
PhillipHamlyn

Optimal Mult-Sampling in Pixel Shader ?

Recommended Posts

Hi,

 

I have a pixel shader for a terrain tile which samples a texture atlas for various ground cover.

 

I have around 8 different ground cover types which I pass to the PS via a Texture Blend Map using Texture2D NormalizedByte4 with one channel per texture weight.

 

Most pixels will blend perhaps 3 of the 8 possible textures, exceptionally 4.

 

What is the optimal way to sample the textures ?

 

I  followed the standard "linear" "add them all up" approach, shown below;

textureColor += tex2D(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(0,0))) * textureWeights1.a;
textureColor += tex2D(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(1,0))) * textureWeights1.r ;
textureColor += tex2D(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(0,1))) * textureWeights1.g ;
textureColor += tex2D(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(1,1))) * textureWeights1.b ;
textureColor += tex2D(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(0,0))) * textureWeights2.a;
textureColor += tex2D(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(1,0))) * textureWeights2.r;
textureColor += tex2D(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(0,1))) * textureWeights2.g;
textureColor += tex2D(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(1,1))) * textureWeights2.b;

However I could have bypassed the many lookups by checking the texture weight prior to sampling. Like this

if(textureWeights1.r > 0) textureColor += tex2D(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(1,0))) * textureWeights1.r ;

 

Which is the recommended approach for performance in a pixel shader ? I understand that the PS can bypass texture lookups sometimes, but I dont know whether doing this manually by checking the texture weight myself is a better solution, especially because I expect only 50% maximum of the texture lookups to actually achieve anything.

 

Phillip


Share this post


Link to post
Share on other sites

Yes, that's the way you'd do it. Use the [branch] attribute in front of your if statements to indicate you want dynamic branching.

 

Unfortunately, in order to successfully bypass the texture lookups, you'll need to use tex2Dlod, as gradient-based instructions don't work inside a dynamic branch (so you'll never see any benefit from your if statements if you keep using tex2D). This means you'll need to calculate the mipmap level manually outside the branch (assuming you're using mipmaps).

Share this post


Link to post
Share on other sites

Thanks phil_t.

 

Unfortunately I'm using SM2 so cannot use tex2DLod. Fortunately it seems I can use text2DGrad to get the same outcome, in combination with ddx() and ddy() helpfully discussed here http://www.gamedev.net/topic/470659-anyone-tell-me-the-difference-of-tex2dgrad--and-tex2d/

 

Even more unfortunately although text2DGrad is supported in SM2 (and therefore Reach Profile) ddx() and ddy() are not supported until SM2.1.

 

It seems I need to abandon Reach profile in order to get optimal performance in branched texture lookups. Ah well, its only a hobby game, so moving to HiDef wont be an issue.

 

Phillip

Share this post


Link to post
Share on other sites

Hmm,

I followed my nose and have the following now; which works nicely enough.

if(textureWeights1.a > 0) textureColor += tex2Dgrad(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(0,0)), texDdx, texDdy) * textureWeights1.a;
if(textureWeights1.r > 0) textureColor += tex2Dgrad(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(1,0)), texDdx, texDdy) * textureWeights1.r;
if(textureWeights1.g > 0) textureColor += tex2Dgrad(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(0,1)), texDdx, texDdy) * textureWeights1.g;
if(textureWeights1.b > 0) textureColor += tex2Dgrad(TextureSamplerAtlas1,getAtlasTextureCoords(textureCoords, float2(1,1)), texDdx, texDdy) * textureWeights1.b;

if(textureWeights2.a > 0) textureColor += tex2Dgrad(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(0,0)), texDdx, texDdy) * textureWeights2.a;
if(textureWeights2.r > 0) textureColor += tex2Dgrad(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(1,0)), texDdx, texDdy) * textureWeights2.r;
if(textureWeights2.g > 0) textureColor += tex2Dgrad(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(0,1)), texDdx, texDdy) * textureWeights2.g;
if(textureWeights2.b > 0) textureColor += tex2Dgrad(TextureSamplerAtlas2,getAtlasTextureCoords(textureCoords, float2(1,1)), texDdx, texDdy) * textureWeights2.b;

 

Phillip

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this