this repo has no description
at 232ee55093cceaa6d53d8fd08f9ee489f6bcec79 78 lines 2.7 kB view raw
1const std = @import("std"); 2 3const spall = @import("spall"); 4const zigimg = @import("zigimg"); 5const zm = @import("zmath"); 6 7const Camera = @import("camera.zig"); 8const hittable = @import("hittable.zig"); 9const material = @import("material.zig"); 10const Ray = @import("ray.zig"); 11const util = @import("util.zig"); 12 13const interval = @import("a").interval; 14const IntervalUsize = interval.IntervalUsize; 15const IntervalF32 = interval.IntervalF32; 16 17const log = std.log.scoped(.renderer); 18 19pub const Context = struct { 20 cam: *Camera, 21 world: *hittable.HittableList, 22}; 23 24pub fn rayColor(r: *Ray, world: *hittable.HittableList, depth: usize) zm.Vec { 25 if (depth <= 0) return zm.f32x4(0, 0, 0, 1.0); 26 27 if (world.hit(r, IntervalF32.init(0.001, std.math.inf(f32)))) |rec| { 28 var attenuation = zm.f32x4s(1.0); 29 if (rec.mat.scatter(r, @constCast(&rec), &attenuation)) |new_r| { 30 return attenuation * rayColor(@constCast(&new_r), world, depth - 1); 31 } 32 33 return zm.f32x4(0, 0, 0, 1.0); 34 } 35 36 const unit_direction = zm.normalize3(r.dir); 37 const a = 0.5 * (unit_direction[1] + 1.0); 38 return zm.f32x4s(1.0 - a) * zm.f32x4s(1.0) + zm.f32x4s(a) * zm.f32x4(0.5, 0.7, 1.0, 1.0); 39} 40 41pub fn run(ctx: Context, height: IntervalUsize, width: IntervalUsize) void { 42 var height_iter = height.iter(); 43 while (height_iter.nextInc()) |j| { 44 if (j >= ctx.cam.image_height) break; 45 46 var width_iter = width.iter(); 47 while (width_iter.nextExc()) |i| { 48 var col = zm.f32x4(0.0, 0.0, 0.0, 1.0); 49 for (0..ctx.cam.samples_per_pixel) |_| { 50 var ray = ctx.cam.getRay(i, j); 51 col += rayColor(&ray, ctx.world, ctx.cam.max_depth); 52 } 53 54 ctx.cam.setPixel(i, j, vecToRgba(col, ctx.cam.samples_per_pixel)) catch break; 55 } 56 } 57} 58 59fn vecToRgba(v: zm.Vec, samples_per_pixel: usize) zigimg.color.Rgba32 { 60 const scale: f32 = 1.0 / @as(f32, @floatFromInt(samples_per_pixel)); 61 const intensity = IntervalF32.init(0.0, 0.999); 62 63 const r_scaled = linearToGamma(v[0] * scale); 64 const g_scaled = linearToGamma(v[1] * scale); 65 const b_scaled = linearToGamma(v[2] * scale); 66 const a_scaled = linearToGamma(v[3] * scale); 67 68 const r: u8 = @intFromFloat(256 * intensity.clamp(r_scaled)); 69 const g: u8 = @intFromFloat(256 * intensity.clamp(g_scaled)); 70 const b: u8 = @intFromFloat(256 * intensity.clamp(b_scaled)); 71 const a: u8 = @intFromFloat(256 * intensity.clamp(a_scaled)); 72 73 return zigimg.color.Rgba32.initRgba(r, g, b, a); 74} 75 76inline fn linearToGamma(linear_component: f32) f32 { 77 return @sqrt(linear_component); 78}