Skip to content

Custom anisotropic filtering for in-shader texture filtering - #2977

Merged
gonetz merged 1 commit into
masterfrom
custom_af
Jul 26, 2026
Merged

Custom anisotropic filtering for in-shader texture filtering#2977
gonetz merged 1 commit into
masterfrom
custom_af

Conversation

@gonetz

@gonetz gonetz commented Jul 16, 2026

Copy link
Copy Markdown
Owner
  • The accurate combiner (texelFetch) and the fast combiner (per-texel texture()/textureGrad) do their own bilinear/3-point filtering, so the sampler's GL_TEXTURE_MAX_ANISOTROPY does not apply. Emulate AF in the shaders.
  • Accurate path: supersample the custom filter along the major axis of the pixel's texture-space footprint (from screen-space derivatives); for mip-mapped textures also bias the LOD toward the minor axis. Non-LOD and mipmap paths, LOD emulation on/off, desktop and GLES2. Driven by a uMaxAnisotropy uniform wired through UTextureFetchMode and UMipmap.
  • Fast path: for textures with a mip chain, keep hardware AF but sample with textureGrad using the continuous pre-wrap gradient (dFdx(vTexCoord)*uTexScale) to avoid seams at texture-repeat boundaries. For textures without a mip chain (HD textures, detected via uTextureHD; and the fake-mipmap path), hardware AF cannot work, so supersample manually at the minor-axis LOD. Original (non-HD) textures are unaffected.
  • Bump shader storage format version to force shader regeneration.

* The accurate combiner (texelFetch) and the fast combiner (per-texel texture()/textureGrad) do their own bilinear/3-point filtering, so the sampler's GL_TEXTURE_MAX_ANISOTROPY does not apply. Emulate AF in the shaders.
* Accurate path: supersample the custom filter along the major axis of the pixel's texture-space footprint (from screen-space derivatives); for mip-mapped textures also bias the LOD toward the minor axis. Non-LOD and mipmap paths, LOD emulation on/off, desktop and GLES2. Driven by a uMaxAnisotropy uniform wired through UTextureFetchMode and UMipmap.
* Fast path: for textures with a mip chain, keep hardware AF but sample with textureGrad using the continuous pre-wrap gradient (dFdx(vTexCoord)*uTexScale) to avoid seams at texture-repeat boundaries. For textures without a mip chain (HD textures, detected via uTextureHD; and the fake-mipmap path), hardware AF cannot work, so supersample manually at the minor-axis LOD. Original (non-HD) textures are unaffected.
* Bump shader storage format version to force shader regeneration.
@gonetz

gonetz commented Jul 16, 2026

Copy link
Copy Markdown
Owner Author

I tested that commit on my desktop only.
I tested only Zelda MM, Termina fields.
I tested both fast and accurate texture path, with mip-mapping emulation on/off.
I tested it with original textures and with Nerrel's HD pack.
It doesn't work perfectly in all cases, sometimes mip-mapped textures still shake on a distance.
Anyway, it now looks way better with AF enabled.
The code is not perfect. If somebody can improve it, welcome.
The code is probably is not fast enough to work on mobile platforms.
It probably won't work on mobile platforms at all. It should be tested.

@fzurita can you test it on gles3 and gles2 devices?
gles2 code has been added too, but no guarantee that it will work somehow.

@gonetz gonetz linked an issue Jul 16, 2026 that may be closed by this pull request
@gonetz
gonetz merged commit ce71e71 into master Jul 26, 2026
28 checks passed
@gonetz
gonetz deleted the custom_af branch July 26, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Anisotropic filtering doesn't work

1 participant