diff --git a/src/Camera.zig b/src/Camera.zig index 950d192..3ba6376 100644 --- a/src/Camera.zig +++ b/src/Camera.zig @@ -32,6 +32,7 @@ image_width: usize, aspect_ratio: f32, samples_per_pixel: usize, +samples_per_pixel_v: zm.Vec, max_depth: usize, vfov: f32, @@ -117,6 +118,7 @@ pub fn init(allocator: std.mem.Allocator, opts: Options) !Camera { .aspect_ratio = aspect_ratio, .samples_per_pixel = opts.samples_per_pixel, + .samples_per_pixel_v = zm.f32x4s(@as(f32, @floatFromInt(opts.samples_per_pixel))), .max_depth = opts.max_depth, .vfov = vfov, diff --git a/src/hittable.zig b/src/hittable.zig index 2cd9c50..cfc2f9b 100644 --- a/src/hittable.zig +++ b/src/hittable.zig @@ -28,7 +28,7 @@ pub const HitRecord = struct { pub const Hittable = union(enum) { sphere: struct { Sphere, []const u8 }, - pub fn sphere(name: []const u8, s: Sphere) Hittable { + pub fn initSphere(name: []const u8, s: Sphere) Hittable { // std.log.info("created sphere with mat: {}", .{s.mat}); return .{ .sphere = .{ s, name } }; } diff --git a/src/material.zig b/src/material.zig index 0c9246c..26cd095 100644 --- a/src/material.zig +++ b/src/material.zig @@ -12,19 +12,19 @@ pub const Material = union(enum) { metal: Metal, dielectric: Dielectric, - pub fn lambertian(tex: texture.Texture) Material { + pub fn initLambertian(tex: texture.Texture) Material { return .{ .lambertian = .{ .tex = tex } }; } - pub fn lambertianS(albedo: zm.Vec) Material { + pub fn initLambertianS(albedo: zm.Vec) Material { return .{ .lambertian = .{ .tex = .{ .solid_color = .{ .albedo = albedo } } } }; } - pub fn metal(albedo: zm.Vec, fuzz: f32) Material { + pub fn initMetal(albedo: zm.Vec, fuzz: f32) Material { return .{ .metal = .{ .albedo = albedo, .fuzz = if (fuzz < 1) fuzz else 1.0 } }; } - pub fn dielectric(refraction_index: f32) Material { + pub fn initDielectric(refraction_index: f32) Material { return .{ .dielectric = .{ .refraction_index = refraction_index } }; } diff --git a/src/scences/checker.zig b/src/scences/checker.zig index cc490d4..59ac5ad 100644 --- a/src/scences/checker.zig +++ b/src/scences/checker.zig @@ -22,10 +22,10 @@ pub fn scene(allocator: std.mem.Allocator) !@This() { c2.* = tex.Texture{ .solid_color = tex.SolidColor.rgb(0.9, 0.9, 0.9) }; const checker = try allocator.create(Material); - checker.* = Material.lambertian(tex.Texture{ .checker_texture = tex.CheckerTexture.init(0.32, c1, c2) }); + checker.* = Material.initLambertian(tex.Texture{ .checker_texture = tex.CheckerTexture.init(0.32, c1, c2) }); - try world.add(Hittable.sphere("s1", Sphere.init(zm.f32x4(0, -10, 0, 0), 10, checker))); - try world.add(Hittable.sphere("s2", Sphere.init(zm.f32x4(0, 10, 0, 0), 10, checker))); + try world.add(Hittable.initSphere("s1", Sphere.init(zm.f32x4(0, -10, 0, 0), 10, checker))); + try world.add(Hittable.initSphere("s2", Sphere.init(zm.f32x4(0, 10, 0, 0), 10, checker))); return .{ .allocator = allocator, .world = world, .camera = Camera.Options{ .aspect_ratio = 16.0 / 9.0, diff --git a/src/scences/in_one_weekend.zig b/src/scences/in_one_weekend.zig index 3a8364e..e367719 100644 --- a/src/scences/in_one_weekend.zig +++ b/src/scences/in_one_weekend.zig @@ -16,8 +16,8 @@ pub fn scene(allocator: std.mem.Allocator) !@This() { var world = HittableList.init(allocator); const material_ground = try allocator.create(Material); - material_ground.* = Material.lambertianS(zm.f32x4(0.5, 0.5, 0.5, 1.0)); - try world.add(Hittable.sphere("Ground", Sphere.init(zm.f32x4(0, -1000, 0, 0), 1000, material_ground))); + material_ground.* = Material.initLambertianS(zm.f32x4(0.5, 0.5, 0.5, 1.0)); + try world.add(Hittable.initSphere("Ground", Sphere.init(zm.f32x4(0, -1000, 0, 0), 1000, material_ground))); const a_max = 30; const b_max = 30; @@ -41,37 +41,37 @@ pub fn scene(allocator: std.mem.Allocator) !@This() { if (choose_mat < 0.8) { // diffuse const albedo = rayray.util.randomVec3() * rayray.util.randomVec3() + zm.f32x4(0, 0, 0, 1); - material.* = Material.lambertianS(albedo); + material.* = Material.initLambertianS(albedo); const center2 = center + zm.f32x4(0, rayray.util.randomF32M(0, 0.5), 0, 0); - try world.add(Hittable.sphere("Lambertian", Sphere.initMoving(center, center2, 0.2, material))); + try world.add(Hittable.initSphere("Lambertian", Sphere.initMoving(center, center2, 0.2, material))); } else if (choose_mat < 0.95) { // metal const albedo = rayray.util.randomVec3M(0.5, 1) + zm.f32x4(0, 0, 0, 1); const fuzz = rayray.util.randomF32M(0, 0.5); - material.* = Material.metal(albedo, fuzz); - try world.add(Hittable.sphere("Metal", Sphere.init(center, 0.2, material))); + material.* = Material.initMetal(albedo, fuzz); + try world.add(Hittable.initSphere("Metal", Sphere.init(center, 0.2, material))); } else { // glass - material.* = Material.dielectric(1.5); - try world.add(Hittable.sphere("Dielectric", Sphere.init(center, 0.2, material))); + material.* = Material.initDielectric(1.5); + try world.add(Hittable.initSphere("Dielectric", Sphere.init(center, 0.2, material))); } } } } const material1 = try allocator.create(Material); - material1.* = Material.dielectric(1.5); - // try world.add(Hittable.sphere("One: Dielectric", Sphere{ .center = zm.f32x4(0, 1, 0, 0), .radius = 1, .mat = material1 })); + material1.* = Material.initDielectric(1.5); + try world.add(Hittable.initSphere("One: Dielectric", Sphere.init(zm.f32x4(0, 1, 0, 0), 1, material1))); const material2 = try allocator.create(Material); - material2.* = Material.lambertianS(zm.f32x4(0.4, 0.2, 0.1, 1)); - try world.add(Hittable.sphere("Two: Lambertian", Sphere.init(zm.f32x4(-4, 1, 0, 0), 1, material1))); + material2.* = Material.initLambertianS(zm.f32x4(0.4, 0.2, 0.1, 1)); + try world.add(Hittable.initSphere("Two: Lambertian", Sphere.init(zm.f32x4(-4, 1, 0, 0), 1, material2))); const material3 = try allocator.create(Material); - material3.* = Material.metal(zm.f32x4(0.7, 0.6, 0.5, 1), 0); - try world.add(Hittable.sphere("Three: Metal", Sphere.init(zm.f32x4(4, 1, 0, 0), 1, material3))); + material3.* = Material.initMetal(zm.f32x4(0.7, 0.6, 0.5, 1), 0); + try world.add(Hittable.initSphere("Three: Metal", Sphere.init(zm.f32x4(4, 1, 0, 0), 1, material3))); - try world.add(Hittable.sphere("One: Dielectric", Sphere.init(zm.f32x4(0, 1, 0, 0), 1, material2))); + // try world.add(Hittable.sphere("One: Dielectric", Sphere.init(zm.f32x4(0, 1, 0, 0), 1, material2))); return .{ .allocator = allocator, .world = world, .camera = .{ .aspect_ratio = 16.0 / 9.0, diff --git a/src/tracer.zig b/src/tracer.zig index 2011970..931564f 100644 --- a/src/tracer.zig +++ b/src/tracer.zig @@ -24,17 +24,20 @@ pub const Context = struct { width: IntervalUsize, }; +const white = zm.f32x4s(1.0); +const black = zm.f32x4(0, 0, 0, 1.0); + pub fn rayColor(r: *Ray, world: *BVH, depth: usize) zm.Vec { @setFloatMode(.optimized); - if (depth == 0) return zm.f32x4(0, 0, 0, 1.0); + if (depth == 0) return black; if (world.hit(r, .{ .min = 0.001, .max = std.math.inf(f32) })) |rec| { - var attenuation = zm.f32x4s(1.0); + var attenuation = white; if (rec.mat.scatter(r, @constCast(&rec), &attenuation)) |new_r| { return attenuation * rayColor(@constCast(&new_r), world, depth - 1); } - return zm.f32x4(0, 0, 0, 1.0); + return black; } const unit_direction = zm.normalize3(r.dir); @@ -43,8 +46,6 @@ pub fn rayColor(r: *Ray, world: *BVH, depth: usize) zm.Vec { } pub fn trace(ctx: Context) void { - const spp = zm.f32x4s(@as(f32, @floatFromInt(ctx.cam.samples_per_pixel))); - var height_iter = ctx.height.iter(); while (height_iter.nextInc()) |j| { if (j >= ctx.cam.image_height) break; @@ -58,7 +59,10 @@ pub fn trace(ctx: Context) void { col += rayColor(&ray, ctx.world, ctx.cam.max_depth); } - ctx.cam.setPixel(i, j, vecToRgba(col, spp)) catch break; + ctx.cam.setPixel(i, j, vecToRgba( + col, + ctx.cam.samples_per_pixel_v, + )) catch break; } } } @@ -68,9 +72,11 @@ const nearly_one = zm.f32x4s(0.999); const v256 = zm.f32x4s(256); inline fn vecToRgba(v: zm.Vec, samples_per_pixel: zm.Vec) zigimg.color.Rgba32 { - var rgba = zm.sqrt(v / samples_per_pixel); // linear to gamma - rgba = zm.clampFast(rgba, zero, nearly_one); - rgba = rgba * v256; + const rgba = zm.clampFast( + @sqrt(v / samples_per_pixel), + zero, + nearly_one, + ) * v256; // linear to gamma return zigimg.color.Rgba32.initRgba( @intFromFloat(rgba[0]),