Skip to content

Commit 0422827

Browse files
committed
use metada instead of material/prim index
2 parents 7c06129 + 759fb63 commit 0422827

6 files changed

Lines changed: 146 additions & 103 deletions

File tree

docs/src/raytracing-core.jl

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,33 +47,12 @@ function Raycore.to_gpu(Arr, ctx::RenderContext)
4747
return RenderContext(to_gpu(Arr, ctx.lights), to_gpu(Arr, ctx.materials), ctx.ambient)
4848
end
4949

50-
function render_context(; glass_cat=false)
51-
# Create lights and materials
52-
lights = [
50+
function default_lights()
51+
return [
5352
PointLight(Point3f(3, 4, -2), 50.0f0, RGB(1.0f0, 0.9f0, 0.8f0)),
5453
PointLight(Point3f(-3, 2, 0), 20.0f0, RGB(0.7f0, 0.8f0, 1.0f0)),
5554
PointLight(Point3f(0, 5, 5), 15.0f0, RGB(1.0f0, 1.0f0, 1.0f0))
5655
]
57-
58-
# Material: base_color, metallic, roughness, ior, transmission
59-
cat_material = if glass_cat
60-
# Glass cat: clear glass with slight green tint, ior=1.5
61-
Material(RGB(0.95f0, 1.0f0, 0.95f0), 0.0f0, 0.0f0, 1.5f0, 1.0f0)
62-
else
63-
# Original diffuse cat
64-
Material(RGB(0.8f0, 0.6f0, 0.4f0), 0.0f0, 0.8f0, 1.0f0, 0.0f0)
65-
end
66-
67-
materials = [
68-
cat_material, # cat (index 1)
69-
Material(RGB(0.3f0, 0.5f0, 0.3f0), 0.0f0, 0.9f0, 1.0f0, 0.0f0), # floor - diffuse
70-
Material(RGB(0.8f0, 0.6f0, 0.5f0), 0.8f0, 0.05f0, 1.0f0, 0.0f0), # back wall - metallic
71-
Material(RGB(0.7f0, 0.7f0, 0.8f0), 0.0f0, 0.8f0, 1.0f0, 0.0f0), # left wall - diffuse
72-
Material(RGB(0.9f0, 0.9f0, 0.9f0), 0.8f0, 0.02f0, 1.0f0, 0.0f0), # sphere1 - metallic
73-
Material(RGB(0.3f0, 0.6f0, 0.9f0), 0.5f0, 0.3f0, 1.0f0, 0.0f0), # sphere2 - semi-metallic
74-
]
75-
76-
return RenderContext(lights, materials, 0.1f0)
7756
end
7857

7958
function compute_light(
@@ -211,9 +190,27 @@ function example_scene(; glass_cat=false)
211190
sphere1 = Tesselation(Sphere(Point3f(-2, -1.5 + 0.8, 2), 0.8f0), 64)
212191
sphere2 = Tesselation(Sphere(Point3f(2, -1.5 + 0.6, 1), 0.6f0), 64)
213192

214-
# Build our BVH acceleration structure
215-
scene_geometry = [cat_mesh, floor, back_wall, left_wall, sphere1, sphere2]
216-
return scene_geometry, render_context(glass_cat=glass_cat)
193+
# Material: base_color, metallic, roughness, ior, transmission
194+
cat_material = if glass_cat
195+
Material(RGB(0.95f0, 1.0f0, 0.95f0), 0.0f0, 0.0f0, 1.5f0, 1.0f0)
196+
else
197+
Material(RGB(0.8f0, 0.6f0, 0.4f0), 0.0f0, 0.8f0, 1.0f0, 0.0f0)
198+
end
199+
200+
# (geometry, material) pairs
201+
scene = [
202+
(cat_mesh, cat_material),
203+
(floor, Material(RGB(0.3f0, 0.5f0, 0.3f0), 0.0f0, 0.9f0, 1.0f0, 0.0f0)),
204+
(back_wall, Material(RGB(0.8f0, 0.6f0, 0.5f0), 0.8f0, 0.05f0, 1.0f0, 0.0f0)),
205+
(left_wall, Material(RGB(0.7f0, 0.7f0, 0.8f0), 0.0f0, 0.8f0, 1.0f0, 0.0f0)),
206+
(sphere1, Material(RGB(0.9f0, 0.9f0, 0.9f0), 0.8f0, 0.02f0, 1.0f0, 0.0f0)),
207+
(sphere2, Material(RGB(0.3f0, 0.6f0, 0.9f0), 0.5f0, 0.3f0, 1.0f0, 0.0f0)),
208+
]
209+
210+
bvh, materials = MaterialScene(scene)
211+
lights = default_lights()
212+
ctx = RenderContext(lights, materials, 0.1f0)
213+
return bvh, ctx
217214
end
218215

219216
function example_scene_glass_cat()

docs/src/test_wavefront.jl

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,29 @@ using BenchmarkTools
1414
include("raytracing-core.jl")
1515
include("wavefront-renderer.jl")
1616

17-
geom, ctx = example_scene()
18-
bvh = BVH(geom)
19-
ibvh = Raycore.InstancedBVH(geom)
17+
bvh, ctx = example_scene()
18+
# ibvh = Raycore.InstancedBVH(geom)
2019
begin
21-
img = fill(RGBf(0, 0, 0), 1024, 2048)
20+
img = fill(RGBf(0, 0, 0), 400, 720)
2221
renderer = WavefrontRenderer(img, bvh, ctx)
2322
@btime render!(renderer)
2423
nothing
2524
end
2625
renderer.framebuffer
2726
renderer_instanced.framebuffer
2827
begin
29-
img = fill(RGBf(0, 0, 0), 1024, 2048)
28+
img = fill(RGBf(0, 0, 0), 400, 720)
3029
renderer_instanced = WavefrontRenderer(
31-
img, ibvh, ctx;
30+
img, bvh, ctx;
3231
camera_pos=Point3f(0, -0.9, -2.5),
3332
fov=45.0f0,
3433
sky_color=RGB{Float32}(0.5f0, 0.7f0, 1.0f0),
3534
samples_per_pixel=4
3635
)
3736
@btime render!(renderer_instanced)
37+
# on windows + ryzen 395 max
38+
# 381.034 ms (1200456 allocations: 90.13 MiB)
39+
3840
nothing
3941
end
4042
using ImageShow
@@ -43,8 +45,9 @@ using FileIO
4345
save("wavefront.png", map(col -> mapc(c -> clamp(c, 0f0, 1f0), col), renderer.framebuffer))
4446

4547
using AMDGPU
46-
amd_renderer = to_gpu(ROCArray, renderer_instanced);
48+
amd_renderer = to_gpu(ROCArray, renderer);
4749
Array(@btime render!(amd_renderer))
50+
# 36ms on windows + amd 8060s
4851

4952
using pocl_jll, OpenCL
5053
amd_renderer = to_gpu(CLArray, renderer);

docs/src/wavefront-renderer.jl

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,44 @@ using KernelAbstractions
55
using KernelAbstractions: @kernel, @index, @Const
66
import KernelAbstractions as KA
77
using Statistics
8+
9+
# ============================================================================
10+
# MaterialScene Helper
11+
# ============================================================================
12+
13+
"""
14+
MaterialScene(geometry_material_pairs) -> (bvh, materials)
15+
16+
Create a BVH and materials array from a vector of (geometry, material) tuples.
17+
18+
# Arguments
19+
- `geometry_material_pairs`: Vector of `(mesh, material)` tuples
20+
21+
# Returns
22+
- `bvh`: BVH with material indices as triangle metadata
23+
- `materials`: Vector of materials
24+
25+
# Example
26+
```julia
27+
scene = [
28+
(sphere_mesh, Material(...)),
29+
(floor_mesh, Material(...)),
30+
]
31+
bvh, materials = MaterialScene(scene)
32+
```
33+
"""
34+
function MaterialScene(geometry_material_pairs::Vector{<:Tuple{<:Any, M}}) where {M}
35+
meshes = [p[1] for p in geometry_material_pairs]
36+
materials = M[p[2] for p in geometry_material_pairs]
37+
38+
# Create BVH with material index as metadata
39+
function metadata_fn(mesh_idx, _tri_idx)
40+
return Int32(mesh_idx)
41+
end
42+
bvh = Raycore.BVH(meshes, metadata_fn)
43+
return bvh, materials
44+
end
45+
846
# ============================================================================
947
# SoA Access Macros
1048
# ============================================================================
@@ -123,11 +161,12 @@ struct ReflectionRayWork
123161
hit_idx::Int32 # Index back to primary hit
124162
end
125163

126-
struct ReflectionHitWork{T}
164+
struct ReflectionHitWork
127165
hit_found::Bool
128-
tri_idx::T # Store triangle index instead of full triangle
166+
material_idx::Int32 # Store material index (triangle metadata)
129167
dist::Float32
130168
bary::Vec3f
169+
normal::Vec3f # Store interpolated normal
131170
ray::Raycore.Ray
132171
primary_hit_idx::Int32
133172
end
@@ -308,7 +347,7 @@ end
308347
normal = Vec3f(normalize(v0 * u + v1 * v + v2 * w))
309348

310349
# Get material
311-
mat = ctx.materials[tri.material_idx]
350+
mat = ctx.materials[tri.metadata]
312351
base_color = Vec3f(mat.base_color.r, mat.base_color.g, mat.base_color.b)
313352
# Start with ambient
314353
total_color = base_color * ctx.ambient
@@ -363,7 +402,7 @@ end
363402
dummy_ray = Raycore.Ray(o=Point3f(0, 0, 0), d=Vec3f(0, 0, 1), t_max=0.0f0)
364403

365404
if hit_found
366-
mat = ctx.materials[tri.material_idx]
405+
mat = ctx.materials[tri.metadata]
367406
if mat.metallic > 0.0f0
368407
# Compute reflection
369408
hit_point = ray.o + ray.d * dist
@@ -413,10 +452,18 @@ end
413452

414453
if ray.t_max > 0.0f0
415454
hit_found, tri, dist, bary = Raycore.closest_hit(bvh, ray)
416-
# Write to SoA using @set
417-
@set reflection_hit_soa[idx] = (hit_found=hit_found, tri_idx=tri.primitive_idx,
418-
dist=dist, bary=Vec3f(bary),
419-
ray=ray, primary_hit_idx=hit_idx)
455+
if hit_found
456+
# Compute normal here so we don't need to store the triangle
457+
v0, v1, v2 = Raycore.normals(tri)
458+
u, v, w = bary[1], bary[2], bary[3]
459+
normal = Vec3f(normalize(v0 * u + v1 * v + v2 * w))
460+
# Write to SoA using @set
461+
@set reflection_hit_soa[idx] = (hit_found=true, material_idx=tri.metadata,
462+
dist=dist, bary=Vec3f(bary), normal=normal,
463+
ray=ray, primary_hit_idx=hit_idx)
464+
else
465+
reflection_hit_soa.hit_found[idx] = false
466+
end
420467
else
421468
# Write only hit_found as false for dummy rays
422469
reflection_hit_soa.hit_found[idx] = false
@@ -431,7 +478,6 @@ end
431478
@kernel function shade_reflections_and_blend!(
432479
@Const(hit_queue),
433480
@Const(reflection_hit_soa), # SoA version: NamedTuple of arrays
434-
@Const(bvh_triangles), # Need original triangles for material lookup
435481
@Const(ctx),
436482
@Const(sky_color),
437483
shading_queue # In/out: update with reflection contribution
@@ -444,21 +490,17 @@ end
444490
@get hit_found, tri, pixel_x, pixel_y, sample_idx = hit_queue[idx]
445491

446492
if hit_found
447-
mat = ctx.materials[tri.material_idx]
493+
mat = ctx.materials[tri.metadata]
448494

449495
if mat.metallic > 0.0f0
450-
# Access from SoA directly (using different variable names for clarity)
451-
@get hit_found, tri_idx, dist, bary, ray = reflection_hit_soa[idx]
496+
# Access from SoA directly
497+
@get hit_found, material_idx, dist, bary, normal, ray = reflection_hit_soa[idx]
452498
# Compute reflection color (simplified - no recursive shadows for performance)
453499
reflection_color = if hit_found
454500
refl_point = ray.o + ray.d * dist
455-
# Get triangle from BVH using stored index
456-
refl_tri = bvh_triangles[tri_idx]
457-
v0, v1, v2 = Raycore.normals(refl_tri)
458-
u, v, w = bary
459-
refl_normal = Vec3f(normalize(v0 * u + v1 * v + v2 * w))
501+
refl_normal = normal
460502

461-
refl_mat = ctx.materials[refl_tri.material_idx]
503+
refl_mat = ctx.materials[material_idx]
462504
refl_base_color = Vec3f(refl_mat.base_color.r, refl_mat.base_color.g, refl_mat.base_color.b)
463505

464506
# Simplified lighting (ambient + first light only, no shadows)
@@ -614,7 +656,7 @@ function WavefrontRenderer(
614656
shadow_ray_queue = similar_soa(img, ShadowRayWork, num_shadow_rays)
615657
shadow_result_queue = similar_soa(img, ShadowResult, num_shadow_rays)
616658
reflection_ray_soa = similar_soa(img, ReflectionRayWork, num_rays)
617-
reflection_hit_soa = similar_soa(img, ReflectionHitWork{Int32}, num_rays)
659+
reflection_hit_soa = similar_soa(img, ReflectionHitWork, num_rays)
618660
shading_queue = similar_soa(img, ShadedResult, num_rays)
619661
sample_accumulator = similar(img, Vec3f, num_rays)
620662
active_count = similar(img, Int32, 1)
@@ -749,7 +791,6 @@ function render!(renderer::WavefrontRenderer)
749791
refl_shade_kernel!(
750792
renderer.primary_hit_queue,
751793
renderer.reflection_hit_soa,
752-
renderer.bvh.primitives,
753794
renderer.ctx,
754795
renderer.sky_color,
755796
renderer.shading_queue,

0 commit comments

Comments
 (0)