Skip to content
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

Image captured from viewport results in garbled png when saved #56687

Open
tcrass opened this issue Jan 11, 2022 · 8 comments
Open

Image captured from viewport results in garbled png when saved #56687

tcrass opened this issue Jan 11, 2022 · 8 comments

Comments

@tcrass
Copy link

tcrass commented Jan 11, 2022

Godot version

3.4.2

System information

Debian Linux 11 "Bullseye", ATI RX580, GLES3

Issue description

I'm using a viewport containing some GUI controls for creating a texture for a mesh. This works great so far, but when I try to save the viewport's texture as PNG image, I seem to get some random noise rather than the texture image.

Here's a screenshot of the minimal reproduction project, showing the GUI viewport's texture applied to the mesh's albedo:

image

And here's what the exported PNG looked like in three consecutive launches:

image
image
image

I would, of course, expect the saved PNGs look exactly like what's visible on the mesh.

Steps to reproduce

Just launch the provided minimal reproduction project and have a look in your Godot user folder.

Minimal reproduction project

viewport-capture-test.zip

@akien-mga
Copy link
Member

akien-mga commented Jan 11, 2022

Script from the MRP for the record:

extends Spatial

func _ready():
	yield(VisualServer, "frame_post_draw")
	var texture = $Viewport.get_texture()
	($MeshInstance.mesh.surface_get_material(0) as SpatialMaterial).albedo_texture = texture
	var image = texture.get_data()
	image.save_png("user://hello-world.png")

yield(VisualServer, "frame_post_draw") was a good idea but it doesn't seem to be sufficient here, what you see is garbage from not-yet-initialized GPU memory. I found that replacing it by yield(get_tree(), "idle_frame") fixes the issue.

I'm not 100% sure why but evidently when _ready runs for that scene, not everything has been fully set-up in the VisualServer. Delaying by one frame for such operation is often a good idea. Probably needs better documentation (in Viewport.get_texture() maybe?).

Probably related, you can see that if you put a breakpoint statement at the start of your Capture scene's _ready, the execution will break before anything appears on screen. But if you break after a yield(get_tree(), "idle_frame"), then you'll see your scene as expected.

Edit: It also works without any yield if you move the Capture node up the tree. The problem is likely that when your Capture node is "ready", the Camera and DirectionalLight nodes aren't yet, as the scene tree is initialized in reverse tree order. Waiting one frame ensures that the whole scene tree is ready, and not just Capture and its children.

@tcrass
Copy link
Author

tcrass commented Jan 11, 2022

Hi,

yield(VisualServer, "frame_post_draw") was a good idea but it doesn't seem to be sufficient here, what you see is garbage from not-yet-initialized GPU memory. I found that replacing it by yield(get_tree(), "idle_frame") fixes the issue.

Edit: It also works without any yield if you move the Capture node up the tree. The problem is likely that when your Capture node is "ready", the Camera and DirectionalLight nodes aren't yet, as the scene tree is initialized in reverse tree order. Waiting one frame ensures that the whole scene tree is ready, and not just Capture and its children.

neither of these changes do fix it for me, still getting garbage... Maybe an OS- and/or hardware-specific problem?

Cheers --
Torsten

@Calinou Calinou added this to the 3.5 milestone Jan 11, 2022
@Calinou
Copy link
Member

Calinou commented Jan 11, 2022

Does it work if you use yield(get_tree(), "idle_frame") twice in succession? I believe this is what the screen capture demo does.

@tcrass
Copy link
Author

tcrass commented Jan 12, 2022

Does it work if you use yield(get_tree(), "idle_frame") twice in succession? I believe this is what the screen capture demo does.

Tried that already... Nope, it doesn't make any difference, no matter how many times I use any of the two versions of the yield call -- once, twice or like a dozen times.

Cheers --
Torsten

@HEPOSHEIKKI
Copy link

I am too having this issue, but instead of trying to save the texture to a file I'm trying to project it onto a Sprite3D.
I am on engine version 4.0.2 with Linux Kubuntu 22.02 and an AMD integrated GPU.

The project works without issue in the editor but after export the texture always gets garbled. I have tried exporting to windows too and running under wine, but I get the same result.

The garbled texture changes with whatever unrelated code the script contains. I have Included a demo to test this. The demo has two cameras both filming a moving object, the objects are there to show that the image projected onto a Sprite3D is not moving when it should, but everything else still works.

Sometimes instead of a garbled texture you just get black, seems to only happen when there are two instances running (eg. a debug build in the editor and an exported binary, or two exported binaries simultaneously)

Any ideas on how to fix this?

Demo: Godot4Sprite3DBugReport.zip

Here's an image from my personal project too, just in case:

image

@Walkingtall85
Copy link

Walkingtall85 commented Jun 20, 2023

We observed something similar with Godot 4.0. For us it seems like on initialisation the viewport texture is filled with random garbage. We've had it on Linux and Windows with two wholly different setups except for the graphics card being from Nvidia.

@HEPOSHEIKKI
Copy link

except for the graphics card being from Nvidia.

Can confirm that this issue persists on my laptop with integrated AMD Radeon graphics. Will ask my friend with a dedicated desktop Radeon GPU to test this out.

@HEPOSHEIKKI
Copy link

The issue persists on AMD GPUs


godotkakka

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants