sample points on gpu
This commit is contained in:
parent
5733a3b043
commit
d0375a15dc
@ -4,7 +4,7 @@ var rot_y = 0
|
||||
|
||||
@onready var world = preload("res://world.tscn")
|
||||
|
||||
@export var PLAYER_SPEED = 1
|
||||
@export var PLAYER_SPEED = 1.0
|
||||
@export var PLAYER_REACH = 1000
|
||||
@export var NOCLIP = false
|
||||
@export_range(0.00001, 0.01) var LOOK_SENSITIVITY = 0.002
|
||||
|
||||
70
compute_test.gd
Normal file
70
compute_test.gd
Normal file
@ -0,0 +1,70 @@
|
||||
|
||||
var rd: RenderingDevice
|
||||
var shader_file: Resource
|
||||
var shader_spirv: RDShaderSPIRV
|
||||
var shader: RID
|
||||
|
||||
func create_device():
|
||||
rd = RenderingServer.create_local_rendering_device()
|
||||
shader_file = load("res://sdf_shader.glsl")
|
||||
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.
|
||||
var total = world_size * world_size * world_size
|
||||
var input := PackedFloat32Array()
|
||||
input.resize(total)
|
||||
var input_bytes := input.to_byte_array()
|
||||
|
||||
# Create a storage buffer that can hold our float values.
|
||||
var buffer := rd.storage_buffer_create(input_bytes.size(), input_bytes)
|
||||
|
||||
# Create a uniform to assign the buffer to the rendering device
|
||||
var uniform_buf := RDUniform.new()
|
||||
uniform_buf.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER
|
||||
uniform_buf.binding = 0 # this needs to match the "binding" in our shader file
|
||||
uniform_buf.add_id(buffer)
|
||||
|
||||
var peer := StreamPeerBuffer.new()
|
||||
peer.put_32(world_size)
|
||||
peer.put_float(threshold)
|
||||
peer.put_32(0)
|
||||
peer.put_32(0)
|
||||
var bytes := peer.data_array
|
||||
|
||||
var params_buffer := rd.uniform_buffer_create(bytes.size(), bytes)
|
||||
|
||||
var uniform_params := RDUniform.new()
|
||||
uniform_params.uniform_type = RenderingDevice.UNIFORM_TYPE_UNIFORM_BUFFER
|
||||
uniform_params.binding = 1
|
||||
uniform_params.add_id(params_buffer)
|
||||
|
||||
var uniform_set := rd.uniform_set_create([uniform_params, uniform_buf], shader, 0) # the last parameter (the 0) needs to match the "set" in our shader file
|
||||
|
||||
# Create a compute pipeline
|
||||
var pipeline := rd.compute_pipeline_create(shader)
|
||||
var compute_list := rd.compute_list_begin()
|
||||
rd.compute_list_bind_compute_pipeline(compute_list, pipeline)
|
||||
rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0)
|
||||
var dispatch_x = int(ceil(world_size / 8.0))
|
||||
var dispatch_y = int(ceil(world_size / 8.0))
|
||||
var dispatch_z = int(ceil(world_size / 1.0)) # local_size_z = 1
|
||||
rd.compute_list_dispatch(compute_list, dispatch_x, dispatch_y, dispatch_z)
|
||||
rd.compute_list_end()
|
||||
|
||||
# Submit to GPU and wait for sync
|
||||
rd.submit()
|
||||
rd.sync()
|
||||
# Read back the data from the buffer
|
||||
var output_bytes := rd.buffer_get_data(buffer)
|
||||
var output := output_bytes.to_float32_array()
|
||||
|
||||
rd.free_rid(buffer)
|
||||
|
||||
rd.free_rid(params_buffer)
|
||||
return output
|
||||
|
||||
|
||||
1
compute_test.gd.uid
Normal file
1
compute_test.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://du1xgjbvpa6dk
|
||||
@ -1,3 +1,2 @@
|
||||
@export var distance = 0
|
||||
@export var position = Vector3.ZERO
|
||||
@export var visible = false
|
||||
|
||||
29
sdf_shader.glsl
Normal file
29
sdf_shader.glsl
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
#[compute]
|
||||
#version 450
|
||||
|
||||
// Workgroup size
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
// Storage buffer
|
||||
layout(set = 0, binding = 0, std430) buffer DataBuffer {
|
||||
float sample_points[];
|
||||
} voxels;
|
||||
|
||||
layout(set = 0, binding = 1) uniform Params {
|
||||
int world_size;
|
||||
float threshold;
|
||||
} params;
|
||||
|
||||
void main() {
|
||||
uvec3 id = gl_GlobalInvocationID;
|
||||
if (id.x >= uint(params.world_size) ||
|
||||
id.y >= uint(params.world_size) ||
|
||||
id.z >= uint(params.world_size))
|
||||
return;
|
||||
|
||||
uint index = id.x + id.y * uint(params.world_size) + id.z * uint(params.world_size) * uint(params.world_size);
|
||||
vec3 p = vec3(id);
|
||||
float d = length(p) - params.threshold;
|
||||
voxels.sample_points[index] = d;
|
||||
}
|
||||
14
sdf_shader.glsl.import
Normal file
14
sdf_shader.glsl.import
Normal file
@ -0,0 +1,14 @@
|
||||
[remap]
|
||||
|
||||
importer="glsl"
|
||||
type="RDShaderFile"
|
||||
uid="uid://dv4s7mmqwnsqr"
|
||||
path="res://.godot/imported/sdf_shader.glsl-8a6992e3be4c1416763f59c511add1b8.res"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://sdf_shader.glsl"
|
||||
dest_files=["res://.godot/imported/sdf_shader.glsl-8a6992e3be4c1416763f59c511add1b8.res"]
|
||||
|
||||
[params]
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
@tool
|
||||
#@tool
|
||||
extends Node3D
|
||||
const CENTER := Vector3.ZERO
|
||||
@export_range(0.0, 6.9999) var RADIUS: float = 5.0
|
||||
@export var RADIUS: float = 5.0
|
||||
|
||||
var sample_points = {}
|
||||
var SamplePoint = preload("res://sample_point.gd")
|
||||
var surface_points = {}
|
||||
var SurfacePoint = preload("res://surface_point.gd")
|
||||
var ComputeSdf = preload("res://compute_test.gd")
|
||||
var gpu_sdf
|
||||
|
||||
|
||||
@export var world_size = 16
|
||||
@export var show_sample_points = false
|
||||
@ -16,6 +19,8 @@ var SurfacePoint = preload("res://surface_point.gd")
|
||||
@export var do_the_thing: bool = false
|
||||
@export var clear_the_thing: bool = false
|
||||
|
||||
var sdf_buffer = []
|
||||
|
||||
var color = Color.CORAL
|
||||
var surface_point_color = Color.CRIMSON
|
||||
|
||||
@ -23,10 +28,14 @@ var mesh
|
||||
var surface_tool: SurfaceTool = SurfaceTool.new()
|
||||
|
||||
func _ready() -> void:
|
||||
initialize_sample_points()
|
||||
gpu_sdf = ComputeSdf.new()
|
||||
gpu_sdf.create_device()
|
||||
#initialize_sample_points()
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
clear()
|
||||
sdf_buffer = gpu_sdf.compute(world_size * 2, RADIUS)
|
||||
if !sdf_buffer.is_empty():
|
||||
create_surface_points()
|
||||
if show_surface_points:
|
||||
draw_surface_points()
|
||||
@ -47,28 +56,21 @@ func draw_sample_points():
|
||||
for x in range(-world_size + 1, world_size):
|
||||
for y in range(-world_size + 1, world_size):
|
||||
for z in range(-world_size + 1, world_size):
|
||||
DebugDraw3D.draw_square(sample_points[Vector3i(x, y, z)].position, 0.2, color)
|
||||
if sample_points.has(Vector3i(x, y, z)):
|
||||
DebugDraw3D.draw_square(Vector3i(x, y, z), 0.2, color)
|
||||
#DebugDraw3D.draw_text(Vector3i(x, y, z), str(Vector3i(x, y, z)))
|
||||
|
||||
func draw_surface_points():
|
||||
for x in range(-world_size + 1, world_size):
|
||||
for y in range(-world_size + 1, world_size):
|
||||
for z in range(-world_size + 1, world_size):
|
||||
if surface_points.has(Vector3i(x, y, z)):
|
||||
DebugDraw3D.draw_square(surface_points[Vector3i(x, y, z)].position, 0.3, surface_point_color)
|
||||
DebugDraw3D.draw_square(Vector3i(x, y, z), 0.3, surface_point_color)
|
||||
|
||||
|
||||
func get_sample_value(index: Vector3i) -> float:
|
||||
return CENTER.distance_to(index) - RADIUS
|
||||
|
||||
func initialize_sample_points():
|
||||
for x in range(-world_size + 1, world_size):
|
||||
for y in range(-world_size + 1, world_size):
|
||||
for z in range(-world_size + 1, world_size):
|
||||
var sample_point = SamplePoint.new()
|
||||
sample_point.distance = get_sample_value(Vector3i(x, y, z))
|
||||
sample_point.position = Vector3(float(x), float(y), float(z))
|
||||
sample_point.visible = show_sample_points
|
||||
sample_points[Vector3i(x, y, z)] = sample_point
|
||||
sample_points = gpu_sdf.compute(world_size, RADIUS)
|
||||
print("sample_points initialized", sample_points)
|
||||
|
||||
func create_surface_points():
|
||||
for x in range(-world_size + 1, world_size):
|
||||
@ -84,7 +86,13 @@ func create_surface_point(voxel: Vector3i):
|
||||
var intersection_points_number = Vector3.ZERO
|
||||
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 sample_point_distance_from_sdf = get_sample_value(sample_point_to_check)
|
||||
var normal_x = voxel.x + world_size - 1
|
||||
var normal_y = voxel.y + world_size - 1
|
||||
var normal_z = voxel.z + world_size - 1
|
||||
var buffer_index = normal_x + normal_y * world_size + normal_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[voxel] = 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
|
||||
@ -96,7 +104,6 @@ func create_surface_point(voxel: Vector3i):
|
||||
var intersection_points_average = intersection_points_sum/intersection_points_number
|
||||
var surface_point = SurfacePoint.new()
|
||||
surface_point.position = intersection_points_average
|
||||
surface_point.visible = show_surface_points
|
||||
surface_points[voxel] = surface_point
|
||||
|
||||
func calculate_surface_point_position(voxel: Vector3i):
|
||||
@ -109,6 +116,7 @@ func create_surface_mesh(size: int = 6):
|
||||
for x in range(-size, size):
|
||||
for y in range(-size, size):
|
||||
for z in range(-size, 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()
|
||||
@ -119,8 +127,8 @@ func create_surface_mesh_quad(index: Vector3i):
|
||||
for axis_index in range(AXIS.size()):
|
||||
var axis = AXIS[axis_index]
|
||||
|
||||
var sample_value1 = get_sample_value(index)
|
||||
var sample_value2 = get_sample_value(index + axis)
|
||||
var sample_value1 = sample_points[index]
|
||||
var sample_value2 = sample_points[index + axis]
|
||||
|
||||
if sample_value1 < 0 and sample_value2 >= 0:
|
||||
add_quad(index, axis_index)
|
||||
@ -147,14 +155,6 @@ const SURFACE_AXIS := [
|
||||
func add_quad(index: Vector3i, axis_index: int):
|
||||
var points = get_quad_points(index, axis_index)
|
||||
|
||||
var normal = Vector3(
|
||||
(get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[1])) + (get_sample_value(index + SURFACE_AXIS[3]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[4])),
|
||||
(get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[0])) + (get_sample_value(index + SURFACE_AXIS[4]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[3])),
|
||||
(get_sample_value(index + SURFACE_AXIS[7]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[3])) + (get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[4])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[6]))
|
||||
)
|
||||
|
||||
surface_tool.set_normal(normal)
|
||||
|
||||
surface_tool.add_vertex(points[0])
|
||||
surface_tool.add_vertex(points[1])
|
||||
surface_tool.add_vertex(points[2])
|
||||
@ -162,18 +162,11 @@ func add_quad(index: Vector3i, axis_index: int):
|
||||
surface_tool.add_vertex(points[0])
|
||||
surface_tool.add_vertex(points[2])
|
||||
surface_tool.add_vertex(points[3])
|
||||
surface_tool.generate_normals()
|
||||
|
||||
func add_reversed_quad(index: Vector3i, axis_index: int):
|
||||
var points = get_quad_points(index, axis_index)
|
||||
|
||||
var normal = Vector3(
|
||||
(get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[1])) + (get_sample_value(index + SURFACE_AXIS[3]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[4])),
|
||||
(get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[7])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[0])) + (get_sample_value(index + SURFACE_AXIS[4]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[6]) - get_sample_value(index + SURFACE_AXIS[3])),
|
||||
(get_sample_value(index + SURFACE_AXIS[7]) - get_sample_value(index + SURFACE_AXIS[2])) + (get_sample_value(index + SURFACE_AXIS[0]) - get_sample_value(index + SURFACE_AXIS[3])) + (get_sample_value(index + SURFACE_AXIS[1]) - get_sample_value(index + SURFACE_AXIS[4])) + (get_sample_value(index + SURFACE_AXIS[5]) - get_sample_value(index + SURFACE_AXIS[6]))
|
||||
)
|
||||
|
||||
surface_tool.set_normal(normal)
|
||||
|
||||
surface_tool.add_vertex(points[0])
|
||||
surface_tool.add_vertex(points[2])
|
||||
surface_tool.add_vertex(points[1])
|
||||
@ -181,6 +174,7 @@ func add_reversed_quad(index: Vector3i, axis_index: int):
|
||||
surface_tool.add_vertex(points[0])
|
||||
surface_tool.add_vertex(points[3])
|
||||
surface_tool.add_vertex(points[2])
|
||||
surface_tool.generate_normals()
|
||||
|
||||
func get_quad_points(index: Vector3i, axis_index: int):
|
||||
return [
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
|
||||
[node name="SmoothWorld" type="Node3D"]
|
||||
script = ExtResource("1_4h467")
|
||||
RADIUS = 3.971
|
||||
world_size = 8
|
||||
RADIUS = 2.059
|
||||
show_sample_points = true
|
||||
show_surface_points = true
|
||||
do_the_thing = true
|
||||
|
||||
@ -29,6 +29,7 @@ shadow_enabled = true
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource("3_036b0")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.182447, 0.6673207, 0.0726881)
|
||||
PLAYER_SPEED = 0.305
|
||||
NOCLIP = true
|
||||
|
||||
[connection signal="change_world" from="." to="." method="_on_change_world"]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user