New MeshStandardMaterial in r112 has banding artifacts on some GPUs
See original GitHub issueAs of r112 the default MeshStandardMaterial (in this case specifically as it’s used when loading glTF files, but probably in other scenarios as well) is exhibiting banding artifacts on some GPUs. Specifically, I have see this issue on a Pixelbook and every generation of Pixel phones. The issue does not occur on the Nvidia desktop GPUs I have tried, nor on an Oculus Go or Oculus Quest.
It should also be noted that I’ve observed the material’s new shader incurred a noticable performance hit relative to r111 for my particular application on various mobile devices, including ones that don’t exhibit the rendering artifacts.
The artifacts look like this (Rendered with Three.js r112 on a Pixelbook)
The expected output looks like this (Rendered with Three.js r111 on the same Pixelbook)
Live link, currently using r112: https://xrdinosaurs.com
All of the dinosaurs on that page exhibit the issue, but ones with large areas of flat or smooth colors (like the TRex’s belly) tend to stand out more.
The material in the screenshot (pasted in full below) uses the glTF extension “KHR_materials_pbrSpecularGlossiness”, and has a diffuse, normal, and specular/glossiness textures.
{
"doubleSided": true,
"emissiveFactor": [
0,
0,
0
],
"extensions": {
"KHR_materials_pbrSpecularGlossiness": {
"diffuseFactor": [
0.46512957319999998,
0.46512957319999998,
0.46512957319999998,
1
],
"diffuseTexture": {
"index": 4,
"texCoord": 0
},
"glossinessFactor": 0.27610518290000002,
"specularFactor": [
0.92244664629999995,
0.92244664629999995,
0.92244664629999995
],
"specularGlossinessTexture": {
"index": 6,
"texCoord": 0
}
}
},
"name": "TRex",
"normalTexture": {
"index": 5,
"scale": 1,
"texCoord": 0
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:18 (7 by maintainers)
Top GitHub Comments
@elalish after running some tests on multiple examples, I was able to pinpoint the actual cause of these artifacts. Contrary to what I said on my previous post, the root cause of the problem is not related with incorrect coordinates sampling, but with the way
PMREMGenerator
is handlingdevicePixelRatio
.On devices with nominal floating point
pixelRatio
we are getting “bad” mipmap coordinates on the generated texture. So there are small gaps and overlapping regions. I also discovered that my machine has differentdevicePixelRatios
depending if I’m viewing the example locally (0.899…) or online (1) and that’s why I was only experiencing these artifacts locally.I’ve setup a simple test by disabling
setPixelRatio
and it seems to solve the problem, if that’s the case for others, then it would be best to refactor the wayPMREMGenerator
is handling it.@toji @plut0nist mind checking the following examples on the devices that presented these artifacts?
DEV Example TEST Example
@sciecode: Verified on my devices. The DEV Example test exhibits a very obvious black line in the environment map while the TEST Example does not. Awesome debugging, thanks!
I’m was extremely curious why
PMREMGenerator
needed to account fordevicePixelRatio
at all, so I went digging. It turns out it’s becauserenderer.setViewport()
automatically factors the DPR into any values you send it, which feels like it’s clearly the wrong behavior for render targets other than the default framebuffer, which are allocated with exact pixel values that don’t account for the pixel ratio at all. I’d suggest the “right” behavior here is that internallyrendere.setViewport()
should be usinggetTargetPixelRatio()
, which returns1
when the active render target is anything other than the default. I can definitely see how that could introduce backwards compat issues, though.