diff --git a/rendering/mesh_texture_rd/2d_array_mesh.tres b/rendering/mesh_texture_rd/2d_array_mesh.tres new file mode 100644 index 00000000000..306abf7b1d4 --- /dev/null +++ b/rendering/mesh_texture_rd/2d_array_mesh.tres @@ -0,0 +1,15 @@ +[gd_resource type="ArrayMesh" format=3 uid="uid://j7duroqwmiuw"] + +[resource] +_surfaces = [{ +"2d": true, +"aabb": AABB(-64, -64, 0, 128, 128, 0), +"attribute_data": PackedByteArray(51, 51, 118, 63, 0, 0, 0, 0, 0, 0, 32, 61, 0, 0, 0, 0, 205, 204, 204, 58, 0, 0, 32, 61, 0, 0, 0, 0, 102, 102, 121, 63, 154, 153, 249, 60, 0, 0, 128, 63, 51, 51, 119, 63, 0, 0, 128, 63, 205, 204, 127, 63, 0, 0, 118, 63, 0, 0, 128, 63, 205, 204, 204, 60), +"format": 34393296913, +"index_count": 18, +"index_data": PackedByteArray(0, 0, 7, 0, 6, 0, 6, 0, 5, 0, 4, 0, 4, 0, 3, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 6, 0, 4, 0, 4, 0, 2, 0, 0, 0), +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 8, +"vertex_data": PackedByteArray(102, 102, 108, 66, 0, 0, 128, 194, 0, 0, 108, 194, 0, 0, 128, 194, 51, 51, 127, 194, 0, 0, 108, 194, 0, 0, 128, 194, 204, 204, 114, 66, 102, 102, 112, 194, 0, 0, 128, 66, 102, 102, 110, 66, 0, 0, 128, 66, 154, 153, 127, 66, 0, 0, 108, 66, 0, 0, 128, 66, 51, 51, 115, 194) +}] diff --git a/rendering/mesh_texture_rd/3d.tscn b/rendering/mesh_texture_rd/3d.tscn new file mode 100644 index 00000000000..64ed2b9a346 --- /dev/null +++ b/rendering/mesh_texture_rd/3d.tscn @@ -0,0 +1,39 @@ +[gd_scene load_steps=7 format=3 uid="uid://mx52oimcwqtn"] + +[ext_resource type="Texture2D" uid="uid://bg8txxwsr4qn8" path="res://text_texture.tres" id="1_y2yqg"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_y2yqg"] +sky_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1) +ground_horizon_color = Color(0.66224277, 0.6717428, 0.6867428, 1) + +[sub_resource type="Sky" id="Sky_fji6l"] +sky_material = SubResource("ProceduralSkyMaterial_y2yqg") + +[sub_resource type="Environment" id="Environment_73ytm"] +background_mode = 2 +sky = SubResource("Sky_fji6l") +tonemap_mode = 2 +glow_enabled = true + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_y2yqg"] +transparency = 1 +shading_mode = 0 +albedo_texture = ExtResource("1_y2yqg") + +[sub_resource type="BoxMesh" id="BoxMesh_p1i0w"] + +[node name="3d" type="Node3D"] + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_73ytm") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.8660254, -0.43301278, 0.25, 0, 0.49999997, 0.86602545, -0.50000006, 0.75, -0.43301266, 0, 0, 0) +shadow_enabled = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +material_override = SubResource("StandardMaterial3D_y2yqg") +mesh = SubResource("BoxMesh_p1i0w") + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(0.7071068, 0.5, -0.5, 0, 0.7071068, 0.70710677, 0.7071068, -0.5, 0.5, -1, 1, 1) diff --git a/rendering/mesh_texture_rd/README.md b/rendering/mesh_texture_rd/README.md new file mode 100644 index 00000000000..4478c71891b --- /dev/null +++ b/rendering/mesh_texture_rd/README.md @@ -0,0 +1,11 @@ +# Rasterize Mesh Texture + +This is a demo showing how to set up a basic render pipeline to draw mesh to texture using RenderingDevice. + +Language: GDScript + +Renderer: Mobile + +## Screenshots + +![Screenshot](screenshots/rasterize_mesh_texture.webp) diff --git a/rendering/mesh_texture_rd/base_texture.glsl b/rendering/mesh_texture_rd/base_texture.glsl new file mode 100644 index 00000000000..d4bb9b709db --- /dev/null +++ b/rendering/mesh_texture_rd/base_texture.glsl @@ -0,0 +1,29 @@ +#[vertex] +#version 450 + +layout(location = 0) in vec3 position; +layout(location = 1) in vec2 uv; + +layout(location = 0) out vec2 uv_interp; + +layout(push_constant) uniform Data { + mat4 xform; +}; + +void main() { + uv_interp = uv; + gl_Position = xform * vec4(position, 1.0); +} + +#[fragment] +#version 450 + +layout(location = 0) in vec2 uv_interp; + +layout(location = 0) out vec4 frag_color; + +layout(set = 0, binding = 0) uniform sampler2D tex; + +void main() { + frag_color = texture(tex, uv_interp); +} diff --git a/rendering/mesh_texture_rd/base_texture.glsl.import b/rendering/mesh_texture_rd/base_texture.glsl.import new file mode 100644 index 00000000000..1a460b0a8d1 --- /dev/null +++ b/rendering/mesh_texture_rd/base_texture.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bsbaafha2qt2x" +path="res://.godot/imported/base_texture.glsl-7668889287fcd72a7484b036a760efd0.res" + +[deps] + +source_file="res://base_texture.glsl" +dest_files=["res://.godot/imported/base_texture.glsl-7668889287fcd72a7484b036a760efd0.res"] + +[params] + diff --git a/rendering/mesh_texture_rd/godot_icon.svg b/rendering/mesh_texture_rd/godot_icon.svg new file mode 100644 index 00000000000..b370ceb7274 --- /dev/null +++ b/rendering/mesh_texture_rd/godot_icon.svg @@ -0,0 +1 @@ + diff --git a/rendering/mesh_texture_rd/godot_icon.svg.import b/rendering/mesh_texture_rd/godot_icon.svg.import new file mode 100644 index 00000000000..cf22642b3ca --- /dev/null +++ b/rendering/mesh_texture_rd/godot_icon.svg.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://crm65s53yy1n6" +path="res://.godot/imported/godot_icon.svg-7b3f4db08ef4bccb8acaa5db9e9fe760.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://godot_icon.svg" +dest_files=["res://.godot/imported/godot_icon.svg-7b3f4db08ef4bccb8acaa5db9e9fe760.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +process/resolution_scale=1.0 +detect_3d/compress_to=0 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/rendering/mesh_texture_rd/icon.webp b/rendering/mesh_texture_rd/icon.webp new file mode 100644 index 00000000000..4bf2b1ccd53 Binary files /dev/null and b/rendering/mesh_texture_rd/icon.webp differ diff --git a/rendering/mesh_texture_rd/icon.webp.import b/rendering/mesh_texture_rd/icon.webp.import new file mode 100644 index 00000000000..620301bdf65 --- /dev/null +++ b/rendering/mesh_texture_rd/icon.webp.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b1ukde136ayme" +path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.webp" +dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +process/resolution_scale=1.0 +detect_3d/compress_to=0 diff --git a/rendering/mesh_texture_rd/main.tscn b/rendering/mesh_texture_rd/main.tscn new file mode 100644 index 00000000000..0b8b9f06b04 --- /dev/null +++ b/rendering/mesh_texture_rd/main.tscn @@ -0,0 +1,68 @@ +[gd_scene load_steps=14 format=3 uid="uid://cnk1inmvelj4x"] + +[ext_resource type="Texture2D" uid="uid://crm65s53yy1n6" path="res://godot_icon.svg" id="1_7mycd"] +[ext_resource type="RDShaderFile" uid="uid://bsbaafha2qt2x" path="res://base_texture.glsl" id="2_7mycd"] +[ext_resource type="Script" uid="uid://cdfq6x7v36k1e" path="res://mesh_texture_rd.gd" id="3_5vw27"] +[ext_resource type="ArrayMesh" uid="uid://j7duroqwmiuw" path="res://2d_array_mesh.tres" id="4_1bvp3"] +[ext_resource type="Texture2D" uid="uid://bg8txxwsr4qn8" path="res://text_texture.tres" id="4_lquwl"] +[ext_resource type="PackedScene" uid="uid://mx52oimcwqtn" path="res://3d.tscn" id="6_7mycd"] + +[sub_resource type="PrismMesh" id="PrismMesh_kek77"] + +[sub_resource type="Texture2DRD" id="Texture2DRD_5vw27"] +script = ExtResource("3_5vw27") +clear_color = Color(0.412266, 0.447241, 0.735728, 1) +mesh = SubResource("PrismMesh_kek77") +base_texture = ExtResource("1_7mycd") +projection = Projection(-0.6, -1.3, 0, 0, 1.1, -1.67, 0, 0, -0.76, 0, -1.2, 0, 0, -0.26, 0, 1.36) + +[sub_resource type="TorusMesh" id="TorusMesh_lquwl"] + +[sub_resource type="Texture2DRD" id="Texture2DRD_7mycd"] +script = ExtResource("3_5vw27") +clear_color = Color(0.271125, 0.510188, 0.620698, 1) +mesh = SubResource("TorusMesh_lquwl") +base_texture = ExtResource("1_7mycd") +projection = Projection(-0.7, -0.92, 0.5, 0, 0.25, -1.5, 0.32, 0, 1.43, -0.14, 0.48, 0.14, 0.1, 0.02, 0.75, 1.85) +metadata/_custom_type_script = "uid://delyovxoqvijt" + +[sub_resource type="QuadMesh" id="QuadMesh_1bvp3"] + +[sub_resource type="Texture2DRD" id="Texture2DRD_lquwl"] +script = ExtResource("3_5vw27") +clear_color = Color(0.572798, 0.384286, 0.683792, 0.337255) +mesh = SubResource("QuadMesh_1bvp3") +base_texture = ExtResource("1_7mycd") +projection = Projection(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) +metadata/_custom_type_script = "uid://delyovxoqvijt" + +[sub_resource type="Texture2DRD" id="Texture2DRD_272bh"] +script = ExtResource("3_5vw27") +mesh = ExtResource("4_1bvp3") +base_texture = ExtResource("1_7mycd") +projection = Projection(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 100) +metadata/_custom_type_script = "uid://cdfq6x7v36k1e" + +[node name="Node2D" type="Node2D"] + +[node name="Prism" type="Sprite2D" parent="."] +position = Vector2(573, 321) +texture = SubResource("Texture2DRD_5vw27") + +[node name="Torus" type="Sprite2D" parent="."] +position = Vector2(898, 319) +texture = SubResource("Texture2DRD_7mycd") + +[node name="Quad" type="Sprite2D" parent="."] +position = Vector2(252, 321) +texture = SubResource("Texture2DRD_lquwl") + +[node name="Text" type="Sprite2D" parent="."] +position = Vector2(293, 89) +texture = ExtResource("4_lquwl") + +[node name="3d" parent="." instance=ExtResource("6_7mycd")] + +[node name="2DMesh" type="Sprite2D" parent="."] +position = Vector2(244, 797) +texture = SubResource("Texture2DRD_272bh") diff --git a/rendering/mesh_texture_rd/mesh_texture_rd.gd b/rendering/mesh_texture_rd/mesh_texture_rd.gd new file mode 100644 index 00000000000..58025e9d8d9 --- /dev/null +++ b/rendering/mesh_texture_rd/mesh_texture_rd.gd @@ -0,0 +1,317 @@ +@tool +extends Texture2DRD +class_name MeshTextureRD + +var rd := RenderingServer.get_rendering_device() + +var framebuffer_texture_rid := RID() +var framebuffer_rid := RID() +var vertex_array_rid := RID() +var index_array_rid := RID() +var shader_rid := RID() +var pipeline_rid := RID() +var sampler_rid := RID() +var uniform_set_rid := RID() +var index_buffer_rid := RID() +var vertex_buffer_pos_rid := RID() +var vertex_buffer_uv_rid := RID() + +var uniform_tex: RDUniform = RDUniform.new() +var vertex_attrs: Array[RDVertexAttribute] +var vertex_format: int + +var shader_dirty := false +var pipeline_dirty := false +var mesh_dirty := false +var uniform_set_dirty := false +var is_2d_mesh := false + +@export var size := Vector2i(256, 256): + get: return size + set(value): + size = value + _queue_update_pipeline() + + +@export var clear_color := Color.TRANSPARENT: + get: return clear_color + set(value): + clear_color = value + _queue_update() + + +@export var mesh: Mesh: + get: return mesh + set(value): + if mesh != null: + mesh.changed.disconnect(_queue_update_mesh) + mesh = value + _queue_update_mesh() + if mesh != null: + mesh.changed.connect(_queue_update_mesh) + + +@export var base_texture: Texture2D: + get: return base_texture + set(value): + if base_texture != null: + base_texture.changed.disconnect(_queue_update_uniform_set) + base_texture = value + _queue_update_uniform_set() + if base_texture != null: + base_texture.changed.connect(_queue_update_uniform_set) + + +@export var projection: Projection = Projection.IDENTITY: + get: return projection + set(value): + projection = value + _queue_update() + + +@export var glsl_file: RDShaderFile = preload("res://base_texture.glsl"): + get: return glsl_file + set(value): + if glsl_file != null: + glsl_file.changed.disconnect(_queue_update_shader) + glsl_file = value + _queue_update_shader() + if glsl_file != null: + glsl_file.changed.connect(_queue_update_shader) + +var _update_queued := false + +func _init() -> void: + sampler_rid = rd.sampler_create(RDSamplerState.new()) + + uniform_tex.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE + uniform_tex.binding = 0 + + var pos := RDVertexAttribute.new() + pos.format = RenderingDevice.DATA_FORMAT_R32G32B32_SFLOAT + pos.location = 0 + pos.stride = 4 * 3 + var uv := RDVertexAttribute.new() + uv.format = RenderingDevice.DATA_FORMAT_R32G32_SFLOAT + uv.location = 1 + uv.stride = 4 * 2 + vertex_attrs.clear() + vertex_attrs.append_array([pos, uv]) + vertex_format = rd.vertex_format_create(vertex_attrs) + if glsl_file and not glsl_file.changed.is_connected(_queue_update_shader): + glsl_file.changed.connect(_queue_update_shader) + _queue_update_shader() + + +func _notification(what: int) -> void: + if what == NOTIFICATION_PREDELETE: + if framebuffer_texture_rid.is_valid(): + rd.free_rid(framebuffer_texture_rid) + if shader_rid.is_valid(): + rd.free_rid(shader_rid) + if sampler_rid.is_valid(): + rd.free_rid(sampler_rid) + if index_buffer_rid.is_valid(): + rd.free_rid(index_buffer_rid) + if vertex_buffer_pos_rid.is_valid(): + rd.free_rid(vertex_buffer_pos_rid) + if vertex_buffer_uv_rid.is_valid(): + rd.free_rid(vertex_buffer_uv_rid) + + +func update(force: bool = false) -> void: + if force: + shader_dirty = true + pipeline_dirty = true + mesh_dirty = true + uniform_set_dirty = true + + if shader_dirty: + _reset_shader() + _reset_pipeline() + _reset_uniform() + shader_dirty = false + if pipeline_dirty: + _reset_pipeline() + pipeline_dirty = false + if uniform_set_dirty: + _reset_uniform() + uniform_set_dirty = false + if mesh_dirty: + _reset_vertex() + mesh_dirty = false + + _draw_list() + emit_changed() + _update_queued = false + + +func _queue_update() -> void: + if _update_queued: + return + _update_queued = true + update.call_deferred() + + +func _queue_update_shader() -> void: + shader_dirty = true + _queue_update() + + +func _queue_update_pipeline() -> void: + pipeline_dirty = true + _queue_update() + + +func _queue_update_uniform_set() -> void: + uniform_set_dirty = true + _queue_update() + + +func _queue_update_mesh() -> void: + mesh_dirty = true + _queue_update() + + +func _reset_vertex() -> void: + if mesh == null or mesh.get_surface_count() == 0: + return + + var surface_array := mesh.surface_get_arrays(0) + var vertex_array: Variant = surface_array[Mesh.ARRAY_VERTEX] + var indices: PackedInt32Array = surface_array[Mesh.ARRAY_INDEX] + var uv_array: PackedVector2Array = surface_array[Mesh.ARRAY_TEX_UV] + is_2d_mesh = false + if vertex_array is PackedVector2Array: + is_2d_mesh = true + var vertex_array_vec3 := PackedVector3Array() + vertex_array_vec3.resize(len(vertex_array)) + for i in range(len(vertex_array)): + var v: Vector2 = vertex_array[i] + # Convert 2D Mesh to 3D to match the vertex format. + vertex_array_vec3[i] = Vector3(v.x, v.y, 0) + + vertex_array = vertex_array_vec3 + + var points_bytes: PackedByteArray = vertex_array.to_byte_array() + + if indices.size() > 0: + var indices_bytes := indices.to_byte_array() + + if index_buffer_rid.is_valid(): + rd.free_rid(index_buffer_rid) + index_buffer_rid = rd.index_buffer_create(indices.size(), RenderingDevice.INDEX_BUFFER_FORMAT_UINT32, indices_bytes) + + index_array_rid = rd.index_array_create(index_buffer_rid, 0, indices.size()) + + var uv_bytes := uv_array.to_byte_array() + + if vertex_buffer_pos_rid.is_valid(): rd.free_rid(vertex_buffer_pos_rid) + if vertex_buffer_uv_rid.is_valid(): rd.free_rid(vertex_buffer_uv_rid) + vertex_buffer_pos_rid = rd.vertex_buffer_create(points_bytes.size(), points_bytes) + vertex_buffer_uv_rid = rd.vertex_buffer_create(uv_bytes.size(), uv_bytes) + + var vertex_buffers := [vertex_buffer_pos_rid, vertex_buffer_uv_rid] + + vertex_array_rid = rd.vertex_array_create(int(float(points_bytes.size()) / 4 / 3), vertex_format, vertex_buffers) + + +func _reset_shader() -> void: + var shader_spirv := glsl_file.get_spirv() + if shader_rid.is_valid(): + rd.free_rid(shader_rid) + pipeline_rid = RID() + uniform_set_rid = RID() + + shader_rid = rd.shader_create_from_spirv(shader_spirv) + + +func _reset_pipeline() -> void: + if glsl_file == null: + return + + var tex_format := RDTextureFormat.new() + var tex_view := RDTextureView.new() + tex_format.texture_type = RenderingDevice.TEXTURE_TYPE_2D + tex_format.width = size.x + tex_format.height = size.y + tex_format.format = RenderingDevice.DATA_FORMAT_R8G8B8A8_SRGB + tex_format.usage_bits = RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT + + tex_format.add_shareable_format(RenderingDevice.DATA_FORMAT_R8G8B8A8_UNORM) + tex_format.add_shareable_format(RenderingDevice.DATA_FORMAT_R8G8B8A8_SRGB) + + var new_rd_tex := rd.texture_create(tex_format, tex_view) + texture_rd_rid = new_rd_tex + + if framebuffer_texture_rid.is_valid(): + rd.free_rid(framebuffer_texture_rid) + + framebuffer_texture_rid = new_rd_tex + + var blend := RDPipelineColorBlendState.new() + blend.attachments.append(RDPipelineColorBlendStateAttachment.new()) + + framebuffer_rid = rd.framebuffer_create([framebuffer_texture_rid]) + + var rs := RDPipelineRasterizationState.new() + rs.front_face = RenderingDevice.POLYGON_FRONT_FACE_COUNTER_CLOCKWISE if is_2d_mesh else RenderingDevice.POLYGON_FRONT_FACE_CLOCKWISE + rs.cull_mode = RenderingDevice.POLYGON_CULL_BACK + + pipeline_rid = rd.render_pipeline_create( + shader_rid, + rd.framebuffer_get_format(framebuffer_rid), + vertex_format, + RenderingDevice.RENDER_PRIMITIVE_TRIANGLES, + rs, + RDPipelineMultisampleState.new(), + RDPipelineDepthStencilState.new(), + blend + ) + + +func _reset_uniform() -> void: + if not sampler_rid.is_valid() or base_texture == null or not base_texture.get_rid().is_valid() or not shader_rid.is_valid(): + return + + uniform_tex.clear_ids() + uniform_tex.add_id(sampler_rid) + # We are rendering to srgb format texture, the uniform should use srgb view. + # Note: Some texture formats(R8, R8G8) don't have srgb view, so they are missing a sRGB -> linear conversion. + uniform_tex.add_id(RenderingServer.texture_get_rd_texture(base_texture.get_rid(), true)) + + uniform_set_rid = UniformSetCacheRD.get_cache(shader_rid, 0, [uniform_tex]) + + +func _draw_list() -> void: + if not rd.render_pipeline_is_valid(pipeline_rid): + print("draw failed, invalid pipeline") + return + elif not rd.framebuffer_is_valid(framebuffer_rid): + print("draw failed, invalid framebuffer") + return + elif not rd.uniform_set_is_valid(uniform_set_rid): + print("draw failed, invalid uniform set") + return + elif not vertex_array_rid.is_valid(): + print("draw failed, invalid vertex") + return + + var xform_array: PackedFloat32Array = [ + projection[0][0], projection[0][1], projection[0][2], projection[0][3], + projection[1][0], projection[1][1], projection[1][2], projection[1][3], + projection[2][0], projection[2][1], projection[2][2], projection[2][3], + projection[3][0], projection[3][1], projection[3][2], projection[3][3] + ] + var xform_bytes := xform_array.to_byte_array() + + # We are rendering to srgb format texture, the clear color should use linear color. + var draw_list := rd.draw_list_begin(framebuffer_rid, RenderingDevice.DRAW_CLEAR_COLOR_ALL, [clear_color.srgb_to_linear()]) + rd.draw_list_bind_render_pipeline(draw_list, pipeline_rid) + rd.draw_list_bind_vertex_array(draw_list, vertex_array_rid) + rd.draw_list_bind_uniform_set(draw_list, uniform_set_rid, 0) + if index_array_rid.is_valid(): + rd.draw_list_bind_index_array(draw_list, index_array_rid) + rd.draw_list_set_push_constant(draw_list, xform_bytes, len(xform_bytes)) + rd.draw_list_draw(draw_list, index_array_rid.is_valid(), 1) + rd.draw_list_end() diff --git a/rendering/mesh_texture_rd/mesh_texture_rd.gd.uid b/rendering/mesh_texture_rd/mesh_texture_rd.gd.uid new file mode 100644 index 00000000000..c6bfb382e70 --- /dev/null +++ b/rendering/mesh_texture_rd/mesh_texture_rd.gd.uid @@ -0,0 +1 @@ +uid://cdfq6x7v36k1e diff --git a/rendering/mesh_texture_rd/project.godot b/rendering/mesh_texture_rd/project.godot new file mode 100644 index 00000000000..8c54e68cf46 --- /dev/null +++ b/rendering/mesh_texture_rd/project.godot @@ -0,0 +1,36 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Rasterize Mesh Texture" +config/description="This is a demo showing how to setup a basic render pipeline to draw mesh to texture using RenderingDevice. +" +config/tags=PackedStringArray("demo", "official", "rendering") +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.5") +config/icon="uid://b1ukde136ayme" + +[debug] + +gdscript/warnings/untyped_declaration=1 + +[display] + +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + +[dotnet] + +project/assembly_name="Rasterize Mesh Texture" + +[rendering] + +renderer/rendering_method="mobile" diff --git a/rendering/mesh_texture_rd/screenshots/.gdignore b/rendering/mesh_texture_rd/screenshots/.gdignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/rendering/mesh_texture_rd/screenshots/rasterize_mesh_texture.webp b/rendering/mesh_texture_rd/screenshots/rasterize_mesh_texture.webp new file mode 100644 index 00000000000..ef7748a0d39 Binary files /dev/null and b/rendering/mesh_texture_rd/screenshots/rasterize_mesh_texture.webp differ diff --git a/rendering/mesh_texture_rd/text_texture.tres b/rendering/mesh_texture_rd/text_texture.tres new file mode 100644 index 00000000000..473b41c689c --- /dev/null +++ b/rendering/mesh_texture_rd/text_texture.tres @@ -0,0 +1,22 @@ +[gd_resource type="Texture2DRD" script_class="MeshTextureRD" load_steps=6 format=3 uid="uid://bg8txxwsr4qn8"] + +[ext_resource type="RDShaderFile" uid="uid://bsbaafha2qt2x" path="res://base_texture.glsl" id="1_rjie5"] +[ext_resource type="Script" uid="uid://cdfq6x7v36k1e" path="res://mesh_texture_rd.gd" id="2_cjslc"] + +[sub_resource type="Gradient" id="Gradient_1bvp3"] +interpolation_color_space = 2 +colors = PackedColorArray(0.692862, 0.522376, 0.466238, 1, 0.634748, 0.521037, 0.665456, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_lquwl"] +gradient = SubResource("Gradient_1bvp3") + +[sub_resource type="TextMesh" id="TextMesh_7mycd"] +text = "Rasterize Mesh Texture" + +[resource] +script = ExtResource("2_cjslc") +size = Vector2i(552, 131) +mesh = SubResource("TextMesh_7mycd") +base_texture = SubResource("GradientTexture2D_lquwl") +projection = Projection(1.095, 0, 0, 0, 0, -5.53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1) +metadata/_custom_type_script = "uid://cdfq6x7v36k1e"