#include #include #include namespace { constexpr int SIZE = 256; double octaves(SimplexNoise1234& simplex, double x, double y, int layers, double persistence, double frequency) { double ampl = 1; double maxval = 0; double val = 0; for (int i = 0; i < layers; i++) { val += simplex.noise(x * frequency, y * frequency) * ampl; maxval += ampl; ampl *= persistence; frequency *= 2; } return val / maxval; } uint8_t data[SIZE * SIZE]; double split_point = 0; double direction = 0.5; double ease_f(double n) { return pow(n, 0.7); } double ease_g(double n) { return pow(n, 2); } double prime(double (*fn)(double), double n) { constexpr double DELTA = 0.001; return (fn(n + DELTA) - fn(n)) / DELTA; } double ease(double n) { const double fprime = prime(ease_f, n); const double gprime = prime(ease_g, n); const double scale = (fprime / gprime) * (ease_g(1) - ease_g(split_point)) + ease_f(split_point); if (n < split_point) { return ease_f(n) / scale; } return (fprime / gprime * (ease_g(n) - ease_g(split_point)) + ease_f(split_point)) / scale; } uint32_t color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return (r << 0) | (g << 8) | (b << 16) | (a << 24); } int pick_pal(uint8_t height) { if (height > 20) { return 0; } if (height > 8) { return 1; } return 2; } void init(sprstk* instance, void* userdata) { sprstk_palette pal = {}; const uint8_t ALPHA = 0xAA; for (int i = 0; i < 28; i++) { uint8_t val = 0x55 / (16.2f - i / 2.0f) + 0x11; pal.colors[i] = color(val, val, val, ALPHA); } for (int i = 28; i < 32; i++) { uint8_t val = 0x50 / (32.0f - i) + 0xA0; pal.colors[i] = color(val, val, val, ALPHA); } sprstk_set_palette(instance, 0, &pal); for (int i = 0; i < 16; i++) { pal.colors[i] = color(0x70 / (5.0f - i / 4.0f), 0x35 / (5.0f - i / 4.0f), 0, ALPHA); } for (int i = 16; i < 32; i++) { pal.colors[i] = color(0x05 / (8.5f - i / 2.5f) + 0x15, 0x40 / (8.5f - i / 2.5f) + 0x0, 0, ALPHA); } sprstk_set_palette(instance, 1, &pal); for (int i = 0; i < 8; i++) { pal.colors[i] = color(0x20 / (8 - i) + 0x10, 0x40 / (8 - i) + 0x20, 0xB0 / (8 - i) + 0x40, ALPHA); } sprstk_set_palette(instance, 2, &pal); sprstk_set_scale(instance, 1.0f); } void update(sprstk* instance, float dt, float* userdata) { *userdata += dt / 2; sprstk_set_angle(instance, *userdata); double direction_modifier = 1 - 1.9 * fabs(0.5 - split_point); split_point += direction_modifier * direction * dt; if (split_point < 0) { direction *= -1; split_point = 0; } if (split_point > 1) { direction *= -1; split_point = 1; } SimplexNoise1234 simplex; for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { double value = octaves(simplex, i, j, 6, 0.4, 1.0 / 128.0); data[i + j * SIZE] = 30 * ease((value + 1) / 2) + 1; } } sprstk_clear(instance); for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { sprstk_tile_info info = {}; info.position = { i - SIZE / 2, j - SIZE / 2 }; info.layers = data[i + SIZE * j]; info.layer_modifiers = { 0, 24, 4 / 255.0f }; info.palette_index = pick_pal(data[i + SIZE * j]); sprstk_put(instance, info); } } } } int main() { float data = 0; sprstk* instance = sprstk_new({.init = init, .update = (sprstk_update_fn)update}, &data); sprstk_run(instance); sprstk_del(instance); return 0; }