Topic was automatically imported from the old Question2Answer platform.
Asked By
bluenote
I’m trying to dynamically create a Viewport, render to it, fetch its contents (as a texture), and discard it again. As a basic test I’m using this script attached to a plain Node2D root node (nothing else in the scene tree):
extends Node2D
func _ready():
# Create viewport
var viewport = Viewport.new()
viewport.size = Vector2(200, 200)
# Create some test content
var rect = ColorRect.new()
rect.color = Color(1, 0, 0)
rect.rect_size = Vector2(100, 100)
# Add to scene
viewport.add_child(rect)
add_child(viewport)
# Wait for content
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
# Fetch viewport content
var texture = viewport.get_texture()
var image = texture.get_data()
image.save_png("test.png") # just as a debugging check
This works in the sense that the I do get a “test.png” output file. However, the file is just black – it looks like nothing has been rendered to the viewport. If I add the test content (the rect) directly as a child it renders fine.
What am I missing that I’m not getting any output from the viewport?
maybe you could try
#Add to scene
viewport.add_child(rect)
rect.show()
add_child(viewport)
Klagsam | 2019-12-14 09:22
@Klagsam Thanks for the suggestion. Unfortunately that doesn’t seem to make a difference for me. Does it work for you?
bluenote | 2019-12-14 10:12
I did not try it. I just had a similar problem which i could solve by adding that line.
(before edit)
I believe you need to add a Camera2D as well beneath your Viewport
as each viewport renders from the child camera beneath it (am not 100% sure tho)
I tried that as well, but it doesn’t make a difference. Also, I’ve seen many (working) examples of viewports without explicit sub-cameras. My understanding is that they come with an implicit camera (much like the root viewport), but if there is an explicit camera that one is preferred.
bluenote | 2019-12-14 20:26
omg I was so idiot you need to change the update_mode
viewport.render_target_update_mode =Viewport.UPDATE_ONCE
or
viewport.render_target_update_mode =Viewport.UPDATE_ALWAYS
extends Node2D
func _ready():
# Create viewport
var viewport = Viewport.new()
viewport.size = Vector2(200, 200)
viewport.render_target_update_mode =Viewport.UPDATE_ALWAYS
#var cam = Camera2D.new()
#viewport.add_child(cam)
# Create some test content
var rect = ColorRect.new()
rect.color = Color(1, 0, 0)
rect.rect_size = Vector2(100, 100)
# Add to scene
viewport.add_child(rect)
add_child(viewport)
# Wait for content
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
# Fetch viewport content
var texture = viewport.get_texture()
var image = texture.get_data()
image.save_png("test.png") # just as a debugging check
Xtremezero | 2019-12-15 02:33
That’s it, indeed the default of UPDATE_WHEN_VISIBLE implies that the viewport is simply not active. Thanks a lot!