worldgen: fractal Perlin noise

This commit is contained in:
Lephenixnoir 2022-07-17 01:40:51 +01:00
parent 252ff19f2a
commit c3ae9c4942
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
1 changed files with 31 additions and 10 deletions

View File

@ -67,17 +67,19 @@ static num lerp(num x, num y, num t)
static num dot(vec2 *grid, int GRID_N, int ix, int iy, num fx, num fy)
{
vec2 g = grid[iy * GRID_N + ix];
/* Wrap the grid around to get a torus effect, so the noise does not appear
discontinuous when we repeat it during fractal sampling */
vec2 g = grid[(iy % GRID_N) * GRID_N + (ix % GRID_N)];
return (fx - num(ix)) * g.x + (fy - num(iy)) * g.y;
}
static uint8_t *perlinNoise(int N, int PERLIN_CELL_SIZE)
static int8_t *perlinNoise(int N, int PERLIN_CELL_SIZE)
{
uint8_t *noise = new uint8_t[N * N];
int8_t *noise = new int8_t[N * N];
if(!noise)
return nullptr;
int GRID_N = (N / PERLIN_CELL_SIZE) + 1;
int GRID_N = N / PERLIN_CELL_SIZE;
vec2 *grid = new vec2[GRID_N * GRID_N];
if(!grid) {
delete[] noise;
@ -104,24 +106,43 @@ static uint8_t *perlinNoise(int N, int PERLIN_CELL_SIZE)
num ry = smooth(fy - num(iy));
num v = lerp(lerp(d0, d1, rx), lerp(d2, d3, rx), ry);
noise[y * N + x] = 128 + (int)(v * num(127));
noise[y * N + x] = (int)(v * num(128));
}
delete[] grid;
return noise;
}
static int8_t samplePerlin(int8_t *noise, int N, int x, int y, int levels)
{
int8_t result = 0;
for(int i = 0; i < levels; i++) {
/* Add something depending on i to decorrelate octaves */
int wy = ((y << i) + (17 * i + 5)) % N;
int wx = ((x << i) + (13 * i + 1)) % N;
int tmp = result + (noise[wy * N + wx] >> i);
result = max(-128, min(tmp, 127));
}
return result;
}
#include <gint/display.h>
void perlinTest(void)
{
uint8_t *noise;
int time = prof_exec({ noise = perlinNoise(128, 16); });
int8_t *noise;
int N = 128;
int PERLIN_CELL_SIZE = 16;
int time = prof_exec({ noise = perlinNoise(N, PERLIN_CELL_SIZE); });
dclear(C_RED);
if(noise)
for(int y = 0; y < 128; y++)
for(int x = 0; x < 128; x++) {
int gray = noise[y * 128 + x] >> 3;
for(int y = 0; y < N; y++)
for(int x = 0; x < N; x++) {
int v = samplePerlin(noise, N, x, y, 3);
int gray = 16 + (v >> 3);
dpixel(x, y, C_RGB(gray, gray, gray));
}
dprint(2, DHEIGHT-20, C_WHITE, "time = %d ms", time / 1000);