-
-
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
Apply fog before tonemapping and encoding #26208
base: dev
Are you sure you want to change the base?
Conversation
Alternatively we could do this to more closely preserve the previous behavior when
What do you think? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The concerns I mentioned in #24362 (comment) have been addressed by updates to color management in r152, so I agree this is a change we should could make.
Still thinking about what the behavior should be if color management is disabled...
@@ -17,7 +16,7 @@ function WebGLMaterials( renderer, properties ) { | |||
|
|||
function refreshFogUniforms( uniforms, fog ) { | |||
|
|||
fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The default value (THREE.ColorManagement.workingColorSpace
) would be the best choice. There's a mistake in the Color#getRGB documentation, to be fixed by #26210.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Oletus has this been resolved?
Related history: #11076 (comment). |
Hmm... I can certainly see an argument that fog should be applied after tone mapping, as suggested by @bhouston in #11076 (comment). Would that still fix #24362? Otherwise fog will need large adjustments for tone mapping exposure. |
Maybe... we can assume that the color passed to |
@LeviPesin the quote above predates #23937, and that is effectively solved now. I think the remaining concerns are:
|
I think there is no question as to the "proper" workflow. See. #24362 (comment). I think we should try to find a way to get there. |
If we were discussing lit volumetric fog, I'd have no hesitation in agreeing. As it is, the way looks problematic. Users often match their fog to the color of the page background or other HTML/CSS elements. Maintaining this behavior would suggest that users should (a) input a fog color that tone-maps to the desired output color, or (b) we should compute that for them. Neither is consistently possible, because tone mapping (and especially ACES) is not capable of generating many possible output colors in the sRGB gamut. This assumption is based on results from @elalish, which I'd love to have misunderstood! We could ask users to do the reverse, and choose their HTML colors based on the tone-mapped fog color, but it's a limiting requirement and I'm not sure what benefit we're getting from it. I would be happy to consider moving fog before encoding, as a stepping-stone toward getting it in front of tone-mapping, as well.. 😅 |
Is there a way that fog could just mostly modifying alpha? So instead of trying to match the colors of the page in a 3D render, we just fade away the canvas and let the underlying page colors show through? This is more flexible in that you can have more complex things happening in the background that just a color, it could be a wallpaper or gradients, etc. |
I don't know much about fog, but I like @bhouston's idea on alpha. That feels very related to the changes I made to transmissive materials on a transparent canvas - not saying it's perfect, but it makes it much easier to be cohesive with page CSS. I'm not familiar with how fog is used though, so I'm not the best person to ask. |
I think real fog should be before tone mapping (yes it contradicts what I
wrote years ago) but that is because fog for the purpose of blending into
the background should be focused on alpha rather than color. So there are
two separate use cases and workflows. Not sure how best to implement it.
-ben
On Wed, Jun 7, 2023 at 3:34 PM Emmett Lalish ***@***.***> wrote:
I don't know much about fog, but I like @bhouston
<https://github.com/bhouston>'s idea on alpha. That feels very related to
the changes I made to transmissive materials on a transparent canvas - not
saying it's perfect, but it makes it much easier to be cohesive with page
CSS. I'm not familiar with how fog is used though, so I'm not the best
person to ask.
—
Reply to this email directly, view it on GitHub
<#26208 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEPV7IBG7ZV7YLP27JMD7LXKDJV5ANCNFSM6AAAAAAY5VVMSE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Ben Houston, CTO https://threekit.com
613-762-4113 / http://calendly.com/benhouston3d
|
I'd lean on applying fog after tone mapping after reading the discussion here. It's a smaller step and we don't have a way to map the fog color to the pre-tonemapped space. The important thing is to apply fog before encoding. It would also be possible to blend the render results to a background buffer by the fog factor, but I'd say that's out of scope for this fix. That seems more like a different, complementary option to the current fog rather than a replacement. It would generate very different results in some cases and whether those results are desirable is a question of preference. It would also have very different performance characteristics, like doubling the required fillrate. |
It sounds weird to me to do fog after tonemapping. |
I think the solid color background is implemented as a clear, so it's not subject to tonemapping. |
@Oletus wrote:
This is only because of the single pass with tone mapping that has been the default Three.js way for years. This isn't fully correct, it was just a way to do HDR tone mapping in a single shader pass so you didn't need, which at the time was poorly supported, FP16 or FP32 intermediate buffers. The correct way to clear would be to clear your FP12/FP32 linear color buffer with the background color, then render everything into it as linear and then as a separate pass, do tone mapping + output color space conversion to the screen. The clear color in this case would be tone mapped and if you did fog during the rendering of the 3D scene to the linear FP16/FP32 buffer, then it would also be tone mapped. I think the solution, is to support alpha background colors and also a special fog that fades to transparent. And also do standard scene fog prior to tone mapping. This lets you incorporate a scene into a webpage seamlessly and better than if you try to match the clear color + fog color to the background. |
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
I rebased the PR on top of dev to fix conflicts. I also changed it so that it applies fog after tone mapping, so that the change doesn't have as significant downsides. I agree that applying fog before tone mapping would be more correct, but not having precise control over the final fog output color is a concern. It could also make sense to offer blending with the page background as an alternative, but I wouldn't want to increase the scope of this PR too much. I opened #26239 for a more focused discussion of the background blending. I hope we can move forward with this change just to fix the mismatch between rendering to SRGB FBOs and the default framebuffer. Can I also get feedback on this part?
|
@bhouston @donmccurdy @WestLangley What do you think?
Framebuffer-dependent ordering of fog and SRGB conversion is a clear bug and required an awkward search-and-replace workaround on our end, so I'd really appreciate getting some kind of fix merged. |
40dca1e
to
59b42b0
Compare
Sorry about the long delay, but I rebased the patch and added the workaround for non-color-managed scenes to keep the behavior similar to before - I think this is a good approach. Do you think that this bug fix could be merged? |
59b42b0
to
e973326
Compare
I tried re-running make-screenshot a few times, also with increased time in puppeteer.js, but some of the failing screenshots don't seem to be updating. Maybe there are some platform differences (I'm on Windows 10)? So I might need help with those. |
e973326
to
83422ba
Compare
I updated the PR, but |
Just one more thing... // Fog code snippet for reference gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor ); // Current #include <tonemapping_fragment>
#include <colorspace_fragment>
#include <fog_fragment> Currently, tone mapping and color space conversion precede the application of fog, and the input // Proposed #include <fog_fragment>
#include <tonemapping_fragment>
#include <colorspace_fragment> By applying fog prior to tone mapping and color space conversion, the input Mixing two values having different units is a red-flag for me. Perhaps |
Other than #24362 (fog color in THREE.Reflector), what use cases are we hoping will benefit from this change? Transmission might be another? The change in color space of three.js/src/renderers/shaders/UniformsUtils.js Lines 87 to 98 in f9e5848
From a user perspective, I think the effects proposed here would be:
|
I think it should yes. |
Definitely a breaking change but doesn't seem too big on an issue for me compared to all the texture and lighting changes we did last year. |
Related issue: #24362
Description
This makes behavior more consistent between rendering to an SRGB texture and rendering to the WebGL default framebuffer. Encoding the color values should always happen after fog has been applied.
This preserves the same fog color as before in case
ColorManagement.enabled
is true. Some example screenshots still need to be updated, since changing the order of operations does affect the rendering results.If color management is disabled, then the fog color that used to be interpreted as SRGB is now interpreted as linear, which does cause significant changes in render output.
This contribution is funded by Higharc