71 lines
2.3 KiB
GDScript3
71 lines
2.3 KiB
GDScript3
|
extends Control
|
||
|
|
||
|
var viewport: Viewport
|
||
|
var render_queue: Array # of PoolByteArrays
|
||
|
var result_queue: Array # of PoolByteArrays
|
||
|
var current_image: Image
|
||
|
var current_tex: ImageTexture # Needed to prevent GC before draw
|
||
|
var waiting_for_viewport: bool
|
||
|
var done_first_draw: bool
|
||
|
|
||
|
func _ready() -> void:
|
||
|
self.viewport = get_parent()
|
||
|
self.render_queue = []
|
||
|
self.result_queue = []
|
||
|
self.waiting_for_viewport = false
|
||
|
self.done_first_draw = false
|
||
|
self.current_image = Image.new()
|
||
|
self.current_tex = ImageTexture.new()
|
||
|
|
||
|
func _process(_delta) -> void:
|
||
|
update()
|
||
|
|
||
|
func _draw() -> void:
|
||
|
# Seems like the first one always fails
|
||
|
if not self.done_first_draw:
|
||
|
self.done_first_draw = true
|
||
|
return
|
||
|
|
||
|
if self.waiting_for_viewport:
|
||
|
# Another node later in the draw sequence can call this within the same frame,
|
||
|
# otherwise, this picks it up the following frame
|
||
|
get_result()
|
||
|
|
||
|
if not self.render_queue:
|
||
|
return
|
||
|
|
||
|
# Draw the next ImageTexture
|
||
|
var data: PoolByteArray = self.render_queue.pop_front()
|
||
|
print(data.subarray(0, 15))
|
||
|
self.current_image.create_from_data(4096, 4096, false, Image.FORMAT_LA8, data)
|
||
|
self.current_tex.create_from_image(self.current_image, Texture.FLAG_FILTER)
|
||
|
self.material.set_shader_param('tex', self.current_tex)
|
||
|
draw_texture(self.current_tex, Vector2.ZERO)
|
||
|
self.waiting_for_viewport = true # Grab the result next draw
|
||
|
|
||
|
func get_result() -> void:
|
||
|
var result_texture := self.viewport.get_texture()
|
||
|
var result_image := result_texture.get_data()
|
||
|
var result_bytes := result_image.get_data()
|
||
|
|
||
|
# Debugging: compare a sequence of all the possible 16bit integers
|
||
|
print_debug('result_image format is %d and has size'%result_image.get_format(), result_image.get_size(), result_bytes.subarray(0, 11))
|
||
|
test_readback(result_bytes)
|
||
|
|
||
|
self.result_queue.append(result_bytes)
|
||
|
self.waiting_for_viewport = false
|
||
|
|
||
|
func test_readback(result_bytes: PoolByteArray):
|
||
|
# Debugging: compare a sequence of all the possible 16bit integers
|
||
|
var buff := StreamPeerBuffer.new()
|
||
|
buff.set_data_array(result_bytes)
|
||
|
var tex_readback = 0
|
||
|
var uv_readback = 0
|
||
|
for i in 0x1000:
|
||
|
tex_readback = buff.get_u16()
|
||
|
uv_readback = buff.get_u16()
|
||
|
if tex_readback != i:
|
||
|
print('tex readback %d (0x%04x) was instead %d (0x%04x)'%[i, i, tex_readback, tex_readback])
|
||
|
if uv_readback != i:
|
||
|
print('uv readback %d (0x%04x) was instead %d (0x%04x)'%[i, i, uv_readback, uv_readback])
|