this repo has no description

antialiasing

+60 -20
+20
src/camera.zig
··· 1 const std = @import("std"); 2 3 const zigimg = @import("zigimg"); 4 const color = zigimg.color; 5 const zm = @import("zmath"); 6 7 const log = std.log.scoped(.camera); 8 ··· 11 pub const Options = struct { 12 image_width: usize, 13 aspect_ratio: f32, 14 }; 15 16 image_height: usize, 17 image_width: usize, 18 aspect_ratio: f32, 19 20 focal_lenght: f32, 21 viewport_height: f32, ··· 61 .image_width = image_width, 62 .image_height = image_height, 63 .aspect_ratio = aspect_ratio, 64 65 .focal_lenght = focal_lenght, 66 .viewport_height = viewport_height, ··· 83 self.image.deinit(); 84 } 85 86 pub fn setPixel(self: *Camera, x: usize, y: usize, c: color.Rgba32) !void { 87 if (x >= self.image_width or y >= self.image_height) return error.OutOfBounds; 88 const i = x + self.image_width * y; 89 self.image.pixels.rgba32[i] = c; 90 }
··· 1 const std = @import("std"); 2 + const random = std.crypto.random; 3 4 const zigimg = @import("zigimg"); 5 const color = zigimg.color; 6 const zm = @import("zmath"); 7 + 8 + pub const Ray = @import("ray.zig"); 9 10 const log = std.log.scoped(.camera); 11 ··· 14 pub const Options = struct { 15 image_width: usize, 16 aspect_ratio: f32, 17 + samples_per_pixel: usize, 18 }; 19 20 image_height: usize, 21 image_width: usize, 22 aspect_ratio: f32, 23 + samples_per_pixel: usize, 24 25 focal_lenght: f32, 26 viewport_height: f32, ··· 66 .image_width = image_width, 67 .image_height = image_height, 68 .aspect_ratio = aspect_ratio, 69 + .samples_per_pixel = opts.samples_per_pixel, 70 71 .focal_lenght = focal_lenght, 72 .viewport_height = viewport_height, ··· 89 self.image.deinit(); 90 } 91 92 + pub fn getRay(self: *Camera, i: usize, j: usize) Ray { 93 + const pixel_center = self.pixel00_loc + (zm.f32x4s(@as(f32, @floatFromInt(i))) * self.pixel_delta_u) + (zm.f32x4s(@as(f32, @floatFromInt(j))) * self.pixel_delta_v); 94 + const pixel_sample = pixel_center + self.pixelSamplesSq(); 95 + 96 + const ray_direction = pixel_sample - self.camera_center; 97 + return Ray.init(self.camera_center, ray_direction); 98 + } 99 + 100 pub fn setPixel(self: *Camera, x: usize, y: usize, c: color.Rgba32) !void { 101 if (x >= self.image_width or y >= self.image_height) return error.OutOfBounds; 102 const i = x + self.image_width * y; 103 self.image.pixels.rgba32[i] = c; 104 } 105 + 106 + fn pixelSamplesSq(self: *Camera) zm.Vec { 107 + const px = zm.f32x4s(-0.5 + random.float(f32)); 108 + const py = zm.f32x4s(-0.5 + random.float(f32)); 109 + return (px * self.pixel_delta_u) + (py * self.pixel_delta_v); 110 + }
+12
src/interval.zig
··· 81 return self.min < x and x < self.max; 82 } 83 84 pub fn iter(self: *const Self) Iterator { 85 return Iterator{ 86 .interval = self.*, ··· 108 109 pub fn surrounds(self: *const Self, x: T) bool { 110 return self.min < x and x < self.max; 111 } 112 }; 113 } else {
··· 81 return self.min < x and x < self.max; 82 } 83 84 + pub fn clamp(self: *const Self, x: T) T { 85 + if (x < self.min) return self.min; 86 + if (x > self.max) return self.max; 87 + return x; 88 + } 89 + 90 pub fn iter(self: *const Self) Iterator { 91 return Iterator{ 92 .interval = self.*, ··· 114 115 pub fn surrounds(self: *const Self, x: T) bool { 116 return self.min < x and x < self.max; 117 + } 118 + 119 + pub fn clamp(self: *const Self, x: T) T { 120 + if (x < self.min) return self.min; 121 + if (x > self.max) return self.max; 122 + return x; 123 } 124 }; 125 } else {
+1 -1
src/main.zig
··· 33 const s = spall.trace(@src(), "Raytracer", .{}); 34 35 // Raytracing part 36 - var raytracer = try rayray.Raytracer.init(allocator, world, .{ .aspect_ratio = 16.0 / 9.0, .image_width = 400 }); 37 defer raytracer.deinit(); 38 39 const img = try raytracer.render();
··· 33 const s = spall.trace(@src(), "Raytracer", .{}); 34 35 // Raytracing part 36 + var raytracer = try rayray.Raytracer.init(allocator, world, .{ .aspect_ratio = 16.0 / 9.0, .image_width = 400, .samples_per_pixel = 100 }); 37 defer raytracer.deinit(); 38 39 const img = try raytracer.render();
+8 -9
src/rayray.zig
··· 64 threads[row].thread = t; 65 } 66 67 - // const stderr = std.io.getStdErr(); 68 - // // defer stderr.close(); 69 70 - // var progress = std.Progress{ 71 - // .terminal = stderr, 72 - // .supports_ansi_escape_codes = true, 73 - // }; 74 - // var node = progress.start("Rendering Completed", num_threads); 75 - // node.activate(); 76 77 while (true) { 78 var done = true; ··· 93 if (done) break; 94 } 95 96 - // node.end(); 97 98 return self.camera.image; 99 }
··· 64 threads[row].thread = t; 65 } 66 67 + const stderr = std.io.getStdErr(); 68 69 + var progress = std.Progress{ 70 + .terminal = stderr, 71 + .supports_ansi_escape_codes = true, 72 + }; 73 + var node = progress.start("Rendering Completed", num_threads); 74 + node.activate(); 75 76 while (true) { 77 var done = true; ··· 92 if (done) break; 93 } 94 95 + node.end(); 96 97 return self.camera.image; 98 }
+19 -10
src/renderer.zig
··· 36 37 var width_iter = width.iter(); 38 while (width_iter.nextExc()) |i| { 39 - const pixel_center = ctx.cam.pixel00_loc + (zm.f32x4s(@as(f32, @floatFromInt(i))) * ctx.cam.pixel_delta_u) + (zm.f32x4s(@as(f32, @floatFromInt(j))) * ctx.cam.pixel_delta_v); 40 - const ray_direction = pixel_center - ctx.cam.camera_center; 41 - var ray = Ray.init(ctx.cam.camera_center, ray_direction); 42 - const col = vecToRgba(rayColor(&ray, ctx.world)); 43 44 - ctx.cam.setPixel(i, j, col) catch break; 45 } 46 } 47 } ··· 63 done.store(true, .Release); 64 } 65 66 - fn vecToRgba(v: zm.Vec) zigimg.color.Rgba32 { 67 - const r: u8 = @intFromFloat(255.999 * v[0]); 68 - const g: u8 = @intFromFloat(255.999 * v[1]); 69 - const b: u8 = @intFromFloat(255.999 * v[2]); 70 - const a: u8 = @intFromFloat(255.999 * v[3]); 71 72 return zigimg.color.Rgba32.initRgba(r, g, b, a); 73 }
··· 36 37 var width_iter = width.iter(); 38 while (width_iter.nextExc()) |i| { 39 + var col = zm.f32x4(0.0, 0.0, 0.0, 1.0); 40 + for (0..ctx.cam.samples_per_pixel) |_| { 41 + var ray = ctx.cam.getRay(i, j); 42 + col += rayColor(&ray, ctx.world); 43 + } 44 45 + ctx.cam.setPixel(i, j, vecToRgba(col, ctx.cam.samples_per_pixel)) catch break; 46 } 47 } 48 } ··· 64 done.store(true, .Release); 65 } 66 67 + fn vecToRgba(v: zm.Vec, samples_per_pixel: usize) zigimg.color.Rgba32 { 68 + const scale: f32 = 1.0 / @as(f32, @floatFromInt(samples_per_pixel)); 69 + const intensity = IntervalF32.init(0.0, 0.999); 70 + 71 + const r_scaled = v[0] * scale; 72 + const g_scaled = v[1] * scale; 73 + const b_scaled = v[2] * scale; 74 + const a_scaled = v[3] * scale; 75 + 76 + const r: u8 = @intFromFloat(256 * intensity.clamp(r_scaled)); 77 + const g: u8 = @intFromFloat(256 * intensity.clamp(g_scaled)); 78 + const b: u8 = @intFromFloat(256 * intensity.clamp(b_scaled)); 79 + const a: u8 = @intFromFloat(256 * intensity.clamp(a_scaled)); 80 81 return zigimg.color.Rgba32.initRgba(r, g, b, a); 82 }