diff --git a/compute_test.gd b/compute_test.gd index 63f6fd6..8f905bc 100644 --- a/compute_test.gd +++ b/compute_test.gd @@ -10,7 +10,6 @@ func create_device(): shader_spirv = shader_file.get_spirv() shader = rd.shader_create_from_spirv(shader_spirv) - func compute(world_size: int, threshold: float): # Prepare our data. We use floats in the shader, so we need 32 bit. @@ -77,11 +76,37 @@ func compute(world_size: int, threshold: float): var output_bytes := rd.buffer_get_data(surface_buffer) var output := output_bytes.to_float32_array() + var output_sample_bytes := rd.buffer_get_data(buffer) + var output_sample := output_sample_bytes.to_float32_array() + rd.free_rid(buffer) rd.free_rid(params_buffer) rd.free_rid(surface_buffer) - return build_surface_dict(world_size, output) + + var surface_points_dict := build_surface_dict(world_size, output) + var sample_points_dict := build_sample_dict(world_size, output_sample) + + return { + "surface_points_dict": surface_points_dict, + "sample_points_dict": sample_points_dict + } +func build_sample_dict(world_size: int, flat_buffer: PackedFloat32Array) -> Dictionary: + var dict := {} + var total = world_size * world_size * world_size + + for idx in total: + var voxel_x = idx % world_size + var voxel_y = (idx / world_size) % world_size + var voxel_z = idx / (world_size * world_size) + + var voxel_id = Vector3i(voxel_x, voxel_y, voxel_z) + var distance = flat_buffer[idx] + + dict[voxel_id] = distance + + return dict + func build_surface_dict(world_size: int, flat_buffer: PackedFloat32Array) -> Dictionary: var dict := {} var total = world_size * world_size * world_size diff --git a/generate_mesh.tres b/generate_mesh.tres new file mode 100644 index 0000000..097cfc3 --- /dev/null +++ b/generate_mesh.tres @@ -0,0 +1,28 @@ +[gd_resource type="VisualShader" load_steps=2 format=3 uid="uid://bose286qacwdl"] + +[sub_resource type="VisualShaderNodeColorConstant" id="VisualShaderNodeColorConstant_sxi40"] +constant = Color(0.30202293, 0.6060653, 0.9109474, 1) + +[resource] +code = "shader_type spatial; +render_mode blend_mix, depth_draw_opaque, depth_test_default, cull_back, diffuse_lambert, specular_schlick_ggx; + + + + +void fragment() { +// ColorConstant:2 + vec4 n_out2p0 = vec4(0.302023, 0.606065, 0.910947, 1.000000); + + +// Output:0 + ALBEDO = vec3(n_out2p0.xyz); + + +} +" +nodes/vertex/0/position = Vector2(360, 220) +nodes/fragment/0/position = Vector2(660, 140) +nodes/fragment/2/node = SubResource("VisualShaderNodeColorConstant_sxi40") +nodes/fragment/2/position = Vector2(260, 220) +nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0) diff --git a/sdf_shader.glsl b/sdf_shader.glsl index c3ad320..a09f3eb 100644 --- a/sdf_shader.glsl +++ b/sdf_shader.glsl @@ -15,7 +15,7 @@ layout(set = 0, binding = 1) uniform Params { float threshold; } params; -layout(set = 0, binding = 2) buffer SurfaceBuffer { +layout(set = 0, binding = 2, std430) buffer SurfaceBuffer { float surface_points[]; } surface; @@ -89,4 +89,6 @@ void main() { store_surface_point(idx, vec3(0.0)); // no surface } + + } diff --git a/smooth_world.gd b/smooth_world.gd index 53233bc..2d31136 100644 --- a/smooth_world.gd +++ b/smooth_world.gd @@ -10,6 +10,8 @@ var SurfacePoint = preload("res://surface_point.gd") var ComputeSdf = preload("res://compute_test.gd") var gpu_sdf +var generate_mesh_shader = preload("res://generate_mesh.tres") + @export var world_size = 16 @export var show_sample_points = false @@ -19,29 +21,34 @@ var gpu_sdf @export var do_the_thing: bool = false @export var clear_the_thing: bool = false -var sdf_buffer = [] -var surface_points_buffer = [] - var color = Color.CORAL var surface_point_color = Color.CRIMSON var mesh var surface_tool: SurfaceTool = SurfaceTool.new() +var meshinstance = MeshInstance3D.new() +var material = ShaderMaterial.new() + func _ready() -> void: + material.shader = generate_mesh_shader + meshinstance.material_override = material + add_child(meshinstance) gpu_sdf = ComputeSdf.new() gpu_sdf.create_device() func _process(_delta: float) -> void: clear() - surface_points = gpu_sdf.compute(world_size, RADIUS) + var dictionaries = gpu_sdf.compute(world_size, RADIUS) + surface_points = dictionaries.surface_points_dict + sample_points = dictionaries.sample_points_dict if !surface_points.is_empty(): #create_surface_points_gpu() #create_surface_points() if show_surface_points: draw_surface_points() if show_surface: - create_surface_mesh(world_size) + create_surface_mesh() if show_sample_points: draw_sample_points() @@ -49,9 +56,7 @@ func _process(_delta: float) -> void: func clear(): surface_points = {} mesh = ArrayMesh.new() - for child in get_children(): - if child is MeshInstance3D: - child.queue_free() + func get_index_from_coords(coords: Vector3i): return coords.x + coords.y * world_size + coords.z * world_size * world_size @@ -68,64 +73,27 @@ func draw_surface_points(): for surface_point in surface_points: if surface_points[surface_point] != Vector3(0, 0, 0): DebugDraw3D.draw_square(surface_points[surface_point] , 0.3, surface_point_color) - #DebugDraw3D.draw_text(surface_points[Vector3i(x, y, z)], str(surface_points[Vector3i(x, y, z)])) - -func create_surface_points(): - for x in range(world_size): - for y in range(world_size): - for z in range(world_size): - create_surface_point(Vector3i(x, y, z)) - -func create_surface_point(voxel: Vector3i): - var previous_sign = 0 - var previous_sample_point - var previous_sample_point_distance_from_sdf - var intersection_points_sum = Vector3.ZERO - var intersection_points_number = 0 - for sample_point_to_check_index in range(SURFACE_AXIS.size()): - var sample_point_to_check = voxel + SURFACE_AXIS[sample_point_to_check_index] - var normal_x = sample_point_to_check.x + world_size - 1 - var normal_y = sample_point_to_check.y + world_size - 1 - var normal_z = sample_point_to_check.z + world_size - 1 - var buffer_index = sample_point_to_check.x + sample_point_to_check.y * world_size + sample_point_to_check.z * world_size * world_size - if buffer_index < sdf_buffer.size(): - var sample_point_distance_from_sdf = sdf_buffer[buffer_index]#get_sample_value(sample_point_to_check) - sample_points[sample_point_to_check] = sample_point_distance_from_sdf - if previous_sign != 0 && sign(sample_point_distance_from_sdf) != previous_sign: - var intersection_point = (1-previous_sample_point_distance_from_sdf/(previous_sample_point_distance_from_sdf - sample_point_distance_from_sdf))*previous_sample_point+(previous_sample_point_distance_from_sdf/(previous_sample_point_distance_from_sdf-sample_point_distance_from_sdf)*sample_point_to_check) - intersection_points_sum += intersection_point - intersection_points_number += 1 - previous_sign = sign(sample_point_distance_from_sdf) - previous_sample_point = sample_point_to_check - previous_sample_point_distance_from_sdf = sample_point_distance_from_sdf - if intersection_points_sum != Vector3.ZERO && intersection_points_number != 0: - var intersection_points_average = intersection_points_sum/Vector3(intersection_points_number, intersection_points_number, intersection_points_number) - var surface_point = SurfacePoint.new() - surface_point.position = intersection_points_average - surface_points[voxel] = surface_point + DebugDraw3D.draw_text(surface_points[surface_point], str(surface_points[surface_point])) func calculate_surface_point_position(voxel: Vector3i): var final_point = Vector3(voxel) return final_point -func create_surface_mesh(size: int = 6): +func create_surface_mesh(): surface_tool = SurfaceTool.new() surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES) - for x in range(-size, size): - for y in range(-size, size): - for z in range(-size, size): + for x in range(world_size): + for y in range(world_size): + for z in range(world_size): if surface_points.has(Vector3i(x, y, z)): create_surface_mesh_quad(Vector3i(x,y,z)); mesh = surface_tool.commit() - var meshinstance = MeshInstance3D.new() meshinstance.mesh = mesh - add_child(meshinstance) func create_surface_mesh_quad(index: Vector3i): for axis_index in range(AXIS.size()): var axis = AXIS[axis_index] if sample_points.has(index + axis): - var sample_value1 = sample_points[index] var sample_value2 = sample_points[index + axis] @@ -179,10 +147,10 @@ func add_reversed_quad(index: Vector3i, axis_index: int): func get_quad_points(index: Vector3i, axis_index: int): if surface_points.has(index + QUAD_POINTS[axis_index][0]) and surface_points.has(index + QUAD_POINTS[axis_index][1]) and surface_points.has(index + QUAD_POINTS[axis_index][2]) and surface_points.has(index + QUAD_POINTS[axis_index][3]): return [ - surface_points[index + QUAD_POINTS[axis_index][0]].position, - surface_points[index + QUAD_POINTS[axis_index][1]].position, - surface_points[index + QUAD_POINTS[axis_index][2]].position, - surface_points[index + QUAD_POINTS[axis_index][3]].position, + surface_points[index + QUAD_POINTS[axis_index][0]], + surface_points[index + QUAD_POINTS[axis_index][1]], + surface_points[index + QUAD_POINTS[axis_index][2]], + surface_points[index + QUAD_POINTS[axis_index][3]], ] const QUAD_POINTS := [ diff --git a/smooth_world.tscn b/smooth_world.tscn index 26d463d..cc6d5ac 100644 --- a/smooth_world.tscn +++ b/smooth_world.tscn @@ -1,8 +1,15 @@ -[gd_scene load_steps=2 format=3 uid="uid://llggsd0qmn4p"] +[gd_scene load_steps=4 format=3 uid="uid://llggsd0qmn4p"] [ext_resource type="Script" uid="uid://bdfq22we54eul" path="res://smooth_world.gd" id="1_4h467"] +[ext_resource type="Shader" uid="uid://bose286qacwdl" path="res://generate_mesh.tres" id="2_an62b"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_iutkt"] +render_priority = 0 +shader = ExtResource("2_an62b") [node name="SmoothWorld" type="Node3D"] script = ExtResource("1_4h467") RADIUS = 6.789 -show_surface_points = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +material_override = SubResource("ShaderMaterial_iutkt")