diff options
Diffstat (limited to 'src/procedural/generator.cc')
| -rw-r--r-- | src/procedural/generator.cc | 119 |
1 files changed, 112 insertions, 7 deletions
diff --git a/src/procedural/generator.cc b/src/procedural/generator.cc index 7c165db..a2a383b 100644 --- a/src/procedural/generator.cc +++ b/src/procedural/generator.cc @@ -4,6 +4,7 @@ #include "procedural/generator.h" #include <cmath> #include <cstdlib> +#include <vector> namespace procedural { @@ -94,9 +95,6 @@ bool gen_perlin(uint8_t* buffer, int w, int h, const float* params, // Params[1]: Frequency (Scale) bool gen_noise(uint8_t* buffer, int w, int h, const float* params, int num_params) { - if (num_params > 0 && params[0] == -1337.0f) - return false; - const float seed = (num_params > 0) ? params[0] : 0.0f; const float freq = (num_params > 1) ? params[1] : 4.0f; @@ -191,16 +189,123 @@ bool make_periodic(uint8_t* buffer, int w, int h, const float* params, return true; } -#if !defined(DEMO_STRIP_ALL) -// Test-only: 256x256 noise generator -bool gen_noise_256(uint8_t* buffer, int w, int h, const float* params, +// Plasma: classic sine-sum color texture +// Params[0]: time/seed, Params[1]: frequency multiplier +bool gen_plasma(uint8_t* buffer, int w, int h, const float* params, + int num_params) { + const float time = (num_params > 0) ? params[0] : 0.0f; + const float freq = (num_params > 1) ? params[1] : 2.0f; + + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + const float nx = (float)x / (float)w * freq; + const float ny = (float)y / (float)h * freq; + + float v = sinf(nx * 6.2832f + time); + v += sinf(ny * 6.2832f + time * 1.3f); + v += sinf((nx + ny) * 3.1416f + time * 0.7f); + v += sinf(sqrtf(nx * nx + ny * ny) * 6.2832f + time); + v = v * 0.125f + 0.5f; + + // Map value to RGB via 120-degree phase-shifted sines + const float kTau = 6.2832f; + const float kPhase = 2.0944f; // 2*pi/3 + const int idx = (y * w + x) * 4; + buffer[idx + 0] = (uint8_t)(fminf(fmaxf(sinf(v * kTau) * 0.5f + 0.5f, 0.0f), 1.0f) * 255.0f); + buffer[idx + 1] = (uint8_t)(fminf(fmaxf(sinf(v * kTau + kPhase) * 0.5f + 0.5f, 0.0f), 1.0f) * 255.0f); + buffer[idx + 2] = (uint8_t)(fminf(fmaxf(sinf(v * kTau + 2.0f * kPhase) * 0.5f + 0.5f, 0.0f), 1.0f) * 255.0f); + buffer[idx + 3] = 255; + } + } + return true; +} + +// Voronoi (Worley) cellular noise +// Params[0]: cell scale, Params[1]: mode (0=F1, 1=F2, 2=F2-F1), Params[2]: seed +bool gen_voronoi(uint8_t* buffer, int w, int h, const float* params, + int num_params) { + const float scale = (num_params > 0) ? params[0] : 4.0f; + const int mode = (num_params > 1) ? (int)params[1] : 2; + const float seed = (num_params > 2) ? params[2] : 0.0f; + + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + const float px = (float)x / (float)w * scale; + const float py = (float)y / (float)h * scale; + const float cell_x = floorf(px); + const float cell_y = floorf(py); + + float f1 = 1e10f, f2 = 1e10f; + + for (int dy = -1; dy <= 1; ++dy) { + for (int dx = -1; dx <= 1; ++dx) { + const float cx = cell_x + dx; + const float cy = cell_y + dy; + const float fx = cx + hash_2f(cx + seed, cy + seed * 1.37f); + const float fy = cy + hash_2f(cx + seed * 1.13f, cy + seed * 0.97f); + const float ddx = px - fx; + const float ddy = py - fy; + const float dist2 = ddx * ddx + ddy * ddy; + + if (dist2 < f1) { f2 = f1; f1 = dist2; } + else if (dist2 < f2) { f2 = dist2; } + } + } + + float value; + if (mode == 0) value = sqrtf(f1) * 1.5f; + else if (mode == 1) value = sqrtf(f2) * 1.2f; + else value = (sqrtf(f2) - sqrtf(f1)) * 3.0f; + + value = fminf(fmaxf(value, 0.0f), 1.0f); + const uint8_t uval = (uint8_t)(value * 255.0f); + const int idx = (y * w + x) * 4; + buffer[idx + 0] = uval; + buffer[idx + 1] = uval; + buffer[idx + 2] = uval; + buffer[idx + 3] = 255; + } + } + return true; +} + +// Normal map: post-process converting grayscale R channel to RGB normals +// Params[0]: strength +bool gen_normalmap(uint8_t* buffer, int w, int h, const float* params, int num_params) { - return gen_noise(buffer, w, h, params, num_params); + const float strength = (num_params > 0) ? params[0] : 4.0f; + + std::vector<float> height(w * h); + for (int i = 0; i < w * h; ++i) { + height[i] = buffer[i * 4] / 255.0f; + } + + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + const float hL = height[y * w + (x - 1 + w) % w]; + const float hR = height[y * w + (x + 1) % w]; + const float hD = height[((y - 1 + h) % h) * w + x]; + const float hU = height[((y + 1) % h) * w + x]; + + const float dx = (hR - hL) * strength; + const float dy = (hU - hD) * strength; + const float len = sqrtf(dx * dx + dy * dy + 1.0f); + + const int idx = (y * w + x) * 4; + buffer[idx + 0] = (uint8_t)((-dx / len * 0.5f + 0.5f) * 255.0f); + buffer[idx + 1] = (uint8_t)((-dy / len * 0.5f + 0.5f) * 255.0f); + buffer[idx + 2] = (uint8_t)((1.0f / len * 0.5f + 0.5f) * 255.0f); + buffer[idx + 3] = 255; + } + } + return true; } +#if !defined(DEMO_STRIP_ALL) // Test-only: Failing generator bool gen_fail(uint8_t* buffer, int w, int h, const float* params, int num_params) { + (void)buffer; (void)w; (void)h; (void)params; (void)num_params; return false; } #endif |
