Screen Capture of Draw Function

Godot Version

4.2.2

Question

Hi,

I’ve been using godot’s draw function to create what is essentially pie charts. The idea is that when I minimize the viewport on which they’re drawn, I’d screenshot it and use that as a thumbnail for the button that brings it back up.

This is the code I’ve been using to capture it:

await RenderingServer.frame_post_draw

clockDisplay.get_texture().get_image().save_png("C:/Users/Player/Test/screenshot.png")

clockDisplay is the subViewport that the draw function uses.

However, all I ever get is a blank image for the screenshot. If I use it on the main viewport, it captures everything except the drawn elements.

The Clear Mode is set to Never like I’ve seen advised. Is it that _draw cannot be screenshotted, or am I doing it wrong?

You’re doing something wrong. Your post is a bit sparse on details, so all I can tell you is that the following minimal example worked fine for me:

func _ready() -> void:
	await RenderingServer.frame_post_draw
	get_viewport().get_texture().get_image().save_png("user://test.png")

func _draw() -> void:
	draw_circle(Vector2(100, 100), 50, Color.RED)

You’re 100% correct. I don’t know why it was giving me issues on the main viewport before. You’ve helped me narrow down the issue and it seems to be that I’m using a subViewport.

If it helps, this is what my tree looks like with the subViewport highlighted. I was running the script from the subViewportContainer node that holds it and that gave me a blank screenshot. I’ve now tried to have it directly running from the subViewport instead but that also gives me a blank screenshot.
If I use get_viewport() as in your example, it uses the main viewport and that does screenshot the _draw function as well (along with everything else). So push comes to shove I can use that as a workaround.
I’d still like to figure out why it’s not working for the subViewport though.

For anyone who may find this useful in the future, I’ve implemented a workaround:

	await RenderingServer.frame_post_draw
	get_viewport().get_texture().get_image().get_region(Rect2i(610, 190, 700, 700)).save_png("C:/Users/Player/Test/Screenshot.png")

This uses the main viewport and I’m just capturing the region that I need from it as found here: Image — Godot Engine (stable) documentation in English.
The values in the Rect2i bracket are the position and size of the screenshot I need as explained here: Rect2i — Godot Engine (stable) documentation in English

Thank you

Still can’t reproduce your issue! My tree now looks like this:

  • Control A
    • SubViewportContainer
      • SubViewport
        • Control B

I didn’t change any settings whatsoever. “Control B” has a script with just the _draw function I used above, whereas “Control A” only contains the _ready function now:

func _ready() -> void:
	await RenderingServer.frame_post_draw
	$SubViewportContainer/SubViewport.get_texture().get_image().save_png("user://test.png")

Works like a charm! The screenshot is smaller than before (since the default size for SubViewport is 512x512 pixels), but still contains the red circle.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.