smoooooth

This commit is contained in:
Guillaume Vern 2026-02-12 21:22:17 +01:00
parent 8901011b81
commit 3b94b0d335
7 changed files with 50 additions and 38 deletions

View File

@ -1,4 +1,4 @@
extends Node3D
var rd: RenderingDevice
var shader_file1: Resource
var shader_file2: Resource
@ -7,6 +7,8 @@ var shader_spirv2: RDShaderSPIRV
var shader_pass1: RID
var shader_pass2: RID
var start_time := Time.get_ticks_msec() / 1000.0
var color = Color.CORAL
@export var iout_surface_points = []
func create_device():
rd = RenderingServer.create_local_rendering_device()
@ -142,6 +144,7 @@ func compute_mesh(world_size: int, threshold: float) -> ArrayMesh:
var out_norms = rd.buffer_get_data(normal_buffer).to_float32_array()
var out_indices = rd.buffer_get_data(idx_buffer).to_int32_array()
var final_count = rd.buffer_get_data(counter_buffer).to_int32_array()[0]
var out_surface_points = rd.buffer_get_data(surface_buffer).to_float32_array()
rd.free_rid(buffer)
rd.free_rid(params_buffer)
@ -185,7 +188,7 @@ func compute_mesh(world_size: int, threshold: float) -> ArrayMesh:
packed_indices.append(active_map[old_idx])
iout_surface_points = out_surface_points
if packed_verts.size() > 0:
arrays[Mesh.ARRAY_VERTEX] = packed_verts
arrays[Mesh.ARRAY_NORMAL] = packed_normals
@ -194,7 +197,6 @@ func compute_mesh(world_size: int, threshold: float) -> ArrayMesh:
return mesh
func build_sample_dict(world_size: int, flat_buffer: PackedFloat32Array) -> Dictionary:
var dict := {}
var total = world_size * world_size * world_size

View File

@ -4,6 +4,7 @@
constant = Color(0.30202293, 0.6060653, 0.9109474, 1)
[resource]
modes/cull = 2
nodes/vertex/0/position = Vector2(360, 220)
nodes/fragment/0/position = Vector2(660, 140)
nodes/fragment/2/node = SubResource("VisualShaderNodeColorConstant_sxi40")

View File

@ -31,6 +31,7 @@ const ivec3 QUAD_OFFSETS[3][4] = ivec3[3][4](
);
void main() {
memoryBarrierBuffer();
ivec3 id = ivec3(gl_GlobalInvocationID);
if (id.x >= params.world_size || id.y >= params.world_size || id.z >= params.world_size) return;
@ -42,20 +43,17 @@ void main() {
for (int i = 0; i < 3; i++) {
ivec3 neighbor_id = id + AXIS[i];
// Ensure neighbor is in bounds before sampling noise
if (any(greaterThanEqual(neighbor_id, ivec3(params.world_size)))) continue;
if (any(greaterThan(neighbor_id, ivec3(params.world_size)))) continue;
float d1 = voxels.sample_points[idx];
float d2 = voxels.sample_points[index3(neighbor_id.x, neighbor_id.y, neighbor_id.z)];
// Sign change check (Crossing detection)
if ((d1 < 0.0) != (d2 < 0.0)) {
ivec3 p0 = id + QUAD_OFFSETS[i][0];
ivec3 p1 = id + QUAD_OFFSETS[i][1];
ivec3 p2 = id + QUAD_OFFSETS[i][2];
ivec3 p3 = id + QUAD_OFFSETS[i][3];
// Verify all 4 surrounding voxels have valid vertices
if (has_vertex(p0) && has_vertex(p1) && has_vertex(p2) && has_vertex(p3)) {
uint v0 = index3(p0.x, p0.y, p0.z);
uint v1 = index3(p1.x, p1.y, p1.z);
@ -64,7 +62,6 @@ void main() {
uint start = atomicAdd(index_count.count, 6);
// Use the same winding logic as your add_quad / add_reversed_quad
if (d1 < 0.0) {
mesh_indices.indices[start + 0] = v0;
mesh_indices.indices[start + 1] = v1;

View File

@ -181,7 +181,7 @@ const ivec3 CORNERS[8] = ivec3[](
);
float get_noise_at(vec3 p) {
return snoise((p / 10.0) + vec3(params.u_time * .5)) * 5.0;
return snoise((p / 20.0) + vec3(params.u_time * .5));
}
// Calculate normal using central difference
@ -193,19 +193,21 @@ vec3 calculate_normal(vec3 p) {
return normalize(vec3(dx, dy, dz));
}
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;
vec3 grid_to_world(uvec3 grid_id) {
return (vec3(grid_id) - params.world_size / 2.0) * 0.5;
}
vec3 p = vec3(id) - params.world_size / 2;
void main() {
ivec3 id = ivec3(gl_GlobalInvocationID);
if (any(greaterThanEqual(id, uvec3(params.world_size)))) return;
vec3 p = grid_to_world(id);
uint idx = index3(id.x, id.y, id.z);
voxels.sample_points[idx] = get_noise_at(p);
barrier();
memoryBarrierBuffer();
barrier();
vec3 intersection_sum = vec3(0.0);
uint count = 0;
@ -223,11 +225,11 @@ void main() {
if (any(greaterThanEqual(c1, uvec3(params.world_size))) ||
any(greaterThanEqual(c2, uvec3(params.world_size)))) continue;
float d1 = voxels.sample_points[index3(c1.x, c1.y, c1.z)];
float d2 = voxels.sample_points[index3(c2.x, c2.y, c2.z)];
float d1 = get_noise_at(grid_to_world(c1));
float d2 = get_noise_at(grid_to_world(c2));
// Standard sign-change test
if ((d1 < 0.0) != (d2 < 0.0)) {
if ((d1 < 0.0) != (d2 < 0.0) && d1 != -d2) {
// Linear interpolation to find the exact crossing point on the edge
float t = d1 / (d1 - d2);
intersection_sum += mix(vec3(c1), vec3(c2), t);
@ -240,7 +242,7 @@ void main() {
store_surface_point(idx, avg_pos);
// Normals should be calculated at the exact averaged surface point
vec3 world_p = avg_pos - params.world_size / 2.0;
vec3 world_p = (avg_pos - params.world_size / 2.0) * vec3(0.5);
vec3 n = calculate_normal(world_p);
uint base = idx * 3u;
normal.normals[base + 0] = n.x;

View File

@ -53,9 +53,19 @@ func _process(_delta: float) -> void:
#regenerate_mesh = false
clear()
meshinstance.mesh = gpu_sdf.compute_mesh(world_size, RADIUS)
if !surface_points.is_empty():
if show_surface_points:
draw_surface_points()
var idx = 0
var text_id = 0
while idx < gpu_sdf.iout_surface_points.size():
text_id += 1
var value = Vector3(gpu_sdf.iout_surface_points.get(idx), gpu_sdf.iout_surface_points.get(idx+1), gpu_sdf.iout_surface_points.get(idx+2)) - Vector3(world_size / 2, world_size / 2, world_size / 2)
if gpu_sdf.iout_surface_points.get(idx) != -1.0:
DebugDraw3D.draw_square(value, 0.2, color.from_rgba8(255, 128, 128, 255))
if text_id % 3 == 0:
DebugDraw3D.draw_text(value, str(value), 35)
idx += 3
else:
idx += 1
if show_sample_points:
draw_sample_points()

View File

@ -10,7 +10,7 @@ shader = ExtResource("2_an62b")
[node name="SmoothWorld" type="Node3D" unique_id=1592820568]
script = ExtResource("1_4h467")
RADIUS = 18.524
world_size = 64
world_size = 53
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1739626442]
material_override = SubResource("ShaderMaterial_iutkt")

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=6 format=3 uid="uid://dls7ggmf46ia0"]
[gd_scene format=3 uid="uid://dls7ggmf46ia0"]
[ext_resource type="Script" uid="uid://caefudn8tgqpr" path="res://activation.gd" id="1_tlwt5"]
[ext_resource type="PackedScene" uid="uid://chbs3naovk63w" path="res://player.tscn" id="3_036b0"]
@ -16,20 +16,20 @@ sky = SubResource("Sky_tlwt5")
tonemap_mode = 2
glow_enabled = true
[node name="Root" type="Node3D"]
[node name="Root" type="Node3D" unique_id=1762688074]
script = ExtResource("1_tlwt5")
wanted_world = 1
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=340320928]
environment = SubResource("Environment_aqk2v")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=1883705458]
transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
shadow_enabled = true
[node name="Player" parent="." instance=ExtResource("3_036b0")]
[node name="Player" parent="." unique_id=1950519856 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
PLAYER_SPEED = 0.035
NOCLIP = true
[connection signal="change_world" from="." to="." method="_on_change_world"]