Skip to content

Commit

Permalink
a bunch
Browse files Browse the repository at this point in the history
  • Loading branch information
robtfm committed Jul 25, 2022
1 parent b6e619b commit f2e4056
Show file tree
Hide file tree
Showing 22 changed files with 1,880 additions and 1,732 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
/Cargo.lock
out.txt
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy = { path = "../bevy" }
# atlas3d = { path = "../atlas3d" }
atlas3d = { git = "https://github.com/robtfm/atlas3d" }
bevy = { git = "https://github.com/robtfm/bevy", branch="sdfao_working" }
# bevy = { path = "../bevy" }
# bevy = { git = "https://github.com/bevyengine/bevy" }
Binary file added assets/gltf/fox2.glb
Binary file not shown.
Binary file modified assets/gltf/monkey.glb
Binary file not shown.
112 changes: 72 additions & 40 deletions assets/shader/compute_sdf.wgsl
Original file line number Diff line number Diff line change
@@ -1,103 +1,134 @@
struct VertexData {
v: vec3<f32>;
n: vec3<f32>;
v: vec3<f32>,
n: vec3<f32>,
};

struct Vertices {
data: array<VertexData>;
data: array<VertexData>,
};

struct EdgeData {
a: vec3<f32>;
b: vec3<f32>;
n: vec3<f32>;
a: vec3<f32>,
b: vec3<f32>,
n: vec3<f32>,
};

struct Edges {
data: array<EdgeData>;
data: array<EdgeData>,
};

struct TriData {
a: vec3<f32>;
b: vec3<f32>;
c: vec3<f32>;
plane: vec4<f32>;
inv_area: f32;
a: vec3<f32>,
b: vec3<f32>,
c: vec3<f32>,
plane: vec4<f32>,
inv_area: f32,
};

struct Tris {
data: array<TriData>;
data: array<TriData>,
};

struct Sdf {
aabb_min: vec3<f32>;
scale: vec3<f32>;
struct InstanceData {
write_position: vec3<u32>,
aabb_min: vec3<f32>,
scale: vec3<f32>,
block_dimensions: vec3<u32>,
counts: vec3<u32>,
block_count: u32,
};

[[group(0), binding(0)]]
var<uniform> sdf: Sdf;
[[group(0), binding(1)]]
struct Instances {
data: array<InstanceData>,
};

@group(0) @binding(0)
var<storage> instances: Instances;
@group(0) @binding(1)
var<storage> vertices: Vertices;
[[group(0), binding(2)]]
@group(0) @binding(2)
var<storage> edges: Edges;
[[group(0), binding(3)]]
@group(0) @binding(3)
var<storage> tris: Tris;
[[group(0), binding(4)]]
@group(0) @binding(4)
var texture: texture_storage_3d<r32float, write>;

fn distance_squared(x: vec3<f32>, y: vec3<f32>) -> f32 {
let v = y - x;
return dot(v, v);
}

[[stage(compute), workgroup_size(8, 8, 8)]]
fn calc([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
@compute
@workgroup_size(8, 8, 8)
fn calc(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
var block_id = invocation_id.x / 8u;
var instance_index = 0;

var start = vec3<u32>(0u, 0u, 0u);
var instance = instances.data[instance_index];
while (block_id >= instance.block_count) {
start = start + instance.counts;
block_id = block_id - instance.block_count;
instance_index = instance_index + 1;
instance = instances.data[instance_index];
}

let block_z = block_id / (instance.block_dimensions.x * instance.block_dimensions.y);
let block_y = (block_id - block_z * (instance.block_dimensions.x * instance.block_dimensions.y)) / instance.block_dimensions.x;
let block_x = (block_id - block_z * (instance.block_dimensions.x * instance.block_dimensions.y) - block_y * instance.block_dimensions.x);

let target_offset = vec3<u32>(
block_x * 8u + invocation_id.x % 8u,
block_y * 8u + invocation_id.y,
block_z * 8u + invocation_id.z,
);

let target_point: vec3<f32> = instance.aabb_min + vec3<f32>(target_offset) * instance.scale;

var best_dist_sq = 999999.0;
var best_norm: vec3<f32>;
var best_nearest: vec3<f32>;

let point: vec3<f32> = sdf.aabb_min + vec3<f32>(invocation_id) * sdf.scale;

for (var i = 0u; i < arrayLength(&vertices.data); i = i + 1u) {
for (var i = start.x; i < start.x + instance.counts.x; i = i + 1u) {
let data = vertices.data[i];
let dist_sq = distance_squared(point, data.v);
let dist_sq = distance_squared(target_point, data.v);
if (dist_sq < best_dist_sq) {
best_dist_sq = dist_sq;
best_norm = data.n;
best_nearest = data.v;
}
}

for (var i = 0u; i < arrayLength(&edges.data); i = i + 1u) {
for (var i = start.y; i < start.y + instance.counts.y; i = i + 1u) {
let data = edges.data[i];

let line = data.b - data.a;
let line_len_sq = dot(line, line);
let intercept = clamp(dot(point - data.a, line), 0.0, line_len_sq);
if (intercept < 0.001 || intercept > line_len_sq * 0.999) {
let edge = data.b - data.a;
let edge_len_sq = dot(edge, edge);
let intercept = clamp(dot(target_point - data.a, edge), 0.0, edge_len_sq);
if (intercept < 0.001 || intercept > edge_len_sq * 0.999) {
continue;
}

let nearest = data.a + line * (intercept / line_len_sq);
let dist_sq = distance_squared(point, nearest);
let nearest = data.a + edge * (intercept / edge_len_sq);
let dist_sq = distance_squared(target_point, nearest);
if (dist_sq < best_dist_sq) {
best_dist_sq = dist_sq;
best_norm = data.n;
best_nearest = nearest;
}
}

for (var i = 0u; i < arrayLength(&tris.data); i = i + 1u) {
for (var i = start.z; i < start.z + instance.counts.z; i = i + 1u) {
let tri = tris.data[i];

let distance_to_plane = dot(tri.plane, vec4<f32>(point, 1.0));
let distance_to_plane = dot(tri.plane, vec4<f32>(target_point, 1.0));
let distance_to_plane_sq = distance_to_plane * distance_to_plane;
if (distance_to_plane_sq > best_dist_sq) {
continue;
}

let n = tri.plane.xyz;
let point_on_plane = point - distance_to_plane * n;
let point_on_plane = target_point - distance_to_plane * n;
// barycentric coords
let u = dot(
cross(tri.c - tri.b, point_on_plane - tri.b),
Expand All @@ -116,8 +147,9 @@ fn calc([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
}
}

let direction = point - best_nearest;
let direction = target_point - best_nearest;
let outside = sign(dot(direction, best_norm));
let dist = sqrt(best_dist_sq) * outside;
textureStore(texture, vec3<i32>(invocation_id), vec4<f32>(dist, 0.0, 0.0, 1.0));

textureStore(texture, vec3<i32>(instance.write_position + target_offset), vec4<f32>(dist, 0.0, 0.0, 1.0));
}
45 changes: 23 additions & 22 deletions assets/shader/render_sdf.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
#import bevy_pbr::mesh_functions

struct Uniform {
aabb_min: vec3<f32>;
aabb_extents: vec3<f32>;
base_color: vec4<f32>;
hit_color: vec4<f32>;
step_color: vec4<f32>;
distance_color: vec4<f32>;
min_step_size: f32;
hit_threshold: f32;
max_step_count: u32;
position: vec3<f32>,
size: vec3<f32>,
scale: f32,
aabb_min: vec3<f32>,
aabb_extents: vec3<f32>,
base_color: vec4<f32>,
hit_color: vec4<f32>,
step_color: vec4<f32>,
distance_color: vec4<f32>,
min_step_size: f32,
hit_threshold: f32,
max_step_count: u32,
};

[[group(1), binding(0)]]
@group(1) @binding(0)
var<uniform> material: Uniform;
[[group(1), binding(1)]]
var sdf_texture: texture_3d<f32>;
[[group(1), binding(2)]]
var sdf_sampler: sampler;

struct FragmentInput {
[[builtin(position)]] frag_coord: vec4<f32>;
@builtin(position) frag_coord: vec4<f32>,
#import bevy_pbr::mesh_vertex_output
};

fn isnan(x: f32) -> bool {
Expand All @@ -37,27 +37,28 @@ fn sample_distance(pos: vec3<f32>) -> vec3<f32> {
let nearest = clamp(local_position, material.aabb_min, material.aabb_min + material.aabb_extents);

let coords = clamp((local_position - material.aabb_min) / material.aabb_extents, vec3<f32>(0.0), vec3<f32>(1.0)); // 0-1
let sample = textureSample(sdf_texture, sdf_sampler, coords).r;
let atlas_coords = material.position + coords * material.size;
let inner_distance = textureSample(sdf_atlas, sdf_sampler, atlas_coords).r;

let offset = nearest - local_position;
let distance_to_aabb_sq = dot(offset, offset);

if (distance_to_aabb_sq == 0.0) {
// inside the volume
return vec3<f32>(sample, 0.0, 0.0);
return vec3<f32>(inner_distance * material.scale, 0.0, 0.0);
} else {
if (sample < 0.0) {
if (inner_distance < 0.0) {
return vec3<f32>(0.0, 1.0, 0.0);
// error, negative on edge
}
// worst case assume right angle
let sample = max(sample, 0.0);
return vec3<f32>(sqrt(distance_to_aabb_sq + sample * sample), 0.0, 0.0);
let inner_distance = max(inner_distance, 0.0) * material.scale;
return vec3<f32>(sqrt(distance_to_aabb_sq + inner_distance * inner_distance), 0.0, 0.0);
}
}

[[stage(fragment)]]
fn fragment(in: FragmentInput) -> [[location(0)]] vec4<f32> {
@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
let x = in.frag_coord.x / f32(view.width) * 2.0 - 1.0;
let y = in.frag_coord.y / f32(view.height) * -2.0 + 1.0;

Expand Down
Loading

0 comments on commit f2e4056

Please sign in to comment.