Jump to content

  • Log In with Google      Sign In   
  • Create Account

Optimal Mult-Sampling in Pixel Shader ?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 PhillipHamlyn   Members   -  Reputation: 523


Posted 20 January 2013 - 05:21 AM



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.




#2 phil_t   Crossbones+   -  Reputation: 7002


Posted 20 January 2013 - 07:47 AM

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).

#3 PhillipHamlyn   Members   -  Reputation: 523


Posted 20 January 2013 - 09:14 AM

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.



#4 PhillipHamlyn   Members   -  Reputation: 523


Posted 20 January 2013 - 09:37 AM


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;



Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.