intersecting triangles on cpu

This commit is contained in:
Anton Ljungdahl 2025-05-06 22:45:23 +02:00
parent 9c4c59e073
commit 6603f27c90
2 changed files with 147 additions and 16 deletions

View File

@ -56,8 +56,10 @@ rl_window_loop :: proc() {
}
main :: proc() {
rl.SetTraceLogLevel(rl.TraceLogLevel.ERROR)
// Fill pixelbuffer with raytraced image.
rayt_cpu_main()
fmt.println("Finished raytracing, launching Raylib window")

View File

@ -2,6 +2,8 @@ package main
import "core:fmt"
import "core:math/rand"
import "core:math/linalg"
import "core:math"
RAND_SEED :: 1984
@ -13,6 +15,11 @@ MAX_NUM_ENTITIES :: 64
Vec3 :: distinct [3]f32
// Global colors
COLOR_LIGHT_BLUE :: Vec3{0.5, 0.7, 1.0}
COLOR_WHITE :: Vec3{1.0, 1.0, 1.0}
Image :: struct {
width : u32,
height : u32,
@ -41,6 +48,11 @@ Viewport :: struct {
}
viewport: Viewport
Ray :: struct {
origin : Vec3,
direction : Vec3
}
HitRecord :: struct {
point : Vec3,
normal : Vec3,
@ -69,6 +81,21 @@ vec3_rand_uniform :: proc() -> Vec3 {
return Vec3{rand.float32(), rand.float32(), rand.float32()}
}
ray_get :: proc(x : f32, y : f32) -> Ray {
out : Ray
px_u := x*viewport.pixel_delta_u
px_v := y*viewport.pixel_delta_v
pixel_center := viewport.pixel_origin + px_u + px_v
ray_direction := pixel_center - camera.center
out.direction = ray_direction
out.origin = camera.center
return out
}
rayt_cpu_main :: proc() {
rand.reset(RAND_SEED)
@ -129,21 +156,8 @@ rayt_cpu_main :: proc() {
pixelbuffer = make([]Vec3, num_pixels);
pixelbuffer_rgb = make([]u8, num_pixels * 3) // rgb values for each pixel
// Temp fill pixels
{
for x in 0..<image.width {
for y in 0..<image.height {
pixel_idx := y * image.width + x
x_val := cast(f32)x/cast(f32)image.width
y_val := cast(f32)y/cast(f32)image.height
pixelbuffer[pixel_idx] = Vec3{x_val, y_val, 0.0}
}
}
}
fmt.println("Starting CPU raytracing")
cpu_raytracing()
// Translate pixelbuffer with colors from 0 to 1, to rgb 0..255
{
@ -159,8 +173,123 @@ rayt_cpu_main :: proc() {
pixelbuffer_rgb[rgb_idx + 1] = u8(255.999 * g)
pixelbuffer_rgb[rgb_idx + 2] = u8(255.999 * b)
}
}
}
}
vec3_lerp :: proc(s : f32, a : Vec3, b : Vec3) -> Vec3 {
return (1.0-s)*a + s*b
}
ray_point :: proc(t : f32, ray : ^Ray) -> Vec3 {
out : Vec3
out = ray.origin + t * ray.direction
return out
}
triangle_intersection :: proc(ray : ^Ray, rec : ^HitRecord, triangle : ^Entity) {
edge1 := triangle.v1-triangle.v0
edge2 := triangle.v2-triangle.v0
rec.hit = false
// Moller-Trumbore intersection algorithm
{
h := linalg.cross(ray.direction, edge2)
closest_so_far : f32 = rec.t
a := linalg.dot(edge1, h)
if a <= -0.001 || a >= 0.001 {
f := 1.0/a
s := ray.origin-triangle.v0
u := f * linalg.dot(s, h)
if u >= 0.0 && u <= 1.0 {
q := linalg.cross(s, edge1)
v := f * linalg.dot(ray.direction, q)
if v >= 0.0 && (u + v) <= 1.0 {
t := f * linalg.dot(edge2, q)
if t > 0.0001 && t <= closest_so_far {
rec.hit = true
rec.t = t
}
}
}
}
}
if rec.hit {
intersection_point := ray_point(rec.t, ray)
v0_normal := linalg.cross(edge1, edge2)
v0_normal = linalg.normalize(v0_normal)
front_face := linalg.dot(ray.direction, v0_normal) < 0.0
if front_face {
rec.normal = v0_normal
} else {
rec.normal = -1.0*v0_normal
}
rec.point = intersection_point
}
}
cpu_raytracing :: proc() {
num_hits : u32 = 0
last_ray : Ray
// Temp fill pixels
{
hit_rec : HitRecord
for x in 0..<image.width {
for y in 0..<image.height {
pixel_idx := y * image.width + x
sample_pixel_color : Vec3
ray := ray_get(cast(f32)x, cast(f32)y)
hit_rec.hit = false
hit_rec.t = math.F32_MAX
temp_hit_rec : HitRecord
temp_hit_rec.hit = false
temp_hit_rec.t = hit_rec.t
for i in 0..<MAX_NUM_ENTITIES {
tri_ref := &entities[i]
triangle_intersection(&ray, &temp_hit_rec, tri_ref)
if temp_hit_rec.hit {
hit_rec.hit = true
hit_rec.t = temp_hit_rec.t
hit_rec.normal = temp_hit_rec.normal
num_hits += 1
}
}
if hit_rec.hit {
// Color triangle
sample_pixel_color = 0.5*(hit_rec.normal + COLOR_WHITE)
} else {
// Background gradient
unit_dir := linalg.normalize(ray.direction)
blend : f32 = 0.5*(unit_dir.y + 1.0)
sample_pixel_color = vec3_lerp(blend, COLOR_WHITE, COLOR_LIGHT_BLUE)
}
pixelbuffer[pixel_idx] = sample_pixel_color
last_ray = ray
}
}
}
//fmt.printf("Num hits on triangles: %i \n", num_hits)
}