-
-
Notifications
You must be signed in to change notification settings - Fork 36.2k
Renderers: Set premultipliedAlpha to true when using MultiplyBlending or SubtractiveBlending. #32542
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
base: dev
Are you sure you want to change the base?
Conversation
…/SubtractiveBlending.
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
|
I bumped into this while working on #32496 and it really broke my flow... |
|
This isn't correct. These warnings are there for a reason. The values used during blending are fundamentally different so you cannot just use the same formula for premultiplied and non premultiplied alpha values - I've explained the difference between the shader output values used in blending here. There is no way to create a blending formula such that you can multiply the alpha into the RGB channel before multiplying by the destination color. Here is an example showing the difference in result. It may look okay when the output alpha is set to 1.0 but it is not at all right otherwise. This is using this normal PNG from the repo which is storing color as "straight alpha" (ie non-premultiplied):
Top left: premultipliedAlpha = false, NormalBlending |
|
Similar to this issue, this is another issue where correctness gets in the way of a nice user development experience. If the user sets
Using So, is there something we can do that doesn't break the user's development flow even if it's not 100% correct? Maybe logging a warning but still getting an okay output? |
I think I will need to understand why you are doing that in this example... EDIT. Oh, I assume you want to render a shadow under the car, and you are using THREE.MultiplyBlending for that. // #31246 explains the motivation for the implemented change. It also explains the behavior you should see. I tested it again today, and it is working as intended. I understand your concern about the premultiplied alpha limitation and the warning, but I am not sure what to do about it so far. A live example may help. |
This is because you're using a texture with 1.0 alpha and opacity 1.0. It will work in this case but break as soon as you try to do anything else. Here's what happens if you try to set the opacity to anything other than 1.0 in order to fade the effect:
Top left: premultipliedAlpha = false, opacity = 1.0, Custom blending with the "MultiplyBlending" factors specified Notice that the "multiply" effect is now impossible to fade.
We should decide what to do when a user specifies an invalid combination of settings, then. We can't support every combination of everything and even then not every combination of every setting is even possible (as seen here) but I don't think half-implementations of a feature are the solution. This will just cause worse confusion in other cases. The log also tells you what you can do to fix the issue, which will work just fine unless you've written a custom shader that does not support the "premultipliedAlpha" flag correctly. Generally I think we should be ferrying people towards "correct" solutions, which the log does. If anything I would consider implicitly treating "premultipliedAlpha" as true if the user is specifying "Multiply" or "Subtractive" blending even if it's set to false and keeping the warning. Then the setting will seem to work as long as a shader that supports premultipliedAlpha is being used. |
If it would work in this case, why are we breaking the blending and throwing and error? 🤔 Shouldn't we check if opacity < 1 before breaking at least? |
No because we can't know if the shader is going to output fragments with partial alpha. This only works in your case because your whole texture is alpha = 1.0 and opacity is 1.0. If any of those resulting fragments are < 1.0 from custom shader logic, texture alpha, opacity, etc then the result will be incorrect. |
|
I guess the solution here is to solve #32472 then... |
|
Another option would be switching Maybe we can do that while we solve #32472. |
Yeah this is what I suggested in #32542 (comment):
I think this is a reasonable solution. It will only break if the user has written a custom shader that doesn't respect the premultiply alpha flag but I think this is a more simple case and at that point we're already dealing with someone who is a bit more knowledgeable about shaders and blending.
I think it would be good to make sure more of the project supports the flag correctly and make sure that at least the examples are encouraging writing shaders that support it. I go back and forth on whether it should be defaulted to "true", though. Either way with node materials we should be able to make sure that all shaders "just work" with the flag since we can control the final generated shader and make sure the pre multiplication is applied. |
9023ca8 to
a6a95c1
Compare
|
@gkjohnson Looks good? |
a6a95c1 to
7fbd9d5
Compare
… or SubtractiveBlending.
7fbd9d5 to
f02e6c1
Compare
I don't think so. The shader has to be recompiled, too. See #31166 (comment). |
|
Oh! So we need to set |
|
// Not to hijack the thread, but in addition, the three.js built-in materials cannot properly handle loading premultiplied alpha textures, such as EXR files, which are premultiplied by default. There is no texture flag that says "this texture already has alpha premultiplied." EDIT -- well, TSL has Any consideration of improving the API should address both of these issues. |



Related issue: #31246
Description
When
MultiplyBlendingorSubtractiveBlendingis used withoutpremultipliedAlpha = true, the renderer now:premultipliedAlphatotrueso the scene renders correctlyThis improves the developer experience by producing correct output while informing users about the requirement.