Edit - The issue is actually that mipmap generation is failing on certain texture source image sizes, certain sizes work and certain don’t. In webGL2 supposedly you do not need power of two images, but there seems to be other constraints to the size which I can’t figure out.
I’m running into persistent moiré patterns on very tight, intricate textures (think detailed linens), even after ruling out all other factors such as post‑processing, GL settings, material types, etc.
I’ve tried experimenting with different minFilters—for example, the default THREE.LinearMipMapLinearFilter
versus other options—and even passed a custom array of mipmaps generated by downscaling the original image with heavy blur to smooth out the detail. However, the moiré remains visible when the texture is minified.
The amount that we need to reduce map repeats, or blur the texture to get to a point of no Moiré renders the texture unusable.
This effect is happening on all the textures that we use for the material that include the same pattern, diffuse, normal, metalness etc. It shows up on pretty much all of our linens/cottons/fabric materials to some extent - sometimes an acceptable amount and sometimes not.
Has anyone encountered this issue? Are there any further strategies or insights on mitigating moiré in such cases? I understand that this is an inherent challenge with very detailed, repetitive textures in graphics rendering but anyone has any alternative approaches that I can attempt that would be fantastic, thank you 
1 Like
Have you verified that the renderers size correctly matches the size of the canvas?
Can you drag one of your GLBs on here:
And see if it shows the same artifacts?
1 Like
Yes the renderer is the correct size, I am using the React Three Fiber Canvas which does this automatically. It is the minFilter / mipmaps that results in this pattern, we have confirmed this with testing.
1 Like
…and just to clarify… you see the same artifacts when your glb is viewed in that gltf viewer i linked?
1 Like
No, the artefacts are caused by the texture specifically. Nothing to do with the glb model. The artefacts are present on a plain cube, plain sphere or any plain shape. It is the intricate patterns in the texture map that is causing the moire.
Post the glb?
( I’m asking because I want to see it first hand. Under regular texturing circumstances, mipmapping /tri/bilinear filtering is used to mitigate exactly this issue, so I want to see why it isn’t working. )
Here is is on a plain cube, it has nothing to do with the object unfortunately.
This image shows it zoomed in, before banding/moire begins.
Here are the colour and normal maps if you want to reproduce the effect. It works with either one, but having both makes it more pronounced.
I should not this is happening with many different textures, this is just an example of one.
Does it improve slightly when setting the anisotropy
of the material? The maximal anisotropy is available in renderer.capabilities.getMaxAnisotropy()
.
2 Likes
Unfortunately not, I have investigated anisotropy.
When Three.js creates the mipmaps, this is an emergent pattern from any detailed texture due to the repeats etc. If you actually resize the image in a canvas it will produce the same pattern.
No renderer setting, anisotropy etc will be able to fix this. I highly doubt that a fix is built into Three.js, this will likely require a custom solution. I can’t seem to find much research on methods past dithering, which I have already tried both by enabling it on the material and by changing the shader chunk.
Thanks. I put them on a cube… in blender… like a barbarian.
Here it is if someone wants to take a look.
noiseybox.glb (1.1 MB)
What you mean by “due to the repeats etc.”?
Because of the intricacies in the texture, when the mipmap is created an emergent pattern comes out. You can actually see this if you look at the thumbnail for the normal map I posted.
This combined with the texture being repeated across the material (texture.wrapS & texture.wrapT) is what is causing the Moire/Banding.
The problem with the glb you posted is that the texture is enlarged so you have to zoom out to where the cube is tiny to be able to barely see the moire. This is a linen fabric so each line should be about the width of a linen thread.
I made a minimal repro here.
I think it shows the issue you’re talking about.
1 Like
Thanks, yep thats the problem 
I’m not actually convinced that this is a “moire” pattern… but its more of a higher order pattern in the texture that emerges at higher minification, since it seems to be stable even when the surface rotates.
A true moire would sizzle and change under rotation…
2 Likes
Yes thats exactly the issue, I don’t know what its called and don’t know the solution.
setting roughness 1 and metalness 0 actually introduces a second pattern that is a moire…
in addition to the higher order pattern.
Hard to say what could really “fix” that except… either using a larger texture, or generating custom mipmaps that fade to a solid color.
I don’t know if this tutorial is current, but seems related: Custom Mipmaps - Three.js Tutorials
1 Like