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.