0 votes

Greetings,

Is there a way to render a scene to a texture, free the scene and then use the texture as image.

I have some custom GraphNodes. I want to generate preview images for each node automatically when the game starts. I want to use these textures as items in an ItemList. I tried the following:

The scene I am trying to render to a texture has the following hierarchy.

enter image description here

I have a script attached to an ItemList node in another scene (my main scene). In the ready method of the ItemList node I use gettexture to get the texture from the Viewport of the instantiated scene I wish to render to a texture and then I try to add an item to the ItemList using the texture I just created. This is the script I am using in the ItemList node:

extends ItemList

func _ready():
    var scene = load("res://Scenes/Previews/Vector3NodePreview.tscn").instance()
    var imageTexture = ImageTexture.new()
    var image = scene.get_node("Viewport").get_texture().get_data()
    imageTexture.create_from_image(image)
    add_item(scene.get_node("Viewport/Node").title, imageTexture)
    pass

The only way I got it to render to a texture was to have the ViewportContainer be a child of my main scene. Then the code above works. However, the ViewportContainer renders ontop of my main scene as well. If I set the Visible property to false of the ViewportContainer, then the texture becomes empty. If I make the ViewportContainer render behind it's parent, then touches stop working.

What am I doing wrong and how can I achieve the effect I desire?

To put it into more simple words: I want to render a single frame of a scene to a texture and then use that texture as am ItemList item.

asked Apr 3, 2019 in Engine by Juxxec (63 points)
retagged Apr 4, 2019 by Juxxec

1 Answer

0 votes

You can query the image data from the viewport texture.

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

and assign it to another texture (here assigned to a TextureRect control):

var tex=ImageTexture.new()
tex.create_from_image(img)
aTextureRectNode.texture=tex

I use it for transferring a viewport over the network (remote controlling an app). It should work. :-)

answered Apr 3, 2019 by wombatstampede (3,185 points)

Greeting wombatstampede,

I tried what you suggest, but it is still not working. I updated my question with more details.

Greetings!

I managed to solve my problems, though I do not fully understand why my code works.

I chaned the script attached to the ItemList to this:

extends ItemList

var preview_generated = false

func _ready():
    pass

func _process(delta):
    if (!preview_generated):
        generate_previews(["res://Scenes/Previews/Vector3NodePreview.tscn"])
        preview_generated = true

func generate_previews(nodes):
    for node in nodes:
        var scene : Node = load(node).instance()
        add_child(scene)
        yield(get_tree(), "idle_frame")
        var imageTexture = ImageTexture.new()
        var image = Image.new()
        image.copy_from(scene.get_node("Viewport").get_texture().get_data())
        imageTexture.create_from_image(image)
        add_item(scene.get_node("Viewport/Node").title, imageTexture)
        remove_child(scene)
        scene.queue_free()

Without the addchiild / removechild lines the script does not work. Without the yield(gettree(), "idleframe") the code does not work ether.

Does anyone know why?

First of all:
Good idea to use image.copy_from. That eliminates the possibility that the data from get_data() is shared. (I'm unsure about that though())

You're loading a scene and then instanciating it. Probably it won't render (to the viewport) unless it is part of the scenetree. Therefore adding it as a child helps.

Also it won't render unless at least one (or two) "frame" has passed.
This is described here under "Capture":
https://docs.godotengine.org/en/3.1/tutorials/viewports/viewports.html

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 How to use this Q&A? before posting your first questions.