-
-
Notifications
You must be signed in to change notification settings - Fork 21.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
Shaders rendered on a transparent viewport are darker #17574
Comments
I wonder if this is related to premultiplied alpha in some way. This is available as an import setting in textures, but I'm not sure if you can toggle it in viewports. |
It is as expected, I was thinking about premultiplying alpha as a post process in viewports, in case you want to use premult, but this wont happen until 3.2 |
Well then, is there any known workaround? I haven't been able to find one myself. This issue seems fairly annoying as my use case for rendering shaders on a viewport, instead of on a node in the root scene, is so I can cut off edges like this: But I don't know if there's any other nodes or methods that will let me do that. |
Would definitely be great to have this added, it seems like I'm stuck with this problem as my tool uses viewports and alpha blended particles. I thought I'd had some success with using a premultiplied shader when drawing the particles, but that screws up as soon as I change their lifetime colour. Guess I'll have to wait until 3.2.. |
ran into the same problem with some custom post processing tests and transparent objects in an extra viewport on the current 3.1 Beta https://i.imgur.com/fQBRMHP.png I think I can somewhat confirm the premultiplied alpha as a cause. In the shader of the object in the vieport I used
and in the shader of the ViewportContainer I used and the problem seems to be nearly gone (small differences remain). |
Looks like sRGB -> linear issues. Make sure everything is kept in linear space until the very end. |
@clayjohn Could you explain? All I'm doing is running a shader that outputs red, with an alpha value that lowers the farther it is from a point -- then the output of that shader is going through a transparent viewport. I'm not sure what sRGB space and linear space have to do with this. |
@LikeLakers2 Depending on your asset workflow there may be sRGB -> linear conversions going on. If the hint of the texture you are using is "hint_albedo" it may force an sRGB -> linear conversion. Depending on the texture settings/viewport settings your viewport may be converting from sRGB -> linear after being rendered to (in anticipation of being used as a texture) in which case you would need to set "hint_albedo". |
@clayjohn The shader code I used for the images in the original posts contains no uniforms, though -- that is, the gradient shown is made entirely with code:
There are no textures to speak of aside from the texture that the shader outputs to the Viewport, and the texture that the Viewport outputs to the Sprite -- so I'm not sure where |
@LikeLakers2 I'm talking about when rendering the Viewport to the screen. |
@clayjohn I'm still not following you. Honestly, I'm becoming more confused with each comment. Please do me a favor if you think it has to do with sRGB -> linear conversions: Open up the reproduction project in the original post, and see if you can fix the issue without changing the structure of the scene tree. If you can, tell me how to do it. |
Adding
Hope it helps to you too |
@devolonter That seems to fix my issue, at least with my reproduction project. Thank you. That said, it doesn't sound quite like an obvious solution to this problem, unless you know that this is an issue related to pre-multiplied alpha -- which, given Godot's target demographic, doesn't sound like something I would expect the average user to know. In fact, I only knew about the term once Calinou and reduz chimed in. @Calinou @akien-mga (not sure which of you to ping, both of you seem appropriate) Would we consider this a fixed issue since we have a solution? Or should the issue be kept open until something else can be done to help this issue? |
We should still find a way to document the workaround, but I'm not sure where we should add this information. Any ideas? |
@Calinou I fear that people may not look in the documentation, seeing as how this may come off as a bug... or if they do look in the documentation, it may not be quite obvious where to look. Do they look under Viewport? Sprite? Shader? etc. Perhaps, if a viewport is marked as transparent, we could scan for nodes under it that use shaders, and emit a warning next to the Viewport node if any of them are not using Otherwise, if we aren't going to add a warning next to the Viewport node, it may be best to just document it in as many relevant places as possible, so that we can ensure people will notice. |
It seems not just for shaders, I tried making a minimap in a viewport, using a simple tilemap with colored squares, and if I made the white square 50% opacity, it would render differently inside the viewport:
Edit: I attempted to work around the issue applying the suggested shader above to the tilemap node in my viewport, to set:
And it had no effect, still renders darker. |
@devolonter They said |
@LikeLakers2 oops, my bad. Perhaps because I spent a whole day to find a similar problem with mipmaps 😅 |
Has anybody applied a successful workaround when doing multi-pass post-processing with ViewportContainers from a 3D Viewport? Nothing seems to work in that case... |
Still valid in 3.4. This needs to be documented somewhere, I just spend a whole day figuring out why my shader was producing wrong results. |
This may have been fixed with the recent changes to Viewport transparency and post processing (coming in 3.5) Can someone please test this once 3.5 releases and confirm whether it is still a problem? |
I have what seems to be a similar or related issue (writing here to document for people with similar issues) When I assign an Image Texture to a Sprite in a Viewport I transparent areas darken: drawing_with_viewports_transparency_issue01.mp4This is my project: Code: extends Sprite
onready var capture_viewport = $"../../.."
onready var capture_layer = $"../../../capture_layer"
onready var viewport = get_parent()
func _process(_delta):
if Input.is_action_just_pressed("LMB"):
viewport.render_target_clear_mode = Viewport.CLEAR_MODE_NEVER
elif Input.is_action_just_released("LMB"):
render_to_texture()
viewport.render_target_clear_mode = Viewport.CLEAR_MODE_ALWAYS
if Input.is_key_pressed(KEY_R):
var _reload = get_tree().reload_current_scene()
if Input.is_action_just_pressed("Save"):
var viewport_data = capture_viewport.get_texture().get_data()
viewport_data.flip_y()
var filepath = str(OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP),"/drawing.png")
viewport_data.save_png(filepath)
global_position = get_global_mouse_position()
func render_to_texture():
var viewport_data = capture_viewport.get_texture().get_data()
viewport_data.flip_y()
var img_tex = ImageTexture.new()
img_tex.create_from_image(viewport_data)
capture_layer.texture = img_tex
Minimal Reproduction Project Download: I've tried pretty much everything I could think of. Made a Reddit post and TheDuriel lead me here. I also tried to apply the fixes mentioned here in various ways, most of it did not work. However eventually: Adding shader_type canvas_item;
render_mode blend_premul_alpha; to the capture_layer fixed the "getting darker with every stroke", while adding the same material to the ViewportContainer2 fixed the overall darkness of transparent areas. @clayjohn : I also tested this project in Godot 3.5 RC6 without noticing any difference to Godot 3.4.4, before and after the fix. |
@golddotasksquestions thank you so much for sharing this. I was running into a similar problem where my viewport textures were taking on a black border that didn't appear when using the texture outside of a viewport. It seems that applying a very simple premult shader to the top-level node(s) in a viewport is the best workaround (for now). See the picture below, in which the middle image has a small black border at the points where the left image became transparent. Using a premult blend mode shader on the viewport textures fixes the issue (right image). This was tested in |
My issues are the same as in the first post. With transparent_bg=true everything semi-transparent gets darkened Currently, to fix this I'm setting shaders or adding this code to shaders on everything that has semi-transparency, and it seems to fix the darkening, but it's very inconvenient. Here's the shader – use it or correct me if I'm doing it wrong This is for canvas item shaders:
and this code on ViewportContainer shader:
Is there going to be an option to simplify this process somehow? |
My problem is (was) maybe a bit different, I'm making a single texture from 4 different textures (each texture for each channel (RGBA)), rendering them on a Viewport, and getting the result texture. I wanted each channel to remain intact and not be premultiplied by the alpha, but I got: This (with the default blend mode in the shader)(This is the (single) result texture showing each channel separately) (Each channel color is being premultiplied by the alpha) And after adding I'm commenting this since in my case it wasn't obvious, I wasn't looking for the colors to be premultiplied, but adding the premultiply_alpha blend ironically made the texture to not be premultiplied by the alpha. Maybe I'm missing something, but it is confusing. IMHO it should be documented somewhere, maybe add some more text to the Viewport's tooltip on the @Ariorick I'm not sure the result you are trying to achieve and the result you are having, but based on my experience, I'd try to delete the For the people loading images directly to the viewport, try to check the format you are saving your pngs. There are some formats that premultiply the alpha when saving the image. |
We're also experiencing this issue. We're dynamically generating images of sprite sheeted characters for optimization purposes and this is causing a lot of problems. |
I ran into this exact issue, and I think it's kind of strange it still hasn't been fixed... I mean, if the workaround is simply some shader code applied here and there, why not simply make Godot write this same shader code and apply it automatically whenever "Transparent Bg == true"? |
I am having a similar issue in Godot v3.4.4 stable, but I am using a 3D viewport, a spatial shader material with alpha = 1.0, and no display texture at all. I just have two cameras looking at (different parts of) the same object, with one rendering to the root viewport and the other rendering to a separate viewport that I created. This second viewport has transparent background enabled. In the image above, both the root viewport and the secondary viewport node render to the entire screen, but the root viewport shows through the transparent background of the second viewport. You can see the color difference between the left side of the screen (root) and the right side (secondary) - the right side is substantially darker. Can someone clarify if this is the same issue, and if so, is there a fix or workaround for spatial materials? |
I'm somewhat confused by this, because I'm not using my secondary viewport's output as input to another shader at all. Also, the texture should be opaque anyway: in fact I just tested it by literally setting the alpha channel to 1.0, and the problem persists. Are you sure this only happens with semi-transparent materials, or is this a different bug? |
Even when no shader is applied at all, the problem occurs. In fact, the fix is made simply by adding this shader code: But, as for the problem persisting even when opaque, that's strange... |
This render mode doesn't exist in 3D – you have to emulate it within the shader. See godotengine/godot-proposals#3431. |
Godot version:
Godot Engine v3.0.2.stable.official
OS/device including version:
Windows 10 Home v1709 (Fall Creator's Update); Nvidia GTX 660 (I don't believe this is specific to my GPU, though)
Issue description:
Shaders that get rendered on a transparent viewport (with nothing behind them) end up darker than they normally should. This can be solved by moving the object with a shader outside of any custom viewport, but I imagine that would end up getting messy quick, if viewports are being relied upon in some way.
What's expected:
What actually happened:
I believe this has to do with how the transparent viewport itself is handled, as having something behind the shader under the viewport will cause the shader to not be dark. (Try moving the ColorRect to under the Viewport, above ShaderPanel, in the reproduction project to see what I mean.)
Steps to reproduce:
Minimal reproduction project:
Shader Blackness.zip
The text was updated successfully, but these errors were encountered: