From 06ac077eadd0a02dcc33e0ba58e45adb491e8fef Mon Sep 17 00:00:00 2001 From: Altagos Date: Tue, 20 Aug 2024 22:31:54 +0200 Subject: [PATCH] implemented a checker texture --- src/Texture.zig | 17 ----------- src/hittable.zig | 4 +-- src/hittable/sphere.zig | 11 +++++++ src/main.zig | 16 ++--------- src/material.zig | 13 ++++++--- src/rayray.zig | 1 + src/scences.zig | 1 + src/scences/checker.zig | 46 ++++++++++++++++++++++++++++++ src/scences/in_one_weekend.zig | 22 +++++++++++--- src/texture.zig | 52 ++++++++++++++++++++++++++++++++++ 10 files changed, 142 insertions(+), 41 deletions(-) delete mode 100644 src/Texture.zig create mode 100644 src/scences/checker.zig create mode 100644 src/texture.zig diff --git a/src/Texture.zig b/src/Texture.zig deleted file mode 100644 index eaee6ac..0000000 --- a/src/Texture.zig +++ /dev/null @@ -1,17 +0,0 @@ -const zm = @import("zmath"); - -pub const SolidColor = struct { - albedo: zm.Vec, - - pub fn init(albedo: zm.Vec) SolidColor { - return .{ .albedo = albedo }; - } - - pub fn rgb(r: f32, g: f32, b: f32) SolidColor { - return init(zm.f32x4(r, g, b, 1.0)); - } - - pub fn value(self: *SolidColor, _: f32, _: f32, _: zm.Vec) zm.Vec { - return self.albedo; - } -}; diff --git a/src/hittable.zig b/src/hittable.zig index 2befe57..2cd9c50 100644 --- a/src/hittable.zig +++ b/src/hittable.zig @@ -15,8 +15,8 @@ pub const HitRecord = struct { normal: zm.Vec = zm.f32x4s(1.0), mat: *Material, t: f32, - u: f32, - v: f32, + u: f32 = 0, + v: f32 = 0, front_face: bool = true, pub fn setFaceNormal(self: *HitRecord, r: *Ray, outward_normal: zm.Vec) void { diff --git a/src/hittable/sphere.zig b/src/hittable/sphere.zig index 4808d39..0dc02db 100644 --- a/src/hittable/sphere.zig +++ b/src/hittable/sphere.zig @@ -1,3 +1,5 @@ +const math = @import("std").math; + const zm = @import("zmath"); const AABB = @import("../AABB.zig"); @@ -71,6 +73,7 @@ pub fn hit(self: *const Sphere, r: *Ray, ray_t: IntervalF32) ?HitRecord { const outward_normal = (rec.p - self.center) / zm.f32x4s(self.radius); rec.setFaceNormal(r, outward_normal); + setSphereUV(&rec, outward_normal); return rec; } @@ -79,3 +82,11 @@ pub inline fn sphereCenter(self: *const Sphere, time: f32) zm.Vec { if (!self.is_moving) return self.center; return self.center + zm.f32x4s(time) * self.center_vec; } + +fn setSphereUV(rec: *HitRecord, p: zm.Vec) void { + const theta = math.acos(-p[1]); + const phi = math.atan2(-p[2], p[0]) + math.pi; + + rec.u = phi / (2 * math.pi); + rec.v = theta / phi; +} diff --git a/src/main.zig b/src/main.zig index 4fae27d..090bba5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -22,25 +22,13 @@ pub fn main() !void { const allocator = arena.allocator(); // Setting up the world - var scence = try scences.inOneWeekend(allocator); + var scence = try scences.checker(allocator); defer scence.deinit(); std.log.info("World created", .{}); // Raytracing part - var raytracer = try rayray.Raytracer.init(allocator, scence.world, .{ - .aspect_ratio = 16.0 / 9.0, - .image_width = 400, - .samples_per_pixel = 50, - .max_depth = 50, - - .vfov = 20, - .look_from = zm.f32x4(20, 6, 6, 0), - .look_at = zm.f32x4(0, 0, 0, 0), - - .defocus_angle = 0.6, - .focus_dist = 18, - }); + var raytracer = try rayray.Raytracer.init(allocator, scence.world, scence.camera); defer raytracer.deinit(); var timer = try std.time.Timer.start(); diff --git a/src/material.zig b/src/material.zig index 49c83cd..0c9246c 100644 --- a/src/material.zig +++ b/src/material.zig @@ -5,14 +5,19 @@ const zm = @import("zmath"); const hittable = @import("hittable.zig"); const Ray = @import("Ray.zig"); const util = @import("util.zig"); +const texture = @import("texture.zig"); pub const Material = union(enum) { lambertian: Lambertian, metal: Metal, dielectric: Dielectric, - pub fn lambertian(albedo: zm.Vec) Material { - return .{ .lambertian = .{ .albedo = albedo } }; + pub fn lambertian(tex: texture.Texture) Material { + return .{ .lambertian = .{ .tex = tex } }; + } + + pub fn lambertianS(albedo: zm.Vec) Material { + return .{ .lambertian = .{ .tex = .{ .solid_color = .{ .albedo = albedo } } } }; } pub fn metal(albedo: zm.Vec, fuzz: f32) Material { @@ -33,14 +38,14 @@ pub const Material = union(enum) { }; pub const Lambertian = struct { - albedo: zm.Vec, + tex: texture.Texture, pub inline fn scatter(self: *Lambertian, r: *Ray, rec: *hittable.HitRecord, attenuation: *zm.Vec) ?Ray { var scatter_dir = rec.normal + util.randomUnitVec(); if (util.nearZero(scatter_dir)) scatter_dir = rec.normal; - attenuation.* = self.albedo; + attenuation.* = self.tex.value(rec.u, rec.v, rec.p); // return Ray.initT(rec.p, scatter_dir, r.tm); return Ray{ .orig = rec.p, .dir = scatter_dir, .tm = r.tm }; } diff --git a/src/rayray.zig b/src/rayray.zig index 0c55f26..0efaee0 100644 --- a/src/rayray.zig +++ b/src/rayray.zig @@ -12,6 +12,7 @@ pub const hittable = @import("hittable.zig"); pub const interval = @import("interval.zig"); const IntervalUsize = interval.IntervalUsize; pub const material = @import("material.zig"); +pub const texture = @import("texture.zig"); pub const tracer = @import("tracer.zig"); pub const util = @import("util.zig"); diff --git a/src/scences.zig b/src/scences.zig index 3351105..1ca35f6 100644 --- a/src/scences.zig +++ b/src/scences.zig @@ -1 +1,2 @@ +pub const checker = @import("scences/checker.zig").scene; pub const inOneWeekend = @import("scences/in_one_weekend.zig").scene; diff --git a/src/scences/checker.zig b/src/scences/checker.zig new file mode 100644 index 0000000..cc490d4 --- /dev/null +++ b/src/scences/checker.zig @@ -0,0 +1,46 @@ +const std = @import("std"); + +const rayray = @import("rayray"); +const Camera = rayray.Camera; +const Hittable = rayray.hittable.Hittable; +const HittableList = rayray.hittable.HittableList; +const Material = rayray.material.Material; +const Sphere = rayray.hittable.Sphere; +const tex = rayray.texture; +const zm = rayray.zmath; + +camera: Camera.Options, +world: HittableList, +allocator: std.mem.Allocator, + +pub fn scene(allocator: std.mem.Allocator) !@This() { + var world = HittableList.init(allocator); + + const c1 = try allocator.create(tex.Texture); + c1.* = tex.Texture{ .solid_color = tex.SolidColor.rgb(0.2, 0.3, 0.1) }; + const c2 = try allocator.create(tex.Texture); + 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) }); + + 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))); + + return .{ .allocator = allocator, .world = world, .camera = Camera.Options{ + .aspect_ratio = 16.0 / 9.0, + .image_width = 400, + .samples_per_pixel = 100, + .max_depth = 50, + + .vfov = 20, + .look_from = zm.f32x4(13, 2, 3, 0), + .look_at = zm.f32x4(0, 0, 0, 0), + + .defocus_angle = 0, + } }; +} + +pub fn deinit(self: *@This()) void { + self.world.deinit(); +} diff --git a/src/scences/in_one_weekend.zig b/src/scences/in_one_weekend.zig index 1891c29..3a8364e 100644 --- a/src/scences/in_one_weekend.zig +++ b/src/scences/in_one_weekend.zig @@ -1,12 +1,14 @@ const std = @import("std"); const rayray = @import("rayray"); +const Camera = rayray.Camera; const Hittable = rayray.hittable.Hittable; const HittableList = rayray.hittable.HittableList; const Material = rayray.material.Material; const Sphere = rayray.hittable.Sphere; const zm = rayray.zmath; +camera: Camera.Options, world: HittableList, allocator: std.mem.Allocator, @@ -14,7 +16,7 @@ pub fn scene(allocator: std.mem.Allocator) !@This() { var world = HittableList.init(allocator); const material_ground = try allocator.create(Material); - material_ground.* = Material.lambertian(zm.f32x4(0.5, 0.5, 0.5, 1.0)); + 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))); const a_max = 30; @@ -39,7 +41,7 @@ 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.lambertian(albedo); + material.* = Material.lambertianS(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))); } else if (choose_mat < 0.95) { @@ -62,7 +64,7 @@ pub fn scene(allocator: std.mem.Allocator) !@This() { // try world.add(Hittable.sphere("One: Dielectric", Sphere{ .center = zm.f32x4(0, 1, 0, 0), .radius = 1, .mat = material1 })); const material2 = try allocator.create(Material); - material2.* = Material.lambertian(zm.f32x4(0.4, 0.2, 0.1, 1)); + 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))); const material3 = try allocator.create(Material); @@ -71,7 +73,19 @@ pub fn scene(allocator: std.mem.Allocator) !@This() { try world.add(Hittable.sphere("One: Dielectric", Sphere.init(zm.f32x4(0, 1, 0, 0), 1, material2))); - return .{ .allocator = allocator, .world = world }; + return .{ .allocator = allocator, .world = world, .camera = .{ + .aspect_ratio = 16.0 / 9.0, + .image_width = 400, + .samples_per_pixel = 50, + .max_depth = 50, + + .vfov = 20, + .look_from = zm.f32x4(20, 6, 6, 0), + .look_at = zm.f32x4(0, 0, 0, 0), + + .defocus_angle = 0.6, + .focus_dist = 18, + } }; } pub fn deinit(self: *@This()) void { diff --git a/src/texture.zig b/src/texture.zig new file mode 100644 index 0000000..cd86c8d --- /dev/null +++ b/src/texture.zig @@ -0,0 +1,52 @@ +const zm = @import("zmath"); + +pub const Texture = union(enum) { + solid_color: SolidColor, + checker_texture: CheckerTexture, + + pub fn value(self: *Texture, u: f32, v: f32, p: zm.Vec) zm.Vec { + switch (self.*) { + inline else => |*n| return n.value(u, v, p), + } + } +}; + +pub const SolidColor = struct { + albedo: zm.Vec, + + pub fn init(albedo: zm.Vec) SolidColor { + return SolidColor{ .albedo = albedo }; + } + + pub fn rgb(r: f32, g: f32, b: f32) SolidColor { + return init(zm.f32x4(r, g, b, 1.0)); + } + + pub fn value(self: *SolidColor, _: f32, _: f32, _: zm.Vec) zm.Vec { + return self.albedo; + } +}; + +pub const CheckerTexture = struct { + inv_scale: f32, + even: *Texture, + odd: *Texture, + + pub fn init(scale: f32, even: *Texture, odd: *Texture) CheckerTexture { + return CheckerTexture{ .inv_scale = 1 / scale, .even = even, .odd = odd }; + } + + pub fn value(self: *CheckerTexture, u: f32, v: f32, p: zm.Vec) zm.Vec { + const x = @as(i32, @intFromFloat(@floor(self.inv_scale * p[0]))); + const y = @as(i32, @intFromFloat(@floor(self.inv_scale * p[1]))); + const z = @as(i32, @intFromFloat(@floor(self.inv_scale * p[2]))); + + const is_even = @rem(x + y + z, 2) == 0; + + if (is_even) { + return self.even.value(u, v, p); + } else { + return self.odd.value(u, v, p); + } + } +}; -- 2.51.2