This commit is contained in:
2025-11-05 13:54:55 +02:00
commit b85f911e3e
3 changed files with 133 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
#include <math.h>
#include <png.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/random.h>
float noise(float x, float y);
float linear_interpolation(float a, float b, float t);
float quintic_curve(float t);
float dot_product(float a[], float b[]);
float *pseudo_random_gradient_vector_get(float x, float y);
static unsigned char random_bytes[1024];
int main() {
int n = getrandom(random_bytes, 1024, 0);
if (n != 1024) {
fprintf(stderr, "err: getrandom didn't work out as planned\n");
return 1;
}
int width = 1024, height = 1024;
png_image img;
memset(&img, 0, sizeof(img));
img.format = PNG_FORMAT_GRAY;
img.width = width;
img.height = height;
img.version = PNG_IMAGE_VERSION;
unsigned char *buffer;
printf("PNG IMAGE SIZE: %u\n", PNG_IMAGE_SIZE(img));
buffer = malloc(PNG_IMAGE_SIZE(img));
for (int x = 0; x < height; ++x) {
for (int y = 0; y < width; ++y) {
float noise_val = noise(x * 0.05, y * 0.05);
unsigned char pixel = (unsigned char)((noise_val + 1.0f) * 127.5f);
buffer[y + x * width] = pixel;
}
}
png_image_write_to_file(&img, "noise.png", 0, buffer, 0, NULL);
free(buffer);
}
float noise(float x, float y) {
int left = floorf(x);
int top = floorf(y);
float point_in_quad_x = x - left;
float point_in_quad_y = y - top;
float *top_left_gradient = pseudo_random_gradient_vector_get(left, top);
float *top_right_gradient = pseudo_random_gradient_vector_get(left + 1, top);
float *bottom_left_gradient =
pseudo_random_gradient_vector_get(left, top + 1);
float *bottom_right_gradient =
pseudo_random_gradient_vector_get(left + 1, top + 1);
float distance_to_top_left[] = {point_in_quad_x, point_in_quad_y};
float distance_to_top_right[] = {point_in_quad_x - 1, point_in_quad_y};
float distance_to_bottom_left[] = {point_in_quad_x, point_in_quad_y - 1};
float distance_to_bottom_right[] = {point_in_quad_x - 1, point_in_quad_y - 1};
float tx1 = dot_product(distance_to_top_left, top_left_gradient);
float tx2 = dot_product(distance_to_top_right, top_right_gradient);
float bx1 = dot_product(distance_to_bottom_left, bottom_left_gradient);
float bx2 = dot_product(distance_to_bottom_right, bottom_right_gradient);
point_in_quad_x = quintic_curve(point_in_quad_x);
point_in_quad_y = quintic_curve(point_in_quad_y);
float tx = linear_interpolation(tx1, tx2, point_in_quad_x);
float bx = linear_interpolation(bx1, bx2, point_in_quad_x);
float tb = linear_interpolation(tx, bx, point_in_quad_y);
free(top_left_gradient);
free(top_right_gradient);
free(bottom_left_gradient);
free(bottom_right_gradient);
return tb;
}
float linear_interpolation(float a, float b, float t) {
return a + (b - a) * t;
}
float quintic_curve(float t) { return t * t * t * (t * (t * 6 - 15) + 10); }
float dot_product(float a[2], float b[2]) { return a[0] * b[0] + a[1] * b[1]; }
float *pseudo_random_gradient_vector_get(float x, float y) {
float *a;
a = malloc(sizeof *a * 2);
int xi = (int)x & 1023;
int yi = (int)y & 1023;
int hash = random_bytes[(random_bytes[xi] + yi) & 1023];
int v = hash & 3;
switch (v) {
case 0:
a[0] = 1;
a[1] = 0;
break;
case 1:
a[0] = -1;
a[1] = 0;
break;
case 2:
a[0] = 0;
a[1] = 1;
break;
case 3:
a[0] = 0;
a[1] = -1;
break;
}
return a;
}