Skip to content

Commit 962431b

Browse files
committed
built bvh i guess
1 parent e090daf commit 962431b

File tree

5 files changed

+145
-17
lines changed

5 files changed

+145
-17
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ fn init(
155155
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
156156
pub async fn run() {
157157
info!("Starting up");
158-
let scale = 1.0;
158+
let scale = 2.0;
159159
let width = 900 * scale as u32;
160160
let height = 450 * scale as u32;
161161
let (window, event_loop) = init(width, height);

src/render_context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,20 @@ impl<'a> RenderContext<'a> {
179179
Some("texture buffer"),
180180
);
181181

182+
let aabb_buffer = StorageBuffer::new_from_bytes(
183+
&device,
184+
bytemuck::cast_slice(scene.get_bvh().as_slice()),
185+
3_u32,
186+
Some("aabb buffer"),
187+
);
188+
182189
let scene_bind_group_layout =
183190
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
184191
entries: &[
185192
sphere_buffer.layout(wgpu::ShaderStages::FRAGMENT, true),
186193
material_buffer.layout(wgpu::ShaderStages::FRAGMENT, true),
187194
texture_buffer.layout(wgpu::ShaderStages::FRAGMENT, true),
195+
aabb_buffer.layout(wgpu::ShaderStages::FRAGMENT, true),
188196
],
189197
label: Some("scene layout"),
190198
});
@@ -195,6 +203,7 @@ impl<'a> RenderContext<'a> {
195203
sphere_buffer.binding(),
196204
material_buffer.binding(),
197205
texture_buffer.binding(),
206+
aabb_buffer.binding(),
198207
],
199208
label: Some("scene bind group"),
200209
});

src/scene/aabb.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use glm::Vec3;
2+
3+
use super::Sphere;
4+
5+
#[repr(C)]
6+
#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
7+
pub struct AABB {
8+
pub min: Vec3,
9+
pub max: Vec3,
10+
pub left_child: u32,
11+
pub right_child: u32,
12+
}

src/scene/mod.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ pub use camera::{Camera, CameraController, GpuCamera};
44
mod material;
55
pub use material::{GpuMaterial, Material, Texture};
66

7+
mod aabb;
8+
79
#[derive(Clone, Debug)]
810
pub struct Scene {
911
pub materials: Vec<Material>,
@@ -132,6 +134,90 @@ impl Scene {
132134
camera_controller,
133135
}
134136
}
137+
138+
pub fn get_bvh(&self) -> Vec<aabb::AABB> {
139+
let mut bvh = Vec::new();
140+
141+
let axis = rand::random::<u32>() % 3;
142+
let mut spheres = self.spheres.clone();
143+
144+
spheres.sort_by(|a, b| {
145+
let a = a.get_bounding_box();
146+
let b = b.get_bounding_box();
147+
148+
a.min[axis as usize]
149+
.partial_cmp(&b.min[axis as usize])
150+
.unwrap()
151+
});
152+
153+
let mut stack = Vec::new();
154+
stack.push((0, spheres.len(), 0));
155+
156+
while let Some((start, end, _)) = stack.pop() {
157+
let mut min = glm::vec3(std::f32::INFINITY, std::f32::INFINITY, std::f32::INFINITY);
158+
let mut max = glm::vec3(
159+
std::f32::NEG_INFINITY,
160+
std::f32::NEG_INFINITY,
161+
std::f32::NEG_INFINITY,
162+
);
163+
164+
for i in start..end {
165+
let sphere = &spheres[i];
166+
let aabb = sphere.get_bounding_box();
167+
168+
min = glm::vec3(
169+
min.x.min(aabb.min.x),
170+
min.y.min(aabb.min.y),
171+
min.z.min(aabb.min.z),
172+
);
173+
174+
max = glm::vec3(
175+
max.x.max(aabb.max.x),
176+
max.y.max(aabb.max.y),
177+
max.z.max(aabb.max.z),
178+
);
179+
}
180+
181+
let mid = (start + end) / 2;
182+
183+
let left_child = if mid - start == 1 {
184+
start as u32
185+
} else {
186+
bvh.len() as u32 + 1
187+
};
188+
189+
let right_child = if end - mid == 1 {
190+
mid as u32
191+
} else {
192+
bvh.len() as u32 + 2
193+
};
194+
195+
bvh.push(aabb::AABB {
196+
min,
197+
max,
198+
left_child,
199+
right_child,
200+
});
201+
202+
if mid - start > 1 {
203+
stack.push((start, mid, bvh.len() as u32 - 1));
204+
}
205+
206+
if end - mid > 1 {
207+
stack.push((mid, end, bvh.len() as u32 - 1));
208+
}
209+
}
210+
211+
// DEBUG: traverse bvh and print a tree
212+
for (i, aabb) in bvh.iter().enumerate() {
213+
println!(
214+
"Node: {} min: {:?} max: {:?} left: {} right: {}",
215+
i, aabb.min, aabb.max, aabb.left_child, aabb.right_child
216+
);
217+
}
218+
219+
bvh
220+
}
135221
}
136222

137223
#[repr(C)]
@@ -191,4 +277,15 @@ impl Sphere {
191277
_padding: [0; 2],
192278
}
193279
}
280+
pub fn get_bounding_box(&self) -> aabb::AABB {
281+
let radius = glm::vec3(self.radius, self.radius, self.radius);
282+
let center = self.center.xyz();
283+
284+
aabb::AABB {
285+
min: center - radius,
286+
max: center + radius,
287+
left_child: 0,
288+
right_child: 0,
289+
}
290+
}
194291
}

src/shader/raytracing.wgsl

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const MAX_T = 1000f;
2525
@group(1) @binding(0) var<storage, read> spheres: array<Sphere>;
2626
@group(1) @binding(1) var<storage, read> materials: array<Material>;
2727
@group(1) @binding(2) var<storage, read> textures: array<array<f32, 3>>;
28+
@group(1) @binding(3) var<storage, read> aabbs: array<AABB>;
2829

2930
@vertex
3031
fn vs_main(
@@ -155,6 +156,13 @@ struct Ray {
155156
direction: vec3<f32>,
156157
};
157158

159+
struct AABB {
160+
min: vec3<f32>,
161+
max: vec3<f32>,
162+
left_child: u32,
163+
right_child: u32,
164+
};
165+
158166
struct Sphere {
159167
center: vec4<f32>,
160168
radius: f32,
@@ -276,22 +284,6 @@ fn get_ray(rngState: ptr<function, u32>, x: f32, y: f32) -> Ray {
276284

277285

278286

279-
// pub fn from_linear_rgb(c: [f32; 3]) -> Color {
280-
// let f = |x: f32| -> u32 {
281-
// let y = if x > 0.0031308 {
282-
// let a = 0.055;
283-
// (1.0 + a) * x.powf(-2.4) - a
284-
// } else {
285-
// 12.92 * x
286-
// };
287-
// (y * 255.0).round() as u32
288-
// };
289-
// f(c[0]) << 16 | f(c[1]) << 8 | f(c[2])
290-
// }
291-
292-
293-
294-
295287
fn ray_color(first_ray: Ray, rngState: ptr<function, u32>) -> vec3<f32> {
296288
var ray = first_ray;
297289
var sky_color = vec3(0.0);
@@ -316,6 +308,24 @@ fn ray_color(first_ray: Ray, rngState: ptr<function, u32>) -> vec3<f32> {
316308
}
317309

318310

311+
fn rayIntersectBV(ray: ptr<function, Ray>, aabb: ptr<function, AABB>) -> bool {
312+
let t0 = ((*aabb).min - (*ray).origin) / (*ray).direction;
313+
let t1 = ((*aabb).max - (*ray).origin) / (*ray).direction;
314+
let tmin = min(t0, t1);
315+
let tmax = max(t0, t1);
316+
let maxMinT = max(tmin.x, max(tmin.y, tmin.z));
317+
let minMaxT = min(tmax.x, min(tmax.y, tmax.z));
318+
return maxMinT < minMaxT;
319+
}
320+
321+
fn rayIntersectBVH(
322+
ray: Ray,
323+
hit: ptr<function, HitRecord>,
324+
) -> bool {
325+
// TODO: Implement BVH traversal
326+
return true;
327+
}
328+
319329

320330
fn scatter(ray: Ray, hit: HitRecord, material: Material, rngState: ptr<function, u32>) -> Scatter {
321331
switch (material.id)

0 commit comments

Comments
 (0)