+7 votes

So far I've been using sprite.set_texture(get_viewport().get_texture()) and it kind of works, but once I add the sprite to the game using add_child(sprite) it is placed at the top, over all my other sprites, while I want it to be below them all, so I set .z on my sprites to 1 and now it's below, but for some reason the generated texture/screenshot only includes graphics that are at or below the sprite receiving the screenshot, everything above gets excluded, which I find strange since get_viewport().get_texture() should work independently from the sprite receiving it, if I bump its z-index to 1 as well the sprites show up again in the screenshot, but again, the sprites are placed below the screenshot sprite instead of over it, which is not desired.

Here is my code:

extends Node2D

var screen = Sprite.new()

func _ready():
    var texture = get_viewport().get_texture()
    screen.centered = true
    screen.flip_v = true
    screen.z = 0

func _process(delta):
    var texture = get_viewport().get_texture()

If I try to place the sprites on top not with z-index but using an add_child order the same thing happens.

One idea I have is that maybe there is some rendering pipeline that renders the sprites in the order of the z-index, from bottom to top, and the screenshot is executed not at the end of this process but at the point when the sprite receiving the screenshot gets rendered, and so anything rendered after that (items with a greater z-index) don't get included.

Any ideas?

I'm new to Godot, and I'm using Godot 3 Beta 2.

in Engine by (21 points)

1 Answer

+3 votes


Very old question without answer. I'm answering for Godot 3.2.1, taking a screenshot, which become assignable to a Sprite. I don't know the trick with the z-index, sorry.

There is an example of code in the Templates (you can load it from the project manager):

Screen Capture Demo

func take_screenshot():
    var old_clear_mode =get_viewport().get_clear_mode()
    # Let two frames pass to make sure the screen was captured.
    yield(get_tree(), "idle_frame")
    yield(get_tree(), "idle_frame")

    # Retrieve the captured image.
    var img = get_viewport().get_texture().get_data()
    # restore the previous value, as some part wont redraw after...

    # Flip it on the y-axis (because it's flipped).

   # I also want a thumbnail 1/3 size
    var s = img.get_size()
    var scale_reduce = 0.3
    img.resize(s.x * scale_reduce, s.y * scale_reduce)

    # I crop it to my need 
    var border = get_parent().get_node("border")
    var border_s = border.to_global(border.texture.get_size())
    var border_p = border.to_global(border.position)
    var zone = Rect2(Vector2(0,0), border_s * scale_reduce)

    # copy to a new image, I need to create it first with the same size with create()
    var imgDest = Image.new()
    imgDest.create(zone.size.x, zone.size.y, false, img.get_format())
    imgDest.blit_rect(img, zone, Vector2.ZERO)

    # Create a texture for it.
    var tex = ImageTexture.new()

    # the texture can be assigned to a Sprite2D or a TextureRect
    $mini.texture = tex

Hope that helps.

by (40 points)

Godot 4 update:

var img = get_viewport().get_texture().get_data()


var img = get_viewport().get_texture().get_image()

(no need to flip y anymore; maybe later, if 4.1 supports OpenGL again and you use that, you may need to)

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.