From 2883c693465116ebfc1bb9e7ef72ce0ca41cfb04 Mon Sep 17 00:00:00 2001 From: ktyl Date: Thu, 2 Mar 2023 00:32:31 +0000 Subject: [PATCH] extract noise to file --- src/gfx.c | 202 +++++++--------------------------------------------- src/gfx.h | 5 +- src/noise.c | 131 ++++++++++++++++++++++++++++++++++ src/noise.h | 13 ++++ 4 files changed, 170 insertions(+), 181 deletions(-) create mode 100644 src/noise.c create mode 100644 src/noise.h diff --git a/src/gfx.c b/src/gfx.c index 803ace3..740d11f 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -1,5 +1,4 @@ #include "gfx.h" -#include "random.h" float vertices[] = { // position color uvs @@ -196,184 +195,33 @@ int createTextures(int width, int height, struct Shaders shaders, struct Texture return 0; } -// creates a noise texture in active texture 1 -GLuint createWhiteNoiseTexture(int width, int height) -{ - // same init steps as with a regular texture - GLuint texture; - glGenTextures(1, &texture); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_REPEAT); - - int channels = 4; // rgba - int length = width*height*channels; - printf("generating %d random floats\n", length); - - float* data = (float*)malloc(length*sizeof(float)); - - for (int i = 0; i < length; i++) - { - data[i] = randomFloat(); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data); - glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); - glGenerateMipmap(GL_TEXTURE_2D); - - free(data); - - return texture; -} - -void generateBlueNoisePoints(vec2* points, int m, int n) -{ - float start = now(); - float elapsed; - int candidatesTested = 0; - - struct Candidate - { - vec2 pos; - // distance to closest point already in pattern - float distance; - }; - - for (int i = 0; i < n; i++) - { - // generate a bunch of candidates - int count = m * i; - struct Candidate candidates[count]; - - for (int j = 0; j < count; j++) - { - struct Candidate* c = &candidates[j]; - - c->pos[0] = randomFloat(); - c->pos[1] = randomFloat(); - // the largest distance we should expect is sqrt(2), - // so pick a maximum larger than that - c->distance = 1.5; - - // get the distance of the closest point already in the pattern - for (int k = 0; k < i; k++) - { - float distance = glm_vec2_distance(c->pos, points[k]); - if (distance < c->distance) - { - c->distance = distance; - } - } - - candidatesTested += i; - - float killAfter = 10.0; - elapsed = now() - start; - if (elapsed > killAfter) - { - printf("noise generation took too long, exiting\n"); - exit(1); - } - } - - // of our candidates, now determine which of them has the furthest - // closest-distance - int furthest = -1; - float furthestDistance = 0.0; - for (int j = 0; j < count; j++) - { - if (candidates[j].distance > furthestDistance) - { - furthest = j; - furthestDistance = candidates[j].distance; - } - } - - glm_vec2_copy(candidates[furthest].pos, points[i]); - } - - elapsed = now() - start; - printf("generated %d blue noise (m=%d) points from %d candidates in %fs\n", - n, - m, - candidatesTested, - elapsed); -} - -GLuint createBlueNoiseTexture(int width, int height) -{ - // same init steps as with a regular texture - GLuint texture; - glGenTextures(1, &texture); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_REPEAT); - - int channels = 4; // rgba - int length = width*height*channels; - //printf("generating %d random floats\n", length); - printf("generating blue noise\n"); - - float* data = (float*)malloc(length*sizeof(float)); - - // blue noise gen parameters - int m = 10; // roughly controls the evenness...? - int n = 100; // number of points to generate - - // for each channel - for (int channel = 0; channel < channels; channel++) - { - // generate a bunch of points - vec2 points[n]; - generateBlueNoisePoints(points, m, n); - - for (int i = 0; i < width*height; i++) - { - int pixelIdx = i; - int x = pixelIdx % width; - int y = pixelIdx / width; - float u = x / (float)width; - float v = y / (float)height; - vec2 pixel = {u,v}; - - float value = 0.0f; - int componentIdx = i * channels + channel; - for (int j = 0; j < n; j++) - { - float d = glm_vec2_distance(points[j], pixel); - //value += 1.0f / (d*d); - - float r = 0.01; - if (d < r) - { - data[componentIdx] = 1.0; - } - } - //data[componentIdx] = value / (float)n; - } - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data); - glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); - glGenerateMipmap(GL_TEXTURE_2D); - - free(data); - - return texture; -} - GLuint createNoiseTexture(int width, int height) { - //return createWhiteNoiseTexture(width, height); - return createBlueNoiseTexture(width, height); + // same init steps as with a regular texture + GLuint texture; + glGenTextures(1, &texture); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_REPEAT); + + int channels = 4; // rgba + int length = width*height*channels; + float* data = (float*)malloc(length*sizeof(float)); + + //writeWhiteNoiseToTexture(data, width, height); + writeBlueNoiseToTexture(data, width, height); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, data); + glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); + glGenerateMipmap(GL_TEXTURE_2D); + + free(data); + + return texture; } GLuint createWriteOnlyTexture(int width, int height) diff --git a/src/gfx.h b/src/gfx.h index b83c652..b911c56 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -6,11 +6,8 @@ #include #include -#include - #include "io.h" -#include "random.h" -#include "clock.h" +#include "noise.h" struct Shaders { diff --git a/src/noise.c b/src/noise.c new file mode 100644 index 0000000..21abda7 --- /dev/null +++ b/src/noise.c @@ -0,0 +1,131 @@ +#include "noise.h" + +void writeWhiteNoiseToTexture(float* data, int width, int height) +{ + int channels = 4; // rgba + int length = width*height*channels; + + printf("generating %d random floats\n", length); + for (int i = 0; i < length; i++) + { + data[i] = randomFloat(); + } +} + +void generateBlueNoisePoints(vec2* points, int m, int n) +{ + float start = now(); + float elapsed; + int candidatesTested = 0; + + struct Candidate + { + vec2 pos; + // distance to closest point already in pattern + float distance; + }; + + for (int i = 0; i < n; i++) + { + // generate a bunch of candidates + int count = m * i; + struct Candidate candidates[count]; + + for (int j = 0; j < count; j++) + { + struct Candidate* c = &candidates[j]; + + c->pos[0] = randomFloat(); + c->pos[1] = randomFloat(); + // the largest distance we should expect is sqrt(2), + // so pick a maximum larger than that + c->distance = 1.5; + + // get the distance of the closest point already in the pattern + for (int k = 0; k < i; k++) + { + float distance = glm_vec2_distance(c->pos, points[k]); + if (distance < c->distance) + { + c->distance = distance; + } + } + + candidatesTested += i; + + float killAfter = 10.0; + elapsed = now() - start; + if (elapsed > killAfter) + { + printf("noise generation took too long (%fs), exiting\n", elapsed); + exit(1); + } + } + + // of our candidates, now determine which of them has the furthest + // closest-distance + int furthest = -1; + float furthestDistance = 0.0; + for (int j = 0; j < count; j++) + { + if (candidates[j].distance > furthestDistance) + { + furthest = j; + furthestDistance = candidates[j].distance; + } + } + + glm_vec2_copy(candidates[furthest].pos, points[i]); + } + + elapsed = now() - start; + printf("generated %d blue noise (m=%d) points from %d candidates in %fs\n", + n, + m, + candidatesTested, + elapsed); +} + +void writeBlueNoiseToTexture(float* data, int width, int height) +{ + printf("generating blue noise\n"); + int channels = 4; + + // blue noise gen parameters + int m = 10; // roughly controls the evenness...? + int n = 100; // number of points to generate + + // for each channel + for (int channel = 0; channel < channels; channel++) + { + // generate a bunch of points + vec2 points[n]; + generateBlueNoisePoints(points, m, n); + + for (int i = 0; i < width*height; i++) + { + int pixelIdx = i; + int x = pixelIdx % width; + int y = pixelIdx / width; + float u = x / (float)width; + float v = y / (float)height; + vec2 pixel = {u,v}; + + //float value = 0.0f; + int componentIdx = i * channels + channel; + for (int j = 0; j < n; j++) + { + float d = glm_vec2_distance(points[j], pixel); + //value += 1.0f / (d*d); + + float r = 0.01; + if (d < r) + { + data[componentIdx] = 1.0; + } + } + //data[componentIdx] = value / (float)n; + } + } +} + diff --git a/src/noise.h b/src/noise.h new file mode 100644 index 0000000..54a6310 --- /dev/null +++ b/src/noise.h @@ -0,0 +1,13 @@ +#pragma once + +#include "GL/glew.h" +#include + +#include "io.h" +#include "random.h" +#include "clock.h" + +void writeWhiteNoiseToTexture(float* data, int width, int height); + +void generateBlueNoisePoints(vec2* points, int m, int n); +void writeBlueNoiseToTexture(float* data, int width, int height);