diff --git a/project.godot b/project.godot index 3edf9e5..1bb802c 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="Slime-Moldies" -run/main_scene="uid://bf4ohdg0sfl8l" +run/main_scene="uid://0q5qa7yiya83" config/features=PackedStringArray("4.4", "Forward Plus") config/icon="res://icon.svg" @@ -21,6 +21,13 @@ window/size/viewport_width=1920 window/size/viewport_height=1080 window/stretch/mode="viewport" +[file_customization] + +folder_colors={ +"res://shaders/": "pink", +"res://slime_simulation_cs/": "gray" +} + [rendering] environment/defaults/default_clear_color=Color(0.0605303, 0.0605304, 0.0605303, 1) diff --git a/shaders/agents_cs.glsl.import b/shaders/agents_cs.glsl.import deleted file mode 100644 index ddad48e..0000000 --- a/shaders/agents_cs.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://u3grg3r2bgi1" -path="res://.godot/imported/agents_cs.glsl-b2836a7ba58df020a54fe9498ba98f67.res" - -[deps] - -source_file="res://shaders/agents_cs.glsl" -dest_files=["res://.godot/imported/agents_cs.glsl-b2836a7ba58df020a54fe9498ba98f67.res"] - -[params] - diff --git a/shaders/decay_cs.glsl.import b/shaders/decay_cs.glsl.import deleted file mode 100644 index 5d051df..0000000 --- a/shaders/decay_cs.glsl.import +++ /dev/null @@ -1,14 +0,0 @@ -[remap] - -importer="glsl" -type="RDShaderFile" -uid="uid://vn5yxao0oxx0" -path="res://.godot/imported/decay_cs.glsl-2b5bb02442e13b8af8a2cd634f7d3362.res" - -[deps] - -source_file="res://shaders/decay_cs.glsl" -dest_files=["res://.godot/imported/decay_cs.glsl-2b5bb02442e13b8af8a2cd634f7d3362.res"] - -[params] - diff --git a/shaders/trail_shader.gdshader b/shaders/trail_shader.gdshader new file mode 100644 index 0000000..28cbe15 --- /dev/null +++ b/shaders/trail_shader.gdshader @@ -0,0 +1,8 @@ +shader_type canvas_item; + +void fragment() { + vec3 c1 = vec3(0.0, 0.4, 0.4); + vec3 c2 = vec3(0.4, 0.0, 0.4); + vec3 cout = mix(c1, c2, UV.x); + COLOR = vec4(cout, 1.0); +} diff --git a/shaders/trail_shader.gdshader.uid b/shaders/trail_shader.gdshader.uid new file mode 100644 index 0000000..76bad6b --- /dev/null +++ b/shaders/trail_shader.gdshader.uid @@ -0,0 +1 @@ +uid://cwt4a55lblykn diff --git a/shaders/view_simulation.gdshader b/shaders/view_simulation.gdshader new file mode 100644 index 0000000..9b698cc --- /dev/null +++ b/shaders/view_simulation.gdshader @@ -0,0 +1,8 @@ +shader_type canvas_item; + +uniform sampler2D view_texture; + +void fragment() { + vec3 v = texture(view_texture, UV).rgb; + COLOR = vec4(v, 1.0); +} \ No newline at end of file diff --git a/shaders/view_simulation.gdshader.uid b/shaders/view_simulation.gdshader.uid new file mode 100644 index 0000000..7147116 --- /dev/null +++ b/shaders/view_simulation.gdshader.uid @@ -0,0 +1 @@ +uid://dkp7mq8d1epi5 diff --git a/slime_simulation.gd b/slime_simulation.gd index ca8cd19..7a757c4 100644 --- a/slime_simulation.gd +++ b/slime_simulation.gd @@ -1,230 +1,12 @@ extends Node2D -@export var texture_size: Vector2i = Vector2i(512, 512) -@export var decay_factor: float = 0.98 -@export var dissipation_factor: float = 0.12 -@export var sensor_angle: float = 32.0: - get(): - return deg_to_rad(sensor_angle) -@export var sensor_distance: float = 3.86 -@export var rng_seed: int = 80085 - -@onready var mesh := $MeshInstance2D - -## Needs to be changed from the shader as well -const AGENTS: int = 1024 * 1024 - -var texture: Texture2DRD -var next_texture: int = 0 +@onready var view := $View +@onready var trail_shader: ShaderMaterial = $SubViewport/Pass1.material +var view_texture: Texture2DRD = null func _ready(): - RenderingServer.call_on_render_thread(_initialize_compute_code.bind(texture_size)) - var mat: ShaderMaterial = mesh.material - texture = mat.get_shader_parameter("trail_tex") - + pass func _process(_delta: float) -> void: - next_texture = (next_texture + 1) % 2 - - if texture: - texture.texture_rd_rid = texture_rds[next_texture] - - RenderingServer.call_on_render_thread( - _render_process.bind( - next_texture, - texture_size, - decay_factor, - dissipation_factor, - sensor_angle, - sensor_distance - ) - ) - - -func _exit_tree() -> void: - if texture: - texture.texture_rd_id = RID() - - RenderingServer.call_on_render_thread(_free_compute_resources) - - -# Everything after this point is designed to run on our rendering thread. - -var rd: RenderingDevice - -var decay_shader: RID -var decay_pipeline: RID - -var agent_shader: RID -var agent_pipeline: RID - -# We use 3 textures: -# - One to render into -# - One that contains the last frame rendered -# - One for the frame before that -var texture_rds: Array[RID] = [RID(), RID()] -var texture_sets: Array[RID] = [RID(), RID()] - -var agent_buffer: RID -var agent_sets: Array[RID] = [RID(), RID()] - - -func _load_shader(rd_: RenderingDevice, path: String) -> RID: - var shader_file := load(path) - var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() - return rd_.shader_create_from_spirv(shader_spirv) - - -func _create_trail_uniform(texture_rd: RID) -> RDUniform: - var uniform := RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE - uniform.binding = 0 - uniform.add_id(texture_rd) - return uniform - - -func _initialize_compute_code(with_texture_size: Vector2i) -> void: - # As this becomes part of our normal frame rendering, - # we use our main rendering device here. - rd = RenderingServer.get_rendering_device() - - # Create shaders - decay_shader = _load_shader(rd, "res://shaders/decay_cs.glsl") - decay_pipeline = rd.compute_pipeline_create(decay_shader) - - agent_shader = _load_shader(rd, "res://shaders/agents_cs.glsl") - agent_pipeline = rd.compute_pipeline_create(agent_shader) - - # Create agent buffer - var rng := RandomNumberGenerator.new() - rng.seed = rng_seed - var agent_positions := PackedVector2Array() - var agent_angles := PackedFloat32Array() - # This must match what is set in the shader, if fixed size - for n in AGENTS: - var new_position := Vector2( - rng.randf_range(0, with_texture_size.x), rng.randf_range(0, with_texture_size.y) - ) - agent_positions.push_back(new_position) - agent_angles.push_back(rng.randf_range(0, TAU)) - - var agent_data := PackedByteArray(agent_positions.to_byte_array()) - agent_data.append_array(agent_angles.to_byte_array()) - agent_buffer = rd.storage_buffer_create( - agent_data.size(), agent_data, 0, RenderingDevice.BUFFER_CREATION_AS_STORAGE_BIT - ) - - # Create trail texture - var tf: RDTextureFormat = RDTextureFormat.new() - tf.format = RenderingDevice.DATA_FORMAT_R32_SFLOAT - tf.texture_type = RenderingDevice.TEXTURE_TYPE_2D - tf.width = with_texture_size.x - tf.height = with_texture_size.y - tf.depth = 1 - tf.array_layers = 1 - tf.mipmaps = 1 - tf.usage_bits = ( - RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT - | RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT - | RenderingDevice.TEXTURE_USAGE_STORAGE_BIT - | RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT - | RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT - ) - - var agent_uniforms: Array[RDUniform] = [] - for i in 2: - texture_rds[i] = rd.texture_create(tf, RDTextureView.new(), []) - # Make sure our textures are cleared. - rd.texture_clear(texture_rds[i], Color.BLACK, 0, 1, 0, 1) - - var trail_uniform := _create_trail_uniform(texture_rds[i]) - texture_sets[i] = rd.uniform_set_create([trail_uniform], decay_shader, 0) - - var txtr_uniform_1 := RDUniform.new() - txtr_uniform_1.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE - txtr_uniform_1.binding = 0 - txtr_uniform_1.add_id(texture_rds[0]) - agent_uniforms.append(txtr_uniform_1) - - var txtr_uniform_2 := RDUniform.new() - txtr_uniform_2.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE - txtr_uniform_2.binding = 1 - txtr_uniform_2.add_id(texture_rds[1]) - agent_uniforms.append(txtr_uniform_2) - - var uniform := RDUniform.new() - uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER - uniform.binding = 2 - uniform.add_id(agent_buffer) - agent_sets[0] = rd.uniform_set_create( - [txtr_uniform_1, txtr_uniform_2, uniform], agent_shader, 0 - ) - agent_sets[1] = rd.uniform_set_create( - [txtr_uniform_2, txtr_uniform_1, uniform], agent_shader, 0 - ) - - -func _render_process( - with_next_texture: int, - tex_size: Vector2i, - decay_fctr: float, - dissipation_fctr: float, - snsr_angle: float, - snsr_distance: float -) -> void: - var next_set := texture_sets[with_next_texture] - var current_set := texture_sets[(with_next_texture - 1) % 2] - - # Run agents - var push_constant := PackedFloat32Array() - push_constant.push_back(tex_size.x) - push_constant.push_back(tex_size.y) - push_constant.push_back(snsr_angle) - push_constant.push_back(snsr_distance) - - var agent_compute_list := rd.compute_list_begin() - rd.compute_list_bind_compute_pipeline(agent_compute_list, agent_pipeline) - rd.compute_list_bind_uniform_set(agent_compute_list, agent_sets[with_next_texture], 0) - rd.compute_list_set_push_constant( - agent_compute_list, push_constant.to_byte_array(), push_constant.size() * 4 - ) - @warning_ignore("integer_division") - rd.compute_list_dispatch(agent_compute_list, 64, 1, 1) - rd.compute_list_end() - - # Decay and dissipate - push_constant.clear() - push_constant.push_back(tex_size.x) - push_constant.push_back(tex_size.y) - push_constant.push_back(decay_fctr) - push_constant.push_back(dissipation_fctr) - - @warning_ignore("integer_division") - var x_groups := (tex_size.x - 1) / 8 + 1 - @warning_ignore("integer_division") - var y_groups := (tex_size.y - 1) / 8 + 1 - - # Run the compute shader - var compute_list := rd.compute_list_begin() - rd.compute_list_bind_compute_pipeline(compute_list, decay_pipeline) - rd.compute_list_bind_uniform_set(compute_list, current_set, 0) - rd.compute_list_bind_uniform_set(compute_list, next_set, 1) - rd.compute_list_set_push_constant( - compute_list, push_constant.to_byte_array(), push_constant.size() * 4 - ) - rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) - rd.compute_list_end() - - -func _free_compute_resources() -> void: - # Note that our sets and pipeline are cleaned up automatically - # as they are dependencies :P - for i in 2: - if texture_rds[i]: - rd.free_rid(texture_rds[i]) - - if decay_shader: - rd.free_rid(decay_shader) - if agent_shader: - rd.free_rid(agent_shader) + pass diff --git a/slime_simulation.gd.uid b/slime_simulation.gd.uid index 1547549..519cea8 100644 --- a/slime_simulation.gd.uid +++ b/slime_simulation.gd.uid @@ -1 +1 @@ -uid://d1bbllvcal2uw +uid://c6et88s5hp5c7 diff --git a/slime_simulation.tscn b/slime_simulation.tscn index e47b452..62f21bd 100644 --- a/slime_simulation.tscn +++ b/slime_simulation.tscn @@ -1,27 +1,36 @@ -[gd_scene load_steps=6 format=3 uid="uid://bf4ohdg0sfl8l"] +[gd_scene load_steps=7 format=3 uid="uid://0q5qa7yiya83"] -[ext_resource type="Script" uid="uid://d1bbllvcal2uw" path="res://slime_simulation.gd" id="1_pxe3a"] -[ext_resource type="Shader" uid="uid://bh4h5oqyhr5bx" path="res://show_simulation.gdshader" id="2_pxe3a"] +[ext_resource type="Script" uid="uid://c6et88s5hp5c7" path="res://slime_simulation.gd" id="1_s6nlv"] +[ext_resource type="Shader" uid="uid://cwt4a55lblykn" path="res://shaders/trail_shader.gdshader" id="3_vkm4v"] -[sub_resource type="Texture2DRD" id="Texture2DRD_pxe3a"] +[sub_resource type="QuadMesh" id="QuadMesh_h0wwo"] +size = Vector2(1920, 1080) -[sub_resource type="ShaderMaterial" id="ShaderMaterial_pxe3a"] -shader = ExtResource("2_pxe3a") -shader_parameter/trail_tex = SubResource("Texture2DRD_pxe3a") +[sub_resource type="ViewportTexture" id="ViewportTexture_s6nlv"] +viewport_path = NodePath("SubViewport") -[sub_resource type="QuadMesh" id="QuadMesh_pxe3a"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_evymn"] +shader = ExtResource("3_vkm4v") + +[sub_resource type="QuadMesh" id="QuadMesh_s6nlv"] size = Vector2(1920, 1080) [node name="SlimeSimulation" type="Node2D"] -script = ExtResource("1_pxe3a") -texture_size = Vector2i(1920, 1080) -decay_factor = 0.8 -sensor_angle = 7.0 -sensor_distance = 10.0 -rng_seed = 8008 +script = ExtResource("1_s6nlv") -[node name="MeshInstance2D" type="MeshInstance2D" parent="."] -self_modulate = Color(0.581022, 0.701395, 0.890748, 1) -material = SubResource("ShaderMaterial_pxe3a") +[node name="View" type="MeshInstance2D" parent="."] position = Vector2(960, 540) -mesh = SubResource("QuadMesh_pxe3a") +mesh = SubResource("QuadMesh_h0wwo") +texture = SubResource("ViewportTexture_s6nlv") + +[node name="SubViewport" type="SubViewport" parent="."] +transparent_bg = true +handle_input_locally = false +snap_2d_vertices_to_pixel = true +size = Vector2i(1920, 1080) +render_target_update_mode = 4 + +[node name="Pass1" type="MeshInstance2D" parent="SubViewport"] +material = SubResource("ShaderMaterial_evymn") +position = Vector2(960, 540) +mesh = SubResource("QuadMesh_s6nlv") diff --git a/shaders/agents_cs.glsl b/slime_simulation_cs/shaders/agents_cs.glsl similarity index 100% rename from shaders/agents_cs.glsl rename to slime_simulation_cs/shaders/agents_cs.glsl diff --git a/slime_simulation_cs/shaders/agents_cs.glsl.import b/slime_simulation_cs/shaders/agents_cs.glsl.import new file mode 100644 index 0000000..3b6b7cf --- /dev/null +++ b/slime_simulation_cs/shaders/agents_cs.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://u3grg3r2bgi1" +path="res://.godot/imported/agents_cs.glsl-f5fde0e4c35a05360ed8814f4e4a012a.res" + +[deps] + +source_file="res://slime_simulation_cs/shaders/agents_cs.glsl" +dest_files=["res://.godot/imported/agents_cs.glsl-f5fde0e4c35a05360ed8814f4e4a012a.res"] + +[params] + diff --git a/shaders/decay_cs.glsl b/slime_simulation_cs/shaders/decay_cs.glsl similarity index 100% rename from shaders/decay_cs.glsl rename to slime_simulation_cs/shaders/decay_cs.glsl diff --git a/slime_simulation_cs/shaders/decay_cs.glsl.import b/slime_simulation_cs/shaders/decay_cs.glsl.import new file mode 100644 index 0000000..3094355 --- /dev/null +++ b/slime_simulation_cs/shaders/decay_cs.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://vn5yxao0oxx0" +path="res://.godot/imported/decay_cs.glsl-ddb2bd80ce1fa22519e2cc84d49ab13a.res" + +[deps] + +source_file="res://slime_simulation_cs/shaders/decay_cs.glsl" +dest_files=["res://.godot/imported/decay_cs.glsl-ddb2bd80ce1fa22519e2cc84d49ab13a.res"] + +[params] + diff --git a/show_simulation.gdshader b/slime_simulation_cs/show_simulation_cs.gdshader similarity index 100% rename from show_simulation.gdshader rename to slime_simulation_cs/show_simulation_cs.gdshader diff --git a/show_simulation.gdshader.uid b/slime_simulation_cs/show_simulation_cs.gdshader.uid similarity index 100% rename from show_simulation.gdshader.uid rename to slime_simulation_cs/show_simulation_cs.gdshader.uid diff --git a/slime_simulation_cs/slime_simulation_cs.gd b/slime_simulation_cs/slime_simulation_cs.gd new file mode 100644 index 0000000..7c79fc2 --- /dev/null +++ b/slime_simulation_cs/slime_simulation_cs.gd @@ -0,0 +1,230 @@ +extends Node2D + +@export var texture_size: Vector2i = Vector2i(512, 512) +@export var decay_factor: float = 0.98 +@export var dissipation_factor: float = 0.12 +@export var sensor_angle: float = 32.0: + get(): + return deg_to_rad(sensor_angle) +@export var sensor_distance: float = 3.86 +@export var rng_seed: int = 80085 + +@onready var mesh := $MeshInstance2D + +## Needs to be changed from the shader as well +const AGENTS: int = 1024 * 1024 + +var texture: Texture2DRD +var next_texture: int = 0 + + +func _ready(): + RenderingServer.call_on_render_thread(_initialize_compute_code.bind(texture_size)) + var mat: ShaderMaterial = mesh.material + texture = mat.get_shader_parameter("trail_tex") + + +func _process(_delta: float) -> void: + next_texture = (next_texture + 1) % 2 + + if texture: + texture.texture_rd_rid = texture_rds[next_texture] + + RenderingServer.call_on_render_thread( + _render_process.bind( + next_texture, + texture_size, + decay_factor, + dissipation_factor, + sensor_angle, + sensor_distance + ) + ) + + +func _exit_tree() -> void: + if texture: + texture.texture_rd_id = RID() + + RenderingServer.call_on_render_thread(_free_compute_resources) + + +# Everything after this point is designed to run on our rendering thread. + +var rd: RenderingDevice + +var decay_shader: RID +var decay_pipeline: RID + +var agent_shader: RID +var agent_pipeline: RID + +# We use 3 textures: +# - One to render into +# - One that contains the last frame rendered +# - One for the frame before that +var texture_rds: Array[RID] = [RID(), RID()] +var texture_sets: Array[RID] = [RID(), RID()] + +var agent_buffer: RID +var agent_sets: Array[RID] = [RID(), RID()] + + +func _load_shader(rd_: RenderingDevice, path: String) -> RID: + var shader_file := load(path) + var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() + return rd_.shader_create_from_spirv(shader_spirv) + + +func _create_trail_uniform(texture_rd: RID) -> RDUniform: + var uniform := RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + uniform.binding = 0 + uniform.add_id(texture_rd) + return uniform + + +func _initialize_compute_code(with_texture_size: Vector2i) -> void: + # As this becomes part of our normal frame rendering, + # we use our main rendering device here. + rd = RenderingServer.get_rendering_device() + + # Create shaders + decay_shader = _load_shader(rd, "res://slime_simulation_cs/shaders/decay_cs.glsl") + decay_pipeline = rd.compute_pipeline_create(decay_shader) + + agent_shader = _load_shader(rd, "res://slime_simulation_cs/shaders/agents_cs.glsl") + agent_pipeline = rd.compute_pipeline_create(agent_shader) + + # Create agent buffer + var rng := RandomNumberGenerator.new() + rng.seed = rng_seed + var agent_positions := PackedVector2Array() + var agent_angles := PackedFloat32Array() + # This must match what is set in the shader, if fixed size + for n in AGENTS: + var new_position := Vector2( + rng.randf_range(0, with_texture_size.x), rng.randf_range(0, with_texture_size.y) + ) + agent_positions.push_back(new_position) + agent_angles.push_back(rng.randf_range(0, TAU)) + + var agent_data := PackedByteArray(agent_positions.to_byte_array()) + agent_data.append_array(agent_angles.to_byte_array()) + agent_buffer = rd.storage_buffer_create( + agent_data.size(), agent_data, 0, RenderingDevice.BUFFER_CREATION_AS_STORAGE_BIT + ) + + # Create trail texture + var tf: RDTextureFormat = RDTextureFormat.new() + tf.format = RenderingDevice.DATA_FORMAT_R32_SFLOAT + tf.texture_type = RenderingDevice.TEXTURE_TYPE_2D + tf.width = with_texture_size.x + tf.height = with_texture_size.y + tf.depth = 1 + tf.array_layers = 1 + tf.mipmaps = 1 + tf.usage_bits = ( + RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT + | RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT + | RenderingDevice.TEXTURE_USAGE_STORAGE_BIT + | RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT + | RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT + ) + + var agent_uniforms: Array[RDUniform] = [] + for i in 2: + texture_rds[i] = rd.texture_create(tf, RDTextureView.new(), []) + # Make sure our textures are cleared. + rd.texture_clear(texture_rds[i], Color.BLACK, 0, 1, 0, 1) + + var trail_uniform := _create_trail_uniform(texture_rds[i]) + texture_sets[i] = rd.uniform_set_create([trail_uniform], decay_shader, 0) + + var txtr_uniform_1 := RDUniform.new() + txtr_uniform_1.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + txtr_uniform_1.binding = 0 + txtr_uniform_1.add_id(texture_rds[0]) + agent_uniforms.append(txtr_uniform_1) + + var txtr_uniform_2 := RDUniform.new() + txtr_uniform_2.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE + txtr_uniform_2.binding = 1 + txtr_uniform_2.add_id(texture_rds[1]) + agent_uniforms.append(txtr_uniform_2) + + var uniform := RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform.binding = 2 + uniform.add_id(agent_buffer) + agent_sets[0] = rd.uniform_set_create( + [txtr_uniform_1, txtr_uniform_2, uniform], agent_shader, 0 + ) + agent_sets[1] = rd.uniform_set_create( + [txtr_uniform_2, txtr_uniform_1, uniform], agent_shader, 0 + ) + + +func _render_process( + with_next_texture: int, + tex_size: Vector2i, + decay_fctr: float, + dissipation_fctr: float, + snsr_angle: float, + snsr_distance: float +) -> void: + var next_set := texture_sets[with_next_texture] + var current_set := texture_sets[(with_next_texture - 1) % 2] + + # Run agents + var push_constant := PackedFloat32Array() + push_constant.push_back(tex_size.x) + push_constant.push_back(tex_size.y) + push_constant.push_back(snsr_angle) + push_constant.push_back(snsr_distance) + + var agent_compute_list := rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(agent_compute_list, agent_pipeline) + rd.compute_list_bind_uniform_set(agent_compute_list, agent_sets[with_next_texture], 0) + rd.compute_list_set_push_constant( + agent_compute_list, push_constant.to_byte_array(), push_constant.size() * 4 + ) + @warning_ignore("integer_division") + rd.compute_list_dispatch(agent_compute_list, 64, 1, 1) + rd.compute_list_end() + + # Decay and dissipate + push_constant.clear() + push_constant.push_back(tex_size.x) + push_constant.push_back(tex_size.y) + push_constant.push_back(decay_fctr) + push_constant.push_back(dissipation_fctr) + + @warning_ignore("integer_division") + var x_groups := (tex_size.x - 1) / 8 + 1 + @warning_ignore("integer_division") + var y_groups := (tex_size.y - 1) / 8 + 1 + + # Run the compute shader + var compute_list := rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, decay_pipeline) + rd.compute_list_bind_uniform_set(compute_list, current_set, 0) + rd.compute_list_bind_uniform_set(compute_list, next_set, 1) + rd.compute_list_set_push_constant( + compute_list, push_constant.to_byte_array(), push_constant.size() * 4 + ) + rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1) + rd.compute_list_end() + + +func _free_compute_resources() -> void: + # Note that our sets and pipeline are cleaned up automatically + # as they are dependencies :P + for i in 2: + if texture_rds[i]: + rd.free_rid(texture_rds[i]) + + if decay_shader: + rd.free_rid(decay_shader) + if agent_shader: + rd.free_rid(agent_shader) diff --git a/slime_simulation_cs/slime_simulation_cs.gd.uid b/slime_simulation_cs/slime_simulation_cs.gd.uid new file mode 100644 index 0000000..1547549 --- /dev/null +++ b/slime_simulation_cs/slime_simulation_cs.gd.uid @@ -0,0 +1 @@ +uid://d1bbllvcal2uw diff --git a/slime_simulation_cs/slime_simulation_cs.tscn b/slime_simulation_cs/slime_simulation_cs.tscn new file mode 100644 index 0000000..fe69652 --- /dev/null +++ b/slime_simulation_cs/slime_simulation_cs.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=6 format=3 uid="uid://bf4ohdg0sfl8l"] + +[ext_resource type="Script" uid="uid://d1bbllvcal2uw" path="res://slime_simulation_cs/slime_simulation_cs.gd" id="1_uoug3"] +[ext_resource type="Shader" uid="uid://bh4h5oqyhr5bx" path="res://slime_simulation_cs/show_simulation_cs.gdshader" id="2_w43x7"] + +[sub_resource type="Texture2DRD" id="Texture2DRD_pxe3a"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_pxe3a"] +shader = ExtResource("2_w43x7") +shader_parameter/trail_tex = SubResource("Texture2DRD_pxe3a") + +[sub_resource type="QuadMesh" id="QuadMesh_pxe3a"] +size = Vector2(1920, 1080) + +[node name="CSSlimeSimulation" type="Node2D"] +script = ExtResource("1_uoug3") +texture_size = Vector2i(1920, 1080) +decay_factor = 0.8 +sensor_angle = 7.0 +sensor_distance = 10.0 +rng_seed = 8008 + +[node name="MeshInstance2D" type="MeshInstance2D" parent="."] +self_modulate = Color(0.581022, 0.701395, 0.890748, 1) +material = SubResource("ShaderMaterial_pxe3a") +position = Vector2(960, 540) +mesh = SubResource("QuadMesh_pxe3a")