From dbd4f668aa6c931c19923ef1dba5d7e904c59aa0 Mon Sep 17 00:00:00 2001 From: Henne Date: Sun, 2 Mar 2025 11:08:22 +0100 Subject: [PATCH] first try with compute shading --- .../flow_field_compute.glsl | 34 +++++++ .../flow_field_compute.glsl.import | 14 +++ .../flow_field_navigation.gd | 90 ++++++++++++++++++- 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 swarm_engine/flow_field_navigation/flow_field_compute.glsl create mode 100644 swarm_engine/flow_field_navigation/flow_field_compute.glsl.import diff --git a/swarm_engine/flow_field_navigation/flow_field_compute.glsl b/swarm_engine/flow_field_navigation/flow_field_compute.glsl new file mode 100644 index 0000000..22d38af --- /dev/null +++ b/swarm_engine/flow_field_navigation/flow_field_compute.glsl @@ -0,0 +1,34 @@ +#[compute] + +#version 450 + +// Speicher für FlowField-Daten +layout(std430, set = 0, binding = 0) buffer FlowFieldBuffer { + vec2 flow_field[]; +}; + +// Zielposition und Grid-Daten +layout(push_constant) uniform Params { + vec2 target_pos; + float cell_size; + int grid_size_x; + int grid_size_z; +}; + +void main(){ + uint x = gl_GlobalInvocationID.x; + uint z = gl_GlobalInvocationID.y; + + if (x >= grid_size_x || z >= grid_size_z) return; + + int index = int(z * grid_size_x + x); + + // Zellzentrum berechnen + vec2 cell_center = vec2(x, z) * cell_size + vec2(cell_size * 0.5); + + // Richtung zum Ziel berechnen + vec2 direction = normalize(target_pos - cell_center); + + // Ergebnis in FlowField speichern + flow_field[index] = direction; +} diff --git a/swarm_engine/flow_field_navigation/flow_field_compute.glsl.import b/swarm_engine/flow_field_navigation/flow_field_compute.glsl.import new file mode 100644 index 0000000..62792eb --- /dev/null +++ b/swarm_engine/flow_field_navigation/flow_field_compute.glsl.import @@ -0,0 +1,14 @@ +[remap] + +importer="glsl" +type="RDShaderFile" +uid="uid://bf4mkjohkqpox" +path="res://.godot/imported/flow_field_compute.glsl-51e5023d4249c63dbf26c3aa62523e13.res" + +[deps] + +source_file="res://swarm_engine/flow_field_navigation/flow_field_compute.glsl" +dest_files=["res://.godot/imported/flow_field_compute.glsl-51e5023d4249c63dbf26c3aa62523e13.res"] + +[params] + diff --git a/swarm_engine/flow_field_navigation/flow_field_navigation.gd b/swarm_engine/flow_field_navigation/flow_field_navigation.gd index 872c0ea..67dfe93 100644 --- a/swarm_engine/flow_field_navigation/flow_field_navigation.gd +++ b/swarm_engine/flow_field_navigation/flow_field_navigation.gd @@ -39,8 +39,54 @@ var flow_direction_list: Array[Vector2] = [] var half_size_x: float var half_size_z: float +var rd: RenderingDevice +var shader: RID +var pipeline: RID +var flow_field_buffer: RID +var flow_field_data: PackedVector2Array func _ready() -> void: + #var rendering_device := RenderingServer.create_local_rendering_device() + #var shader_file := load("res://swarm_engine/flow_field_navigation/flow_field_compute.glsl") + #var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() + #var shader_RID := rendering_device.shader_create_from_spirv(shader_spirv) + # + #var center_array: PackedVector3Array + #for x in range(grid_size_x): + #for z in range(grid_size_z): + #center_array.append(_get_cell_center_with_coordinates(x,z)) +# + #var center_byte_array = center_array.to_byte_array() + #var storage_buffer_RID = rendering_device.storage_buffer_create(center_byte_array.size(), center_byte_array) + # + #var uniform := RDUniform.new() + #uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + #uniform.binding = 0 + #uniform.add_id(storage_buffer_RID) + #var uniform_set_RID := rendering_device.uniform_set_create([uniform], shader_RID, 0) + # + #var pipeline_RID := rendering_device.compute_pipeline_create(shader_RID) + #var compute_list_id := rendering_device.compute_list_begin() + # + #rendering_device.compute_list_bind_compute_pipeline(compute_list_id, pipeline_RID) + #rendering_device.compute_list_bind_uniform_set(compute_list_id, uniform_set_RID, 0) + #rendering_device.compute_list_dispatch(compute_list_id, 1, 1, 1) + #rendering_device.compute_list_end() + #rendering_device.submit() + + #rd = RenderingServer.get_rendering_device() +# + ## Compute Shader laden + #var shader_file = load("res://swarm_engine/flow_field_navigation/flow_field_compute.glsl") + #shader = rd.shader_create_from_spirv(shader_file.get_spirv()) + #pipeline = rd.compute_pipeline_create(shader) +# + ## Speicher für FlowField erstellen + #var buffer_size = grid_size_x * grid_size_z * 8 # Vector2 -> 2 floats = 8 Bytes pro Eintrag + #flow_field_buffer = rd.storage_buffer_create(buffer_size) + #flow_field_data.resize(grid_size_x * grid_size_z) + # + for x in range(grid_size_x): for z in range(grid_size_z): flow_direction_list.append(Vector2(0.0, 0.0)) @@ -49,10 +95,52 @@ func _ready() -> void: func _process(delta: float) -> void: - + #_update_gpu_flow_field() _update_flow_field() _draw_debug() +func _update_gpu_flow_field(): + if not target: + return + + # Push-Constants für Shader setzen + var push_constants = PackedByteArray() + push_constants.append_array(PackedByteArray([ + target.position.x, + target.position.z, + cell_size, + float(grid_size_x), + float(grid_size_z) + ])) + + # GPU Command erstellen + var compute_list = rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, pipeline) + rd.compute_list_bind_storage_buffer(compute_list, flow_field_buffer, 0, 0) + rd.compute_list_set_push_constant(compute_list, push_constants, 0) + rd.compute_list_dispatch(compute_list, grid_size_x, grid_size_z, 1) + rd.compute_list_end() + + # GPU Berechnung starten + rd.submit() + rd.sync() + + # Daten von der GPU zurückholen + var buffer_data = rd.buffer_get_data(flow_field_buffer) + var output = buffer_data.to_float32_array() + + # 2D-Array für FlowField initialisieren + flow_direction_list = [] + for x in range(grid_size_x): + flow_direction_list.append([]) # Erstellt leere Arrays für jede X-Spalte + + # Konvertiere die 1D-GPU-Daten in ein 2D-Array + for z in range(grid_size_z): + for x in range(grid_size_x): + var index = (z * grid_size_x + x) * 2 # 2 Floats pro Vector2 + var flow_vector = Vector2(output[index], output[index + 1]) + flow_direction_list[index] = flow_vector + func _update_flow_field(): if target != null: for x in range(grid_size_x):