diff options
| author | nsfisis <nsfisis@gmail.com> | 2022-12-09 00:02:09 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2022-12-09 00:02:09 +0900 |
| commit | d1a300610db20107af89d57824d5596531037435 (patch) | |
| tree | bcd9595f609171150ad8b208e502209d71cbd4b5 | |
| parent | 86914985b77ddf5d6d3a3dd6c13deed9d906a471 (diff) | |
| download | RayTracingInOneWeekend.zig-d1a300610db20107af89d57824d5596531037435.tar.gz RayTracingInOneWeekend.zig-d1a300610db20107af89d57824d5596531037435.tar.zst RayTracingInOneWeekend.zig-d1a300610db20107af89d57824d5596531037435.zip | |
5.1
| -rw-r--r-- | src/main.zig | 23 | ||||
| -rw-r--r-- | src/rtw/perlin.zig | 59 | ||||
| -rw-r--r-- | src/rtw/texture.zig | 20 |
3 files changed, 101 insertions, 1 deletions
diff --git a/src/main.zig b/src/main.zig index e0e5702..e2553b5 100644 --- a/src/main.zig +++ b/src/main.zig @@ -162,6 +162,22 @@ fn generateTwoSpheres(rng: Random, allocator: anytype) !Hittable { return .{ .list = .{ .objects = hittable_objects } }; } +fn generateTwoPerlinSpheres(rng: Random, allocator: anytype) !Hittable { + var hittable_objects = ArrayList(Hittable).init(allocator); + + const perlin = Texture.makeNoise(rng); + var mat1 = try allocator.create(Material); + var mat2 = try allocator.create(Material); + + mat1.* = .{ .diffuse = .{ .albedo = perlin } }; + mat2.* = .{ .diffuse = .{ .albedo = perlin } }; + + try hittable_objects.append(makeSphere(.{ .x = 0, .y = -1000, .z = 0 }, 1000, mat1)); + try hittable_objects.append(makeSphere(.{ .x = 0, .y = 2, .z = 0 }, 2, mat2)); + + return .{ .list = .{ .objects = hittable_objects } }; +} + fn generateRandomScene(rng: Random, allocator: anytype) !Hittable { var hittable_objects = ArrayList(Hittable).init(allocator); @@ -243,7 +259,7 @@ pub fn main() !void { const samples_per_pixel = 50; const max_depth = 50; - const scene = 2; + const scene = 3; // World var world: Hittable = undefined; @@ -263,6 +279,11 @@ pub fn main() !void { lookFrom = .{ .x = 13, .y = 2, .z = 3 }; lookAt = .{ .x = 0, .y = 0, .z = 0 }; vFov = 20.0; + } else if (scene == 3) { + world = try generateTwoPerlinSpheres(rng, allocator); + lookFrom = .{ .x = 13, .y = 2, .z = 3 }; + lookAt = .{ .x = 0, .y = 0, .z = 0 }; + vFov = 20.0; } defer world.deinit(allocator); diff --git a/src/rtw/perlin.zig b/src/rtw/perlin.zig new file mode 100644 index 0000000..df5de76 --- /dev/null +++ b/src/rtw/perlin.zig @@ -0,0 +1,59 @@ +const rand = @import("rand.zig"); +const Random = rand.Random; +const randomReal01 = rand.randomReal01; +const randomInt = rand.randomInt; +const Point3 = @import("vec.zig").Point3; + +pub const Perlin = struct { + const POINT_COUNT = 256; + + randomNoise: [POINT_COUNT]f64, + permX: [POINT_COUNT]usize, + permY: [POINT_COUNT]usize, + permZ: [POINT_COUNT]usize, + + pub fn init(rng: Random) Perlin { + var perlin = Perlin{ + .randomNoise = undefined, + .permX = undefined, + .permY = undefined, + .permZ = undefined, + }; + + var i: usize = 0; + while (i < POINT_COUNT) : (i += 1) { + perlin.randomNoise[i] = randomReal01(rng); + } + perlinGeneratePerm(rng, &perlin.permX); + perlinGeneratePerm(rng, &perlin.permY); + perlinGeneratePerm(rng, &perlin.permZ); + + return perlin; + } + + pub fn noise(perlin: Perlin, p: Point3) f64 { + const i = @intCast(usize, @floatToInt(i32, 4.0 * p.x) & 255); + const j = @intCast(usize, @floatToInt(i32, 4.0 * p.y) & 255); + const k = @intCast(usize, @floatToInt(i32, 4.0 * p.z) & 255); + + return perlin.randomNoise[perlin.permX[i] ^ perlin.permY[j] ^ perlin.permZ[k]]; + } + + fn perlinGeneratePerm(rng: Random, p: []usize) void { + var i: usize = 0; + while (i < POINT_COUNT) : (i += 1) { + p[i] = i; + } + permute(rng, p, POINT_COUNT); + } + + fn permute(rng: Random, p: []usize, n: usize) void { + var i = n - 1; + while (i > 0) : (i -= 1) { + const target = randomInt(usize, rng, 0, i); + const tmp = p[i]; + p[i] = p[target]; + p[target] = tmp; + } + } +}; diff --git a/src/rtw/texture.zig b/src/rtw/texture.zig index 47c3c4f..63b8f46 100644 --- a/src/rtw/texture.zig +++ b/src/rtw/texture.zig @@ -2,15 +2,20 @@ const std = @import("std"); const Color = @import("vec.zig").Color; const Vec3 = @import("vec.zig").Vec3; +const rgb = @import("vec.zig").rgb; +const Random = @import("rand.zig").Random; +const Perlin = @import("perlin.zig").Perlin; const TextureTag = enum { solid, checker, + noise, }; pub const Texture = union(TextureTag) { solid: SolidTexture, checker: CheckerTexture, + noise: NoiseTexture, pub fn makeSolid(color: Color) Texture { return .{ .solid = .{ .color = color } }; @@ -24,10 +29,15 @@ pub const Texture = union(TextureTag) { ) }; } + pub fn makeNoise(rng: Random) Texture { + return .{ .noise = .{ .perlin = Perlin.init(rng) } }; + } + pub fn value(tx: Texture, u: f64, v: f64, p: Vec3) Color { return switch (tx) { TextureTag.solid => |solidTx| solidTx.value(u, v, p), TextureTag.checker => |checkerTx| checkerTx.value(u, v, p), + TextureTag.noise => |noiseTx| noiseTx.value(u, v, p), }; } }; @@ -70,3 +80,13 @@ pub const CheckerTexture = struct { return if (sines < 0) tx.odd.value(u, v, p) else tx.even.value(u, v, p); } }; + +pub const NoiseTexture = struct { + perlin: Perlin, + + fn value(tx: NoiseTexture, u: f64, v: f64, p: Vec3) Color { + _ = u; + _ = v; + return rgb(1, 1, 1).mul(tx.perlin.noise(p)); + } +}; |
