pop stack using highest differing bit
This commit is contained in:
@@ -57,6 +57,7 @@ const ZERO3F = vec3<f32>(0.0);
|
|||||||
const ZERO2F = vec2<f32>(0.0);
|
const ZERO2F = vec2<f32>(0.0);
|
||||||
const FULL_ALPHA = 0.999;
|
const FULL_ALPHA = 0.999;
|
||||||
const EPSILON = 0.00000000001;
|
const EPSILON = 0.00000000001;
|
||||||
|
const MAX_ITERS = 1000;
|
||||||
|
|
||||||
fn trace_full(pos_view: vec4<f32>, dir_view: vec4<f32>) -> vec4<f32> {
|
fn trace_full(pos_view: vec4<f32>, dir_view: vec4<f32>) -> vec4<f32> {
|
||||||
let gi = 0;
|
let gi = 0;
|
||||||
@@ -85,7 +86,7 @@ fn trace_full(pos_view: vec4<f32>, dir_view: vec4<f32>) -> vec4<f32> {
|
|||||||
(group.transform * vec4<f32>(0.0, dir_if.y, 0.0, 0.0)).xyz,
|
(group.transform * vec4<f32>(0.0, dir_if.y, 0.0, 0.0)).xyz,
|
||||||
(group.transform * vec4<f32>(0.0, 0.0, dir_if.z, 0.0)).xyz,
|
(group.transform * vec4<f32>(0.0, 0.0, dir_if.z, 0.0)).xyz,
|
||||||
);
|
);
|
||||||
var next_normal = vec3<f32>(0.0, 0.0, 0.0);
|
var axis = 0u;
|
||||||
|
|
||||||
// find where ray intersects with group
|
// find where ray intersects with group
|
||||||
let pos_min = (vec3<f32>(1.0) - dir_uf) * dim_f;
|
let pos_min = (vec3<f32>(1.0) - dir_uf) * dim_f;
|
||||||
@@ -94,7 +95,6 @@ fn trace_full(pos_view: vec4<f32>, dir_view: vec4<f32>) -> vec4<f32> {
|
|||||||
// time of intersection; x = td + p, solve for t
|
// time of intersection; x = td + p, solve for t
|
||||||
let t_min = (pos_min - pos) / dir;
|
let t_min = (pos_min - pos) / dir;
|
||||||
let t_max = (pos_max - pos) / dir;
|
let t_max = (pos_max - pos) / dir;
|
||||||
var t = 0.0;
|
|
||||||
if outside3f(pos, ZERO3F, dim_f) {
|
if outside3f(pos, ZERO3F, dim_f) {
|
||||||
// points of intersection
|
// points of intersection
|
||||||
let px = pos + t_min.x * dir;
|
let px = pos + t_min.x * dir;
|
||||||
@@ -111,11 +111,12 @@ fn trace_full(pos_view: vec4<f32>, dir_view: vec4<f32>) -> vec4<f32> {
|
|||||||
return vec4<f32>(0.0);
|
return vec4<f32>(0.0);
|
||||||
}
|
}
|
||||||
pos = select(select(pz, py, hit.y), px, hit.x);
|
pos = select(select(pz, py, hit.y), px, hit.x);
|
||||||
t = select(select(t_min.z, t_min.y, hit.y), t_min.x, hit.x);
|
axis = select(select(2u, 1u, hit.y), 0u, hit.x);
|
||||||
next_normal = select(select(normals[2], normals[1], hit.y), normals[0], hit.x);
|
|
||||||
}
|
}
|
||||||
var vox_pos = clamp(vec3<i32>(pos), vec3<i32>(0), dim_i - vec3<i32>(1));
|
// time to move 1 unit in each direction
|
||||||
let inc_t = abs(1.0 / dir);
|
let inc_t = abs(1.0 / dir);
|
||||||
|
let t_offset = max(max(t_min.x, t_min.y), t_min.z);
|
||||||
|
var t = max(0.0, t_offset);
|
||||||
|
|
||||||
let dir_i = vec3<i32>(dir_if);
|
let dir_i = vec3<i32>(dir_if);
|
||||||
let dir_u = vec3<u32>((dir_i + vec3<i32>(1)) / 2);
|
let dir_u = vec3<u32>((dir_i + vec3<i32>(1)) / 2);
|
||||||
@@ -123,70 +124,85 @@ fn trace_full(pos_view: vec4<f32>, dir_view: vec4<f32>) -> vec4<f32> {
|
|||||||
let inv_dir_bits = 7 - dir_bits;
|
let inv_dir_bits = 7 - dir_bits;
|
||||||
|
|
||||||
var node_start = 1u;
|
var node_start = 1u;
|
||||||
var t_center = (t_max + t_min) / 2.0;
|
var scale = 7u;
|
||||||
var half_t_span = f32(256 / 2) * inc_t;
|
var half_t_span = f32(1u << scale) * inc_t;
|
||||||
var scale = 0;
|
var t_center = t_min + half_t_span;
|
||||||
|
|
||||||
var dir_idx = vec3<u32>(vec3<f32>(t) > t_center);
|
|
||||||
var child = vec_to_dir(dir_idx);
|
|
||||||
var parents = array<u32, 8>();
|
|
||||||
var color = vec4<f32>(0.0);
|
var color = vec4<f32>(0.0);
|
||||||
|
var parents = array<u32, 8>();
|
||||||
|
|
||||||
for (var safety = 0; safety < 1000; safety += 1) {
|
var child = (u32(t > t_center.x) << 2) + (u32(t > t_center.y) << 1) + u32(t > t_center.z);
|
||||||
|
var child_pos = dir_to_vec(child);
|
||||||
|
var vox_pos = child_pos * (1u << scale);
|
||||||
|
|
||||||
|
var iters = 0;
|
||||||
|
loop {
|
||||||
|
if iters == MAX_ITERS {
|
||||||
|
return vec4<f32>(1.0, 0.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
iters += 1;
|
||||||
let node = voxels[group.offset + node_start + (child ^ inv_dir_bits)];
|
let node = voxels[group.offset + node_start + (child ^ inv_dir_bits)];
|
||||||
if node >= LEAF_BIT {
|
if node >= LEAF_BIT {
|
||||||
let vcolor = get_color(node & LEAF_MASK);
|
let vcolor = get_color(node & LEAF_MASK);
|
||||||
if vcolor.a > 0.0 {
|
if vcolor.a > 0.0 {
|
||||||
let diffuse = max(dot(global_lights[0].dir, next_normal) + 0.1, 0.0);
|
let diffuse = max(dot(global_lights[0].dir, normals[axis]) + 0.1, 0.0);
|
||||||
let ambient = 0.2;
|
let ambient = 0.2;
|
||||||
let lighting = max(diffuse, ambient);
|
let lighting = max(diffuse, ambient);
|
||||||
let new_color = min(vcolor.xyz * lighting, vec3<f32>(1.0));
|
let new_color = min(vcolor.xyz * lighting, vec3<f32>(1.0));
|
||||||
color += vec4<f32>(new_color.xyz * vcolor.a, vcolor.a) * (1.0 - color.a);
|
color += vec4<f32>(new_color.xyz * vcolor.a, vcolor.a) * (1.0 - color.a);
|
||||||
if color.a > FULL_ALPHA { return color; }
|
if color.a > FULL_ALPHA { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
let center_adj = t_center + half_t_span * vec3<f32>(dir_idx);
|
// move to next time point and determine which axis to move along
|
||||||
t = min(min(center_adj.x, center_adj.y), center_adj.z);
|
let t_next = t_center + half_t_span * vec3<f32>(child_pos);
|
||||||
var move_dir = 0u;
|
t = min(min(t_next.x, t_next.y), t_next.z);
|
||||||
if t == center_adj.x { move_dir = 4u; next_normal = normals[0]; }
|
axis = select(select(0u, 1u, t == t_next.y), 2u, t == t_next.z);
|
||||||
if t == center_adj.y { move_dir = 2u; next_normal = normals[1]; }
|
let move_dir = 4u >> axis;
|
||||||
if t == center_adj.z { move_dir = 1u; next_normal = normals[2]; }
|
|
||||||
if move_dir == 0 { return vec4<f32>(1.0); }
|
|
||||||
while (child & move_dir) > 0 {
|
|
||||||
if scale == 0 { return color; }
|
|
||||||
|
|
||||||
scale -= 1;
|
// check if need to pop stack
|
||||||
|
if (child & move_dir) > 0 {
|
||||||
|
// calculate new scale; first differing bit after adding
|
||||||
|
let new_pos = vox_pos[axis] + (1u << scale);
|
||||||
|
if new_pos == 256 { break; }
|
||||||
|
let differing = vox_pos[axis] ^ new_pos;
|
||||||
|
vox_pos[axis] = new_pos;
|
||||||
|
scale = firstLeadingBit(differing);
|
||||||
|
|
||||||
|
// restore & recalculate parent
|
||||||
let parent_info = parents[scale];
|
let parent_info = parents[scale];
|
||||||
node_start = parent_info >> 3;
|
node_start = parent_info >> 3;
|
||||||
child = parent_info & 7;
|
child = parent_info & 7;
|
||||||
|
let scale_vec = vec3<u32>(scale + 1);
|
||||||
dir_idx = dir_to_vec(child);
|
vox_pos = (vox_pos >> scale_vec) << scale_vec; // remove lower scale bits
|
||||||
t_center -= half_t_span * (vec3<f32>(dir_idx * 2) - 1.0);
|
half_t_span = f32(1u << scale) * inc_t;
|
||||||
half_t_span *= 2.0;
|
t_center = vec3<f32>(vox_pos) * inc_t + t_min + half_t_span;
|
||||||
}
|
}
|
||||||
child = child ^ move_dir;
|
// move to next child and voxel position
|
||||||
dir_idx = dir_to_vec(child);
|
child ^= move_dir;
|
||||||
|
child_pos = dir_to_vec(child);
|
||||||
|
vox_pos |= child_pos << vec3<u32>(scale);
|
||||||
} else {
|
} else {
|
||||||
|
// push current node to stack
|
||||||
parents[scale] = (node_start << 3) + child;
|
parents[scale] = (node_start << 3) + child;
|
||||||
scale += 1;
|
scale -= 1u;
|
||||||
|
|
||||||
|
// calculate child node vars
|
||||||
half_t_span /= 2.0;
|
half_t_span /= 2.0;
|
||||||
t_center += half_t_span * (vec3<f32>(dir_idx * 2) - 1.0);
|
t_center += half_t_span * (vec3<f32>(child_pos * 2) - 1.0);
|
||||||
dir_idx = vec3<u32>(vec3<f32>(t) > t_center);
|
child_pos = vec3<u32>(vec3<f32>(t) > t_center);
|
||||||
|
child = (child_pos.x << 2) + (child_pos.y << 1) + child_pos.z;
|
||||||
child = vec_to_dir(dir_idx);
|
vox_pos += child_pos * (1u << scale);
|
||||||
node_start = node_start + 8 + node;
|
node_start = node_start + 8 + node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec4<f32>(1.0, 0.0, 1.0, 1.0);
|
// return vec4<f32>(f32(iters) / f32(MAX_ITERS), 0.0, 0.0, 1.0);
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LEAF_BIT = 1u << 31u;
|
const LEAF_BIT = 1u << 31u;
|
||||||
const LEAF_MASK = ~LEAF_BIT;
|
const LEAF_MASK = ~LEAF_BIT;
|
||||||
|
|
||||||
// no clue if this is efficient, mod is faster for all I know
|
|
||||||
fn dir_to_vec(bits: u32) -> vec3<u32> {
|
fn dir_to_vec(bits: u32) -> vec3<u32> {
|
||||||
return vec3<u32>(extractBits(bits, 2u, 1u), extractBits(bits, 1u, 1u), extractBits(bits, 0u, 1u));
|
return vec3<u32>(bits >> 2, (bits & 2) >> 1, bits & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vec_to_dir(vec: vec3<u32>) -> u32 {
|
fn vec_to_dir(vec: vec3<u32>) -> u32 {
|
||||||
|
|||||||
Reference in New Issue
Block a user