this repo has no description
at main 2.9 kB view raw
1const std = @import("std"); 2 3const spall = @import("spall"); 4const zigimg = @import("zigimg"); 5const zm = @import("zmath"); 6 7const BVH = @import("BVH.zig"); 8const Camera = @import("Camera.zig"); 9const hittable = @import("hittable.zig"); 10const material = @import("material.zig"); 11const Ray = @import("Ray.zig"); 12const util = @import("util.zig"); 13 14const interval = @import("interval.zig"); 15const IntervalUsize = interval.IntervalUsize; 16const IntervalF32 = interval.IntervalF32; 17 18const log = std.log.scoped(.tracer); 19 20pub const Context = struct { 21 pixels: []zm.Vec, 22 cam: *const Camera, 23 world: *const BVH, 24 height: IntervalUsize, 25 width: IntervalUsize, 26}; 27 28const white = zm.f32x4s(1.0); 29const black = zm.f32x4(0, 0, 0, 1.0); 30 31pub fn rayColor(r: *Ray, world: *const BVH, depth: usize) zm.Vec { 32 @setFloatMode(.optimized); 33 if (depth == 0) return backgroundColor(r); 34 35 if (world.hit(r, .{ .min = 0.001, .max = std.math.inf(f32) })) |rec| { 36 var attenuation = zm.f32x4s(1.0); 37 if (rec.mat.scatter(r, &rec, &attenuation)) |new_r| { 38 return attenuation * rayColor(@constCast(&new_r), world, depth - 1); 39 } 40 } 41 42 return backgroundColor(r); 43} 44 45fn backgroundColor(r: *Ray) zm.Vec { 46 const unit_direction = zm.normalize3(r.dir); 47 const a = 0.5 * (unit_direction[1] + 1.0); 48 return zm.f32x4s(1.0 - a) * zm.f32x4s(1.0) + zm.f32x4s(a) * zm.f32x4(0.5, 0.7, 1.0, 1.0); 49} 50 51pub fn trace(ctx: *Context) void { 52 var height_iter = ctx.height.iter(); 53 while (height_iter.nextInc()) |j| { 54 if (j >= ctx.cam.image_height) break; 55 56 var width_iter = ctx.width.iter(); 57 while (width_iter.nextExc()) |i| inner: { 58 var col = zm.f32x4(0.0, 0.0, 0.0, 1.0); 59 60 for (0..ctx.cam.samples_per_pixel) |_| { 61 var ray = ctx.cam.getRay(i, j); 62 col += rayColor(&ray, ctx.world, ctx.cam.max_depth); 63 } 64 65 setPixel(ctx.pixels, ctx.cam, i, j, col) catch { 66 log.err("Trying to set a pixel out of bounds ({}, {})", .{ i, j }); 67 break :inner; 68 }; 69 } 70 } 71} 72 73const zero = zm.f32x4s(0.0); 74const nearly_one = zm.f32x4s(0.999); 75const v256 = zm.f32x4s(256); 76 77inline fn vecToRgba(v: zm.Vec, samples_per_pixel: zm.Vec) zigimg.color.Rgba32 { 78 const rgba = zm.clampFast( 79 @sqrt(v / samples_per_pixel), 80 zero, 81 nearly_one, 82 ) * v256; // linear to gamma 83 84 return zigimg.color.Rgba32.initRgba( 85 @intFromFloat(rgba[0]), 86 @intFromFloat(rgba[1]), 87 @intFromFloat(rgba[2]), 88 @intFromFloat(rgba[3]), 89 ); 90} 91 92pub fn setPixel(pixels: []zm.Vec, cam: *const Camera, x: usize, y: usize, c: zm.Vec) !void { 93 if (x >= cam.image_width or y >= cam.image_height) return error.OutOfBounds; 94 const i = x + cam.image_width * y; 95 pixels[i] = c; 96 // try cam.setPixel(x, y, vecToRgba(c, cam.samples_per_pixel_v)); 97}