-
-
Notifications
You must be signed in to change notification settings - Fork 21.2k
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
Add premult alpha blending to 3D (spatial) shaders #85609
Conversation
2f360d9
to
f7962aa
Compare
8d508fa
to
b305c5c
Compare
I suggest converting this PR to an implementation of a general-purpose Example: #ifdef DELAYED_RGB_MULTIPLIER_USED
vec3 delayed_rgb_multiplier = vec3(1.0);
#endif // DELAYED_RGB_MULTIPLIER_USED |
@OhiraKyou could you give me an example usecase of this multiplier being a vec3? what kind of effect would it enable? |
First, AssumptionsThe use cases described below assume the following:
Use casesCustom channel mixingCustom, per-channel post-processing of shader output colors—that includes lighting—may be applied in linear space by assigning a color multiplier to the delayed multiplier. This includes processing of per-channel, non-color data for custom buffer rendering. Custom colored lightingCustom colored lighting (with no actual light objects in a scene) may be implemented in linear space in otherwise sRGB compatibility renderer shaders by ignoring the existing lighting system (i.e., using |
We've discussed this PR in the rendering meeting and the design/thinking process around this is the following: Like everything in Godot, we want to first talk about problems, then solutions. Light multiplication is something I personally really want to do. I am hoping to be able to eventually have a post-light function (this is a wish, not a promise). But we need to respond with solution when there's a problem to begin with. But this is a whole different problem than what we're trying to solve here. Additionally, concerns have been brought up about leaving doors open for usecases that are not explicitely supported: this may be a problem in the future when optimizing shaders or refactoring them. I understand that we could say "any use outside of premul alpha is unsupported and you're on your own if you do it" but this historically has never worked: people depend on it, and are disappointed when we "break" things that were never supposed to work to begin with. I will bring this PR to completion in this dev cycle (4.3), unless something comes up, so that we can finally have premul alpha in 3D ^^ (integrating the render mode too) |
5a6fc8a
to
25f6dbc
Compare
25f6dbc
to
facda0d
Compare
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.
Great work! I left a few comments to help clean this up. Most of them are just enforcing a consistent naming of BLEND_MODE_PREMULT_ALPHA
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
Outdated
Show resolved
Hide resolved
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
Outdated
Show resolved
Hide resolved
7a38045
to
738c28f
Compare
Any idea if |
738c28f
to
d6335bc
Compare
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.
Looks great!
This PR uses a mix of |
See akien-mga's comment after the approval
2a0a535
to
b87eeeb
Compare
Co-authored-by: jitspoe <[email protected]> Co-authored-by: Clay John <[email protected]>
b87eeeb
to
41a2b0e
Compare
Thanks! |
@@ -688,6 +688,9 @@ void BaseMaterial3D::_update_shader() { | |||
case BLEND_MODE_MUL: | |||
code += "blend_mul"; | |||
break; | |||
case BLEND_MODE_PREMULT_ALPHA: | |||
code += "blend_premul_alpha"; |
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.
I merged a bit too fast, this one is still wrong.
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.
So it seems like we had this BLEND_MODE_PREMULT_ALPHA
but blend_premul_alpha
inconsistency in CanvasItem shaders already.
Should we fix it in Spatial shaders and accept that we have an inconsistency in 2D blend_premul_alpha
/ 3D blend_premult_alpha
, or should we do like in 2D?
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.
I noticed that too, but I'd rather not start touching things elsewhere for now
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.
I mean this one is a bug, it's writing blend_premul_alpha
in Spatial shaders but what's expected is blend_premult_alpha
. I haven't tested but I think the latest update before merge broke the feature.
So we have two options:
- Fix this one up to be
blend_premult_alpha
, and accept that 3D shaders will use a different keyword from 2D shaders - Go back to the previous version of your PR before my review (I didn't know you just replicated the inconsistency of existing 2D keywords) and use
blend_premul_alpha
in 3D too.
And yes to be clear we shouldn't change 2D shaders, that would break compat.
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.
I didn't remember either, and frankly I wonder if I did it on purpose or not. I'm not sure if we want to keep consistent with 2d and generally inconsistent, or if we should have correct 3d and weird 2D. Is there any precedent we can reference to take the decision?
@@ -609,6 +609,9 @@ | |||
<constant name="BLEND_MODE_MUL" value="3" enum="BlendMode"> | |||
The color of the object is multiplied by the background. | |||
</constant> | |||
<constant name="BLEND_MODE_PREMULT_ALPHA" value="4" enum="BlendMode"> | |||
The color of the object is added to the background and the alpha channel is used to mask out the background. This is effectively a hybrid of the blend mix and add modes, useful for FX like fire where you want the flame to add but the smoke to mix. By default, this works with unshaded materials using premultiplied textures. For shaded materials, use the PREMUL_ALPHA_FACTOR built-in so that lighting can be modulated as well. |
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.
Should be [code]PREMULT_ALPHA_FACTOR[/code]
.
Does this PR address fog making stuff light up that should be transparent? That was one thing I never got around to fixing on mine. |
case BLEND_MODE_PREMULT_ALPHA: { | ||
// This is unlikely to ever be used for detail textures, and in order for it to function in the editor, another bit must be used in MaterialKey, | ||
// but there are only 5 bits left, so I'm going to leave this disabled unless it's actually requested. | ||
//code += "\tvec3 detail = (1.0-detail_tex.a)*ALBEDO.rgb+detail_tex.rgb;\n"; |
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.
@QbieShay I don't understand why this is commented out. Before the nuance is lost to the sands of time can you expand a little more? 5 bits left where?
godot/scene/resources/material.h
Line 326 in f91db3d
uint64_t detail_blend_mode : get_num_bits(BLEND_MODE_MAX - 1); |
The bits as far as I can tell are already spent allocating BLEND_MODE_PREMULT_ALPHA
. Commenting it out just seems a little strange.
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.
Ah, that was probably taken from my original PR which didn't have the bits taken. I was hesitant to waste a bit for this, but if the bit is already taken, this should be uncommented.
Ok, just cherry-picked this and tested and verified that this does NOT properly address fog, at least independently. I did notice there were some other fog related things in the shader file that changed, but I don't think they're related. Guess that should still be addressed. To better explain, I'm using flame sprites with premult alpha, and if I have fog enabled, the whole quad starts becoming visible, (additively blended with the fog color). I thought maybe the premult_alpha_factor would somehow get used, but looking closer, I'm not really sure what premult_alpha_factor even does, as it seems to just be renamed to premult_alpha, which is a bit confusing. |
@jitspoe it's multiplied at the very end of the shader. Do you mind supplying a test scene with your setup (via DM is fine too) so that u can try and fix the dog issue? |
Can you share your shader? Are you writing to |
Make sure to also cherry-pick #91399 if testing on a branch different from upstream |
I havent had a chance to boot my dev PC yet but I think I understand the issue, I'll debug it later. If it is what I imagine, I need to multiply fog by alpha if render mode pmul alpha is on. |
Pmul alpha is already multiplied after fog though. I don't see why you would need to multiply it twice |
Because the fog should be applied only to the non transparent parts of a quad. Alpha zero, factor non zero = additive. |
@jitspoe Please test against latest master, I can't reproduce. Don't forget to use the PREMUL_ALPHA_FACTOR |
So it seems like PREMUL_ALPHA_FACTOR just scales the albedo color value, effectively turning it into a regular alpha, kind of defeating the purpose of the premultiplied aspect. Fixes the fog, but the whole point is to be able to have additive things like flames mixed in with alpha masked stuff like smoke. Unless I'm just not understanding how this is intended to be used? Still trying to understand the reasoning behind PREMUL_ALPHA_FACTOR. How is it different from just scaling ALBEDO? Building latest main now to do further tests. |
I'm moving the discussion to godotengine/godot-proposals#3431 (comment) so it's in one cohesive location, since there is a lot of other discussion in there as well. |
太棒了,多年来终于解决了这个问题。 |
Follow-up to #68548
Implements godotengine/godot-proposals#3431 (comment)