godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.11k stars 20.2k forks source link

Viewport.get_texture() not correct when alpha!=1.0 #91828

Open CsloudX opened 4 months ago

CsloudX commented 4 months ago

Tested versions

v4.3.dev6.mono.official [89850d553]

System information

Godot v4.3.dev6.mono - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1060 5GB (NVIDIA; 31.0.15.3623) - AMD Ryzen 9 3900X 12-Core Processor (24 Threads)

Issue description

I'm create a scene like this: image

and set viewport's transparent_bg to true: image

then set ColorRect's color with alpha <= 1.0: image

then coding like this: image

then the output like this: image

Steps to reproduce

see above

Minimal reproduction project (MRP)

viewporttest.zip

timothyqiu commented 4 months ago

Seems to be a long existing issue, see #20069.

waci11 commented 3 days ago

I also have the same problem . i think , this may be due to the viewport did not directly render ColorRect, but instead rendered ColorRect with a background which is color.black and then set the alpha .

Tested versions :v4.3.stable.official [77dcf97d8] System information : macos 10.15.7 just create a subviewport , then add this script to it :

extends SubViewport

func _ready() -> void: 
    render_target_update_mode=UPDATE_ALWAYS
    var cr:=ColorRect.new()
    cr.color=Color8(12,23,35,123)
    add_child(cr)
    cr.size=Vector2.ONE
    print("default_clear_color black : ")
    RenderingServer.set_default_clear_color(Color.BLACK)
    transparent_bg=false
    await RenderingServer.frame_post_draw
    print(get_texture().get_image().get_pixel(0,0))
    transparent_bg=true
    await RenderingServer.frame_post_draw
    print(get_texture().get_image().get_pixel(0,0))
    print("default_clear_color white : ")
    RenderingServer.set_default_clear_color(Color.WHITE)
    transparent_bg=false
    await RenderingServer.frame_post_draw
    print(get_texture().get_image().get_pixel(0,0))
    transparent_bg=true
    await RenderingServer.frame_post_draw
    print(get_texture().get_image().get_pixel(0,0))

the log :

default_clear_color black : 
(0.0235, 0.0431, 0.0667, 1)
(0.0235, 0.0431, 0.0667, 0.4824)
default_clear_color white : 
(0.5412, 0.5608, 0.5843, 1)
(0.0235, 0.0431, 0.0667, 0.4824)

I found that adding a material with BLEND_MODE_PREMULT_ALPHA can solve the problem . But it is only effective when there is only one ColorRect .

add this script to a subviewport :

func _ready() -> void: 
    render_target_update_mode=UPDATE_ALWAYS
    var cr:=ColorRect.new()
    cr.color=Color8(17,123,35,23)
    print("ColorRect color : " , cr.color)
    add_child(cr)
    cr.size=Vector2.ONE
    cr.material=CanvasItemMaterial.new()
    cr.material.blend_mode=CanvasItemMaterial.BLEND_MODE_PREMULT_ALPHA
    transparent_bg=true
    await RenderingServer.frame_post_draw
    print(get_texture().get_image().get_pixel(0,0))

the log:

ColorRect color : (0.0667, 0.4824, 0.1373, 0.0902)
(0.0667, 0.4824, 0.1373, 0.0902)