You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add mipmapped minification (trilinear) and optional anisotropic filtering for WebGL textures, so high-frequency textures stop shimmering/aliasing when minified (viewed small, at a distance, or at grazing angles). Extends the textureFilter work from #1506.
Motivation / scope
The mesh + sprite texture path currently sets TEXTURE_MIN_FILTER to the same value as TEXTURE_MAG_FILTER (gl.LINEAR or gl.NEAREST) — no mipmaps. That means a minified high-frequency texture (brick, foliage, text on a sign, photographic detail) seen at distance or oblique angles aliases/shimmers under motion, because each fragment samples one texel of a much larger image.
This is NOT needed for melonJS's stylized low-poly target — low-poly kits texture with flat/palette colors (e.g. Kenney colormap = large flat color blocks, very low-frequency), which barely alias under minification; plain LINEAR already looks clean. So this is a quality-completion for detailed-texture 3D, deliberately deferred out of #1506, not core.
Where it pays off: textured 3D with detailed/high-frequency maps viewed at varying depth (a textured ground plane receding to the horizon, distant detailed props, oblique walls).
Current state
MaterialBatcher.createTexture2D already has a mipmap param and a POT check (isPowerOfTwo(w) && isPowerOfTwo(h)), and WebGL 2 can mipmap NPOT — so some of the plumbing exists, but the min filter is never set to a *_MIPMAP_* mode.
setAntiAlias / setTextureFilter re-apply that single filter to both TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER.
Proposal
Mipmapped min filter — when the resolved filter is linear and mipmaps are generated, set TEXTURE_MIN_FILTER to LINEAR_MIPMAP_LINEAR (trilinear) while MAG_FILTER stays LINEAR. For nearest, keep crisp (NEAREST / NEAREST_MIPMAP_NEAREST as appropriate). Generate mipmaps via gl.generateMipmap after upload (already partially wired); WebGL 1 requires POT — guard and fall back to plain LINEAR for NPOT on WebGL 1.
Anisotropic filtering — query EXT_texture_filter_anisotropic (getExtension + MAX_TEXTURE_MAX_ANISOTROPY_EXT), expose an Application setting (e.g. anisotropy: number or "auto"/level, default off/1) and apply texParameterf(TEXTURE_MAX_ANISOTROPY_EXT, level) clamped to the GPU max. Graceful no-op when the extension is absent.
Decide the knob: likely fold into the existing textureFilter story — e.g. a mipmap/anisotropy Application setting, and/or a per-Mesh opt-in, mirroring Mesh.textureFilter.
Update setAntiAlias/setTextureFilter/_reapplyTextureFilter so the MIN side picks the mipmapped variant (the MIN/MAG split the current code collapses).
Considerations
MIN vs MAG split: today _reapplyTextureFilter(filter) sets both to one enum — needs to become min/mag-aware.
Summary
Add mipmapped minification (trilinear) and optional anisotropic filtering for WebGL textures, so high-frequency textures stop shimmering/aliasing when minified (viewed small, at a distance, or at grazing angles). Extends the
textureFilterwork from #1506.Motivation / scope
The mesh + sprite texture path currently sets
TEXTURE_MIN_FILTERto the same value asTEXTURE_MAG_FILTER(gl.LINEARorgl.NEAREST) — no mipmaps. That means a minified high-frequency texture (brick, foliage, text on a sign, photographic detail) seen at distance or oblique angles aliases/shimmers under motion, because each fragment samples one texel of a much larger image.This is NOT needed for melonJS's stylized low-poly target — low-poly kits texture with flat/palette colors (e.g. Kenney
colormap= large flat color blocks, very low-frequency), which barely alias under minification; plainLINEARalready looks clean. So this is a quality-completion for detailed-texture 3D, deliberately deferred out of #1506, not core.Where it pays off: textured 3D with detailed/high-frequency maps viewed at varying depth (a textured ground plane receding to the horizon, distant detailed props, oblique walls).
Current state
MaterialBatcher.createTexture2Dalready has amipmapparam and a POT check (isPowerOfTwo(w) && isPowerOfTwo(h)), and WebGL 2 can mipmap NPOT — so some of the plumbing exists, but the min filter is never set to a*_MIPMAP_*mode.WebGLRenderer._glTextureFilter()/getDefaultTextureFilter()(added in feat(gltf): material features Tier 2 + mesh-batcher perf + texture-filter decoupling #1506) resolve a single"linear"/"nearest"mode used for both min and mag.setAntiAlias/setTextureFilterre-apply that single filter to bothTEXTURE_MIN_FILTERandTEXTURE_MAG_FILTER.Proposal
linearand mipmaps are generated, setTEXTURE_MIN_FILTERtoLINEAR_MIPMAP_LINEAR(trilinear) whileMAG_FILTERstaysLINEAR. Fornearest, keep crisp (NEAREST/NEAREST_MIPMAP_NEARESTas appropriate). Generate mipmaps viagl.generateMipmapafter upload (already partially wired); WebGL 1 requires POT — guard and fall back to plainLINEARfor NPOT on WebGL 1.EXT_texture_filter_anisotropic(getExtension+MAX_TEXTURE_MAX_ANISOTROPY_EXT), expose an Application setting (e.g.anisotropy: numberor"auto"/level, default off/1) and applytexParameterf(TEXTURE_MAX_ANISOTROPY_EXT, level)clamped to the GPU max. Graceful no-op when the extension is absent.textureFilterstory — e.g. amipmap/anisotropyApplication setting, and/or a per-Meshopt-in, mirroringMesh.textureFilter.setAntiAlias/setTextureFilter/_reapplyTextureFilterso the MIN side picks the mipmapped variant (the MIN/MAG split the current code collapses).Considerations
_reapplyTextureFilter(filter)sets both to one enum — needs to become min/mag-aware.textureFilter: "linear"and explicitly opted in).textureFilter.Acceptance criteria
MIN_FILTERuses a*_MIPMAP_*mode when mipmaps are on; MAG unchanged.References
src/video/webgl/batchers/material_batcher.js(createTexture2Dmipmap/POT,uploadTexturefilter resolution)src/video/webgl/webgl_renderer.js(_glTextureFilter,_reapplyTextureFilter,setAntiAlias,setTextureFilter)src/video/renderer.js(getDefaultTextureFilter)src/application/settings.ts(textureFilter; addanisotropy/mipmaphere)