From 6603f27c903de2a5b08303dc3fdea0b8b8349136 Mon Sep 17 00:00:00 2001 From: Anton Ljungdahl Date: Tue, 6 May 2025 22:45:23 +0200 Subject: [PATCH] intersecting triangles on cpu --- src/main.odin | 2 + src/rayt_base.odin | 161 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 147 insertions(+), 16 deletions(-) diff --git a/src/main.odin b/src/main.odin index e6e01c0..a4ffa89 100644 --- a/src/main.odin +++ b/src/main.odin @@ -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") diff --git a/src/rayt_base.odin b/src/rayt_base.odin index 7b83ab5..5472061 100644 --- a/src/rayt_base.odin +++ b/src/rayt_base.odin @@ -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.. 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..