Skip to content

Instantly share code, notes, and snippets.

@wojtekpil
Created December 30, 2022 20:49
Show Gist options
  • Save wojtekpil/b4e526a69058bc5cb13aa4c28e57a222 to your computer and use it in GitHub Desktop.
Save wojtekpil/b4e526a69058bc5cb13aa4c28e57a222 to your computer and use it in GitHub Desktop.
Godot 4 - Rendering pipeline with 32 bits image attachment
extends Node
# based on https://github.com/pkdawson/rd_demo/blob/master/demo.gd
# CC0-1.0 license
#path to TextureRect node for visualisations
@onready var texture_rect = $"../VBoxContainer/TextureRect"
var vertSrc = "#version 450
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
}"
var fragSrc = "#version 450
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(1.0, 0.0, 0.0, 1.0);
}"
var framebuffer: RID
var pipeline: RID
var shader: RID
var img_texture: RID
var clearColors := PackedColorArray([Color.TRANSPARENT])
@onready var rd := RenderingServer.get_rendering_device()
func gen_texture() -> RID:
var tf = RDTextureFormat.new()
tf.format = RenderingDevice.DATA_FORMAT_R32G32B32A32_SFLOAT
tf.height = 512
tf.width = 512
tf.usage_bits = RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT | RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT
tf.texture_type = RenderingDevice.TEXTURE_TYPE_2D
var channels = 4
var bytes_per_channel = 4
var data = PackedByteArray()
data.resize(tf.height *tf.width*channels*bytes_per_channel)
var texture_rid = rd.texture_create(tf,RDTextureView.new(), [data])
return texture_rid
func create_framebuffer(imageTexture: RID):
framebuffer = rd.framebuffer_create([imageTexture])
func _ready():
var src := RDShaderSource.new()
src.source_fragment = fragSrc
src.source_vertex = vertSrc
var spirv := rd.shader_compile_spirv_from_source(src)
shader = rd.shader_create_from_spirv(spirv)
img_texture = gen_texture()
create_framebuffer(img_texture)
var blend := RDPipelineColorBlendState.new()
blend.attachments.push_back(RDPipelineColorBlendStateAttachment.new())
pipeline = rd.render_pipeline_create(
shader,
rd.screen_get_framebuffer_format(),
-1,
RenderingDevice.RENDER_PRIMITIVE_TRIANGLES,
RDPipelineRasterizationState.new(),
RDPipelineMultisampleState.new(),
RDPipelineDepthStencilState.new(),
blend
)
func _exit_tree():
rd.free_rid(pipeline)
rd.free_rid(framebuffer)
rd.free_rid(shader)
rd.free_rid(img_texture)
func update_texture():
# This is workaround for extrating texture data and putting it TextureRect
# Relays a lot of GPU -> CPU -> GPU copying so not ideal
# But usually output of this would be used by other things like e.g Compute Shaders
var data = rd.texture_get_data(img_texture, 0)
var dynImage = Image.create_from_data(512,512,false,Image.FORMAT_RGBAF, data)
var imageTexture = ImageTexture.create_from_image(dynImage)
texture_rect.texture = imageTexture
func _process(_delta):
# handle resizing
if not rd.framebuffer_is_valid(framebuffer):
print("Issue")
var draw_list := rd.draw_list_begin(framebuffer,
RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ,
RenderingDevice.INITIAL_ACTION_CLEAR, RenderingDevice.FINAL_ACTION_READ,
clearColors)
rd.draw_list_bind_render_pipeline(draw_list, pipeline)
rd.draw_list_draw(draw_list, false, 1, 3)
rd.draw_list_end()
update_texture()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment