Skip to content

Instantly share code, notes, and snippets.

@clayjohn
Created August 5, 2019 22:04
Show Gist options
  • Save clayjohn/80d9b1e52e1b9a23445504e85a8d7890 to your computer and use it in GitHub Desktop.
Save clayjohn/80d9b1e52e1b9a23445504e85a8d7890 to your computer and use it in GitHub Desktop.
Uses custom viewports to generate textures before the first frame is drawn
extends Node2D
var myViewport
var myCanvas
func _ready():
## Stop main viewport from drawing when we force draw
## should loop through all other viewports as well
VisualServer.viewport_set_active(get_viewport().get_viewport_rid(), false)
# initialize Viewport, needs canvas
myViewport = VisualServer.viewport_create()
myCanvas = VisualServer.canvas_create()
VisualServer.viewport_attach_canvas(myViewport, myCanvas)
VisualServer.viewport_set_size(myViewport, 64, 64)
## "active" instructs it to be drawn
VisualServer.viewport_set_active(myViewport, true)
## create CanvasItem and add to canvas just as in servers tutorial
var ci_rid = VisualServer.canvas_item_create()
VisualServer.viewport_set_canvas_transform(myViewport, myCanvas, Transform())
VisualServer.canvas_item_set_parent(ci_rid, myCanvas)
var sprite = load("res://icon.png")
VisualServer.canvas_item_add_texture_rect(ci_rid, Rect2(Vector2(0, 0), sprite.get_size()), sprite)
## draw it once, this should be bundled into a function
VisualServer.viewport_set_update_mode(myViewport, VisualServer.VIEWPORT_UPDATE_ONCE)
VisualServer.viewport_set_vflip(myViewport, true)
VisualServer.force_draw(false)
var image = VisualServer.texture_get_data(VisualServer.viewport_get_texture(myViewport))
var texture = ImageTexture.new()
texture.create_from_image(image)
$Sprite2.texture = texture
#exact same as above
VisualServer.viewport_set_update_mode(myViewport, VisualServer.VIEWPORT_UPDATE_ONCE)
VisualServer.viewport_set_vflip(myViewport, false)
VisualServer.force_draw(false)
var image2 = VisualServer.texture_get_data(VisualServer.viewport_get_texture(myViewport))
var texture2 = ImageTexture.new()
texture2.create_from_image(image2)
$Sprite3.texture = texture2
#prints 0 as no frames have actually drawn
print(Engine.get_frames_drawn())
#reset the main viewport so everything actually draws to screen
VisualServer.viewport_set_active(get_viewport().get_viewport_rid(), true)
@Flarkk
Copy link

Flarkk commented Apr 11, 2021

Ok got it, many thanks.
For now I’ll stick in waiting a bit the draw command complete (as the work is done on a thread, it doesn’t freeze the entire game).
I’ll rewrite the whole thing with compute shaders when Godot 4.0 is out, as it should allow to completely separate textures rendering from the draw process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment