heman_image* heman_ops_warp_core(heman_image* img, heman_image* secondary, int seed, int octaves) { struct osn_context* ctx; open_simplex_noise(seed, &ctx); int width = img->width; int height = img->height; int nbands = img->nbands; heman_image* result = heman_image_create(width, height, nbands); heman_image* result2 = secondary ? heman_image_create(width, height, secondary->nbands) : 0; HEMAN_FLOAT invw = 1.0 / width; HEMAN_FLOAT invh = 1.0 / height; HEMAN_FLOAT inv = MIN(invw, invh); HEMAN_FLOAT aspect = (float) width / height; float gain = 0.6; float lacunarity = 2.0; float initial_amplitude = 0.05; float initial_frequency = 8.0; #pragma omp parallel for for (int y = 0; y < height; y++) { HEMAN_FLOAT* dst = result->data + y * width * nbands; for (int x = 0; x < width; x++) { float a = initial_amplitude; float f = initial_frequency; HEMAN_FLOAT* src; // This is a little hack that modulates noise according to // elevation, to prevent "swimming" at high elevations. if (nbands == 4) { src = heman_image_texel(img, x, y); HEMAN_FLOAT elev = 1 - src[3]; a *= pow(elev, 4); } float s = x * inv; float t = y * inv; float u = x * invw; float v = y * invh; for (int i = 0; i < octaves; i++) { u += NOISEX(s, t, a, f); v += aspect * NOISEY(s, t, a, f); a *= gain; f *= lacunarity; } int i = CLAMP(u * width, 0, width - 1); int j = CLAMP(v * height, 0, height - 1); src = heman_image_texel(img, i, j); for (int n = 0; n < nbands; n++) { *dst++ = *src++; } if (secondary) { src = heman_image_texel(secondary, x, y); HEMAN_FLOAT* dst2 = heman_image_texel(result2, i, j); for (int n = 0; n < secondary->nbands; n++) { *dst2++ = *src++; } } } } open_simplex_noise_free(ctx); if (secondary) { free(secondary->data); secondary->data = result2->data; free(result2); } return result; }
OsnNoise::~OsnNoise() { if (_context) { open_simplex_noise_free(_context); } }