Jump to content
  • Advertisement
Sign in to follow this  

Optimal Mult-Sampling in Pixel Shader ?

This topic is 2156 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts



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.




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.



Share this post

Link to post
Share on other sites


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;



Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!