Sign in to follow this  

Possible to manually implement texture filtering?

This topic is 3631 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

Hi guys, I am making use or texture atlases to texture what is effectively a terrain. As you may know, one of the problems with texture atlases is that the textures do not repeat very well because the linear interpolation causes artifacts at the edge of each texture. These artifacts disappear if you switch off texture filtering. So what I would like to do is firstly manually implement the linear texture filtering (by taking several samples without filtering) and secondly to modify my filtering code to work with texture atlases. Could this work? I'm no shader expert but I tried the following Cg code (so far it only filters in the 'x' direction.) Note that the size of the texture atlas is 2048x2048, which is why I think I need those scaling factors.
float4 performInterpolatedTextureLookup(sampler2D texture, float2 pos)
{
	float xPos = pos.x * 2048.0;
	float xFrac = frac(xPos);
	float xMin = xPos - xFrac;
	float xMax = xPos + 1.0;
	xMin /= 2048.0;
	xMax /= 2048.0;
	
	float yPos = pos.y;
	float4 resultMin = tex2D(texture, float2(xMin, yPos));
	float4 resultMax = tex2D(texture, float2(xMax, yPos));
	
	float4 result = (resultMin * (1-xFrac) + resultMax * xFrac);
	return result;
}
However, it doesn't look much (if any) different from having no filtering. Am I on the right track? Also, as I understand it this problem should go away when using DirectX 10 texture arrays instead of texture atlases? I would still be nice to get it working on older hardware though... Thanks for any help!

Share this post


Link to post
Share on other sites
You can definitely manually implement texture filtering.... but you're not going to be happy with the speed!

I'd suggest instead using some shader/sampler code to implement just the boundary conditions and modify the texture coordinates, but still let the hardware handle trilinear filtering (you probably want a max mipmap level clamp as well). Thus you're trying to ensure that the texture coordinates that you request from the hardware are always within the [0,1] range (hardware boundary conditions never kick in) and they are never between two different atlas textures (bilinear will never blend unrelated items). This isn't terribly hard to do - particularly if you lay out your atlases along power-of-2 boundaries (this helps with mipmapping as well).

Another note is that your interpolation code above does not appear to be correct. For simple bilinear filtering you need 4 lookups and 3 lerps/mads. For trilinear you need 8 lookups (4 on each of the two adjacent mipmap levels) and 7 lerps/mads. For anisotropic filtering you need many more lookups and you effectively can't implement it with any sort of reasonable efficiency in shader code.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
You can definitely manually implement texture filtering.... but you're not going to be happy with the speed!

I'd suggest instead using some shader/sampler code to implement just the boundary conditions and modify the texture coordinates, but still let the hardware handle trilinear filtering (you probably want a max mipmap level clamp as well). Thus you're trying to ensure that the texture coordinates that you request from the hardware are always within the [0,1] range (hardware boundary conditions never kick in) and they are never between two different atlas textures (bilinear will never blend unrelated items). This isn't terribly hard to do - particularly if you lay out your atlases along power-of-2 boundaries (this helps with mipmapping as well).


Ok, thanks. I will have a look at implementing it in this way. I already have power-of-two for exactly the mipmapping reason. I may well post back here if I have more problems!

Quote:
Original post by AndyTXAnother note is that your interpolation code above does not appear to be correct. For simple bilinear filtering you need 4 lookups and 3 lerps/mads. For trilinear you need 8 lookups (4 on each of the two adjacent mipmap levels) and 7 lerps/mads. For anisotropic filtering you need many more lookups and you effectively can't implement it with any sort of reasonable efficiency in shader code.


Sure, but actually I have only implemented linear filtering in one direction (x). I was intending to add the other direction (y) next (to mimic bilinear filtering) but could already see it might not go as planned...

Thanks for the input!

Share this post


Link to post
Share on other sites
Quote:
Original post by esuvs
Sure, but actually I have only implemented linear filtering in one direction (x). I was intending to add the other direction (y) next (to mimic bilinear filtering) but could already see it might not go as planned...

Ah I see now. Sorry I didn't take a detailed look at your code before I replied :S

Share this post


Link to post
Share on other sites

This topic is 3631 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.

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