aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/rtw
diff options
context:
space:
mode:
Diffstat (limited to 'src/rtw')
-rw-r--r--src/rtw/perlin.zig59
-rw-r--r--src/rtw/texture.zig20
2 files changed, 79 insertions, 0 deletions
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));
+ }
+};