summaryrefslogtreecommitdiff
path: root/src/procedural/generator.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-03 18:14:45 +0100
committerskal <pascal.massimino@gmail.com>2026-02-03 18:14:45 +0100
commit815c428dea14a6a1ea5c421c400985d0c14d473d (patch)
tree0c7b6782753cb7c6d92df19d46abf0af39f955b9 /src/procedural/generator.cc
parent0bd2d4eae458d9017de4e2c4e04c1c1cc5315520 (diff)
clean-up the procedural code a bit
Diffstat (limited to 'src/procedural/generator.cc')
-rw-r--r--src/procedural/generator.cc86
1 files changed, 43 insertions, 43 deletions
diff --git a/src/procedural/generator.cc b/src/procedural/generator.cc
index 9a52e8d..12dcb56 100644
--- a/src/procedural/generator.cc
+++ b/src/procedural/generator.cc
@@ -7,6 +7,10 @@
namespace procedural {
+// Smoothstep
+constexpr float smooth(float x) { return x * x * (3.f - 2.f * x); }
+constexpr float mix(float a, float b, float t) { return (a * (1.0f - t) + b * t); }
+
// Simple smooth noise generator (Value Noise-ish)
// Params[0]: Seed
// Params[1]: Frequency (Scale)
@@ -18,44 +22,41 @@ void gen_noise(uint8_t* buffer, int w, int h, const float* params,
}
// Create a small lattice of random values
- int lattice_w = (int)ceil(freq);
- int lattice_h = (int)ceil(freq);
+ const int lattice_w = (int)ceil(freq);
+ const int lattice_h = (int)ceil(freq);
std::vector<float> lattice(lattice_w * lattice_h);
for (float& v : lattice) {
v = (float)rand() / RAND_MAX;
}
+ const float scale_u = 1.f * (lattice_w - 1) / w;
+ const float scale_v = 1.f * (lattice_h - 1) / h;
for (int y = 0; y < h; ++y) {
+ const float v = scale_v * y;
+ const int ly = (int)floor(v);
+ const int ly_next = (ly + 1) % lattice_h; // Wrap
+ const float* const n0 = &lattice[ly * lattice_w];
+ const float* const n1 = &lattice[ly_next * lattice_w];
+ float fv = smooth(v - ly);
+ uint8_t* const dst = &buffer[y * w * 4];
for (int x = 0; x < w; ++x) {
- float u = (float)x / w * (lattice_w - 1);
- float v = (float)y / h * (lattice_h - 1);
-
- int lx = (int)floor(u);
- int ly = (int)floor(v);
- int lx_next = (lx + 1) % lattice_w;
- int ly_next = (ly + 1) % lattice_h; // Wrap
-
- float fu = u - lx;
- float fv = v - ly;
-
- // Smoothstep
- fu = fu * fu * (3.0f - 2.0f * fu);
- fv = fv * fv * (3.0f - 2.0f * fv);
+ float u = scale_u * x;
+ const int lx = (int)floor(u);
+ const int lx_next = (lx + 1) % lattice_w;
+ float fu = smooth(u - lx);
- float n00 = lattice[ly * lattice_w + lx];
- float n10 = lattice[ly * lattice_w + lx_next];
- float n01 = lattice[ly_next * lattice_w + lx];
- float n11 = lattice[ly_next * lattice_w + lx_next];
+ float n00 = n0[lx];
+ float n10 = n0[lx_next];
+ float n01 = n1[lx];
+ float n11 = n1[lx_next];
- float noise = (1.0f - fv) * ((1.0f - fu) * n00 + fu * n10) +
- fv * ((1.0f - fu) * n01 + fu * n11);
+ const float noise = mix(mix(n00, n10, fu), mix(n01, n11, fu), fv);
- uint8_t val = (uint8_t)(noise * 255.0f);
- int idx = (y * w + x) * 4;
- buffer[idx + 0] = val; // R
- buffer[idx + 1] = val; // G
- buffer[idx + 2] = val; // B
- buffer[idx + 3] = 255; // A
+ const uint8_t val = (uint8_t)(noise * 255.0f);
+ dst[4 * x + 0] = val; // R
+ dst[4 * x + 1] = val; // G
+ dst[4 * x + 2] = val; // B
+ dst[4 * x + 3] = 255; // A
}
}
}
@@ -95,22 +96,23 @@ void make_periodic(uint8_t* buffer, int w, int h, const float* params,
if (ratio > 0.5f)
ratio = 0.5f;
- int bx = (int)(w * ratio);
- int by = (int)(h * ratio);
+ const int bx = (int)(w * ratio);
+ const int by = (int)(h * ratio);
+ const float scale_x = 1. / bx;
+ const float scale_y = 1. / by;
// X pass: blend right edge into left edge
for (int y = 0; y < h; ++y) {
for (int x = 0; x < bx; ++x) {
- float t = (float)x / bx;
- t = t * t * (3.0f - 2.0f * t); // Smoothstep
+ const float t = smooth(scale_x * x);
- int idx_dst = (y * w + x) * 4;
- int idx_src = (y * w + (w - bx + x)) * 4;
+ const int idx_dst = (y * w + x) * 4;
+ const int idx_src = (y * w + (w - bx + x)) * 4;
for (int c = 0; c < 3; ++c) {
- float v_dst = buffer[idx_dst + c];
- float v_src = buffer[idx_src + c];
- buffer[idx_dst + c] = (uint8_t)(v_src * (1.0f - t) + v_dst * t);
+ const float v_dst = buffer[idx_dst + c];
+ const float v_src = buffer[idx_src + c];
+ buffer[idx_dst + c] = (uint8_t)mix(v_src, v_dst, t);
}
}
// Copy left edge back to right edge to ensure perfect pixel match?
@@ -136,16 +138,14 @@ void make_periodic(uint8_t* buffer, int w, int h, const float* params,
// Y pass
for (int x = 0; x < w; ++x) {
for (int y = 0; y < by; ++y) {
- float t = (float)y / by;
- t = t * t * (3.0f - 2.0f * t);
-
- int idx_dst = (y * w + x) * 4;
- int idx_src = ((h - by + y) * w + x) * 4;
+ const float t = smooth(scale_y * y);
+ const int idx_dst = (y * w + x) * 4;
+ const int idx_src = ((h - by + y) * w + x) * 4;
for (int c = 0; c < 3; ++c) {
float v_dst = buffer[idx_dst + c];
float v_src = buffer[idx_src + c];
- buffer[idx_dst + c] = (uint8_t)(v_src * (1.0f - t) + v_dst * t);
+ buffer[idx_dst + c] = (uint8_t)mix(v_src, v_dst, t);
}
}
}