intersecting triangles on cpu
This commit is contained in:
parent
9c4c59e073
commit
6603f27c90
@ -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")
|
||||
|
||||
@ -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)
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user