Michael
Michael

Reputation: 595

DirectX 11 texture filter linear/point flicker

I wrote a small DirectX 11 application on Windows 10 x64 using C++. Now I want to render some low resolution textures (e.g. 16px * 16px) without loosing it's sharpness on magnifications (how in games like Terraria). So the only options I see are making the sprite textures high resolution or change the sampler state from D3D11_FILTER_MIN_MAG_MIP_LINEAR to D3D11_FILTER_MIN_MAG_MIP_POINT. The former is not an option for me because I want to save video memory and not wasting it for redundant information. But the second approach cause some new problem. If I move a textured rectangle using this sampler I get an annoying flicker.

Point:
enter image description here

Linear:
enter image description here

Point:
enter image description here

Linear:
enter image description here

After thinking about it I came to the result that using D3D11_FILTER_MIN_MAG_MIP_POINT will always cause this flicker. The following image illustrates how I understood point filtering and also shows the reason for flicker. On it one can see an horizontal sampling process, using point filtering, from an low resolution textured rectangle moving to the right.

enter image description here

I did not post any code because I think this issue is not related to any specific code and would not help at all. So if I am wrong with this assumption please tell.
Finally the question is how I can fix this or what alternatives are left?

Upvotes: 2

Views: 3320

Answers (3)

d7samurai
d7samurai

Reputation: 3216

To avoid aliasing while maintaining crisp pixels (like in the typical pixel art aesthetic) during magnification or sub-pixel translation, you can use antialiased point sampling, implemented manually in the shader. Here are some examples:

https://www.shadertoy.com/view/ltBGWc

short intro gist: https://gist.github.com/d7samurai/9f17966ba6130a75d1bfb0f1894ed377

in context, complete sprite renderer: https://gist.github.com/d7samurai/e51adec8a440126d028b87406556079b

enter image description here

enter image description here

Upvotes: 0

Pablo H
Pablo H

Reputation: 659

Some ideas:

There is a filtering technique called bilateral filter, where the idea is to blur more where local contrast is low, and blur less where local contrast is high, to preserve edges. It might be possible to (manually) upsample your low resolution texture using a similar idea...

If your texture is such that a low-resolution version looks good enough, then higher resolution plus texture compression might work for you.

There is also multisampling (MSAA). Perhaps point sampling works acceptable with multisampling enabled. Note that you will probably need to also do/enable multisample shading, because if not, all samples for a pixel would have the same color.

Upvotes: 0

Chuck Walbourn
Chuck Walbourn

Reputation: 40992

The filtering mode doesn't have anything to do with memory usage. You can use these filtering modes even on textures without mipmap chains, although the filtering is less effective when the target pixel size would use a lower mip.

Nearest-point filtering is likely to always cause artifacts unless you can ensure exactly a 1:1 texel-to-pixel mapping, so it's not particularly useful.

SpriteBatch in the DirectX Tool Kit defaults to using D3D11_FILTER_MIN_MAG_MIP_LINEAR and D3D11_FILTER_MIN_MAG_MIP_LINEAR which tends to work best for 2D sprites.

You could try using D3D11_FILTER_ANISOTROPIC to see if that improves your scenario, but keep in mind that you have to use a MaxAnisotropy of 2 if you are supporting Direct3D Hardware Feature Level 9.1. If you have any higher feature level, you can use D3D11_MAX_MAXANISOTROPY.

For modern PCs or the Universal Windows Platform (UWP), a minimum of D3D_FEATURE_LEVEL_9_3 is reasonable as 9.2 and 9.1 are quite old. Even Windows phone is at least 9.3.

Upvotes: 0

Related Questions