Help with rendering viewport to texture

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Rubixnoob13

I’m working on a project that procedurally generates levels for a game. I have code that successfully works, however I’ve tested some things and I am looking to optimize the code.

Basically, right now I am generating a world of 10x10 rooms, each room is 10x8 tiles, and each tile is a 64x64 2D sprite. Effectively, right now everything works, but if I want to get much larger with the map, I’m running into some performance issues on the test machine.

What I am attempting to do is position a 10x8 room worth of 64x64 sprites into viewport, then save that viewport as a texture, so instead of rendering 80 textures per room, I am only rendering 1. I’ve tested manually placing “big textures”, and I know the performance is much better than a ton of small tiles.

I know the game by default has a viewport. I was trying to find some tutorials online, and I ran into a few 404 errors, or ones that simply grab the default viewport. Ideally, I’d like to have an offscreen viewport, although I’m not even sure this is possible.

What I have working so far:

yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
var img = get_viewport().get_texture().get_data()
var tex = ImageTexture.new()
tex.create_from_image(img)
img.flip_y()
img.save_png("user://screenshot.png")

However, the above code will only grab the current viewport. What I want is to have another Viewport which is a child of the Node2D, for example named “TexMaker”. I’ve attempted to do the following:

yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
***THE LINE BELOW THIS IS THE ONLY CHANGE***
var img = get_parent().get_node("TexMaker").get_texture().get_data()
var tex = ImageTexture.new()
tex.create_from_image(img)
img.flip_y()
img.save_png("user://screenshot.png")

When I run the second code, the scene tree is simply:
Node2D named “Game”
|-> Child Node Viewport named “TexMaker”
|->->Camera2D which is a child of “TexMaker” and set to current

For some reason, when I run this code, all I get is a blank screenshot.png that is the size of the viewport “TexMaker”. I was of the understanding that you can use viewports as like an offscreen render target, then save the contents to a texture to use later, which is what I am attempting to do, however I’ve been stuck on this for around 2 hours now so I decided to ask for some help. Thanks in advance for any tips or advice!

:bust_in_silhouette: Reply From: andersmmg

Assuming your node reference is correct, the problem is probably with the viewport itself. Make sure the viewport and the camera have a size, and that the camera is displaying on the viewport.