-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Force linear encoding for WebXR render targets #24698
Conversation
Thanks @cabanier! I'm worried that something feels off about putting an I assume we cannot really be transmitting frames to the WebXR device in Linear-sRGB at 8-bit precision; the quality loss would be large. Also consider that a WebGL application with multiple post-processing steps might use sRGB for intermediate render targets, even if the last step required Linear-sRGB output, to make better use of the limited 8-bit precision before a final tone-mapping step. |
For WebXR, the quest browser allocates an RGBA texture and then uses the msaa_render_to_texture extension to directly render to multisampled pixels. We can't set the WebXR texture to sRGB because that will cause double conversion which makes the output too light. |
If you're hoping to have this change included in r145 this month, it isn't my intention to block the PR. I'll defer to @Mugen87 on a short-term fix. However, it sounds like our compromise for lack of real color management in the HTML Canvas API in traditional WebGL applications has leaked into our WebXR implementation, if we are relying on inline GLSL in material shaders to apply the Linear-sRGB → sRGB transform here. This is not an ideal solution even for traditional WebGL apps, and is something we'd remove in a heartbeat if the Canvas API allowed us (see #23019).
If we disabled the initial conversion (currently applied by inline GLSL material shaders), it would be fine to make the WebXR texture and the renderbuffer sRGB, then? |
No, I'm not in a hurry. Fixing WebXR for non-quest devices also requires patches in the WebXR Layers polyfill.
The Quest browser currently ignores requests for sRGB because there were too many three.js experiences that suffered from the double conversion problem. |
By default, three.js disables the initial conversion when rendering to any render target. Currently dev...donmccurdy:three.js:hotfix/webxr-rtt-srgb Context for others reading, this goes back to:
It appears to me that the double conversion would be caused by #23288, and by reverting that change (and adding support for sRGB output in Oculus Browser) we avoid that risk. Does that sound correct? So the painful part of this change would be that users of older three.js versions will see incorrect colors (double conversion) after Oculus adds sRGB support, until they upgrade to the latest three.js release. That's unfortunate, but disabling sRGB at the browser level also doesn't seem sustainable1. 😕 I don't suppose we can detect support for sRGB output in Oculus Browser somehow, roll this out conditioned on browser support, and give developers time to make the update? In general I would advise developers using three.js + WebXR to initialize their application with the following settings, from our color management documentation: renderer.outputEncoding = THREE.sRGBEncoding;
renderer.physicallyCorrectLights = true;
THREE.ColorManagement.legacyMode = false; Each of these settings will make things easier down the road. When post-processing is involved, things are a bit more complex. 1 Related workaround in Wolvic |
Just to be explicit — colors written by THREE.WebGLRenderer to the texture have Rec. 709 (sRGB) primaries, sRGB transfer function, and D65 white point (assuming |
I think the sRGB problem predates that change.
We currently print a warning to the console when creating an sRGB layer and create it as RGB instead. Is there a way to query a texture for its format? FWIW the whole RGB workflow is messed up, at least on Quest in order to match the colors that are produced when drawing to an HTML canvas. I'd be very happy to sit down one day with other vendors and work out what it should look like. |
Thanks! |
When the WEBGL_multisampled_render_to_texture extension is not available, three.js falls back to using renderbuffers to get support for multisampled rendering.
However, there was a change that forces the renderbuffer to sRGB. This result in a GL error when it tries to copy the MSAA renderbuffer into the WebXR texture. WebXR is special in that its texture format is RGB but the three.js renderer is set to sRGB.
The fix now correctly flags the getInternalFormat call for WebXR to not choose sRGBA.
This contribution is funded by Meta