Created
December 30, 2022 20:49
-
-
Save wojtekpil/b4e526a69058bc5cb13aa4c28e57a222 to your computer and use it in GitHub Desktop.
Godot 4 - Rendering pipeline with 32 bits image attachment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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