diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-03 18:14:45 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-03 18:14:45 +0100 |
| commit | 815c428dea14a6a1ea5c421c400985d0c14d473d (patch) | |
| tree | 0c7b6782753cb7c6d92df19d46abf0af39f955b9 | |
| parent | 0bd2d4eae458d9017de4e2c4e04c1c1cc5315520 (diff) | |
clean-up the procedural code a bit
| -rw-r--r-- | README.md | 9 | ||||
| -rw-r--r-- | src/procedural/generator.cc | 86 |
2 files changed, 52 insertions, 43 deletions
@@ -2,6 +2,15 @@ This is a C++ project aiming to create a cross-platform (Windows, macOS, Linux) 64-kilobyte demo. +## Quickstart + +Development setup: + +```bash +cmake -S . -B build -DDEMO_ALL_OPTIONS=ON +cmake --build build +``` + ## Project Files - `ASSET_SYSTEM.md`: Describes the custom asset packing and management system. 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); } } } |
