extract noise to file

This commit is contained in:
ktyl 2023-03-02 00:32:31 +00:00
parent 3a0ccfdbe8
commit 2883c69346
4 changed files with 170 additions and 181 deletions

202
src/gfx.c
View File

@ -1,5 +1,4 @@
#include "gfx.h" #include "gfx.h"
#include "random.h"
float vertices[] = { float vertices[] = {
// position color uvs // position color uvs
@ -196,184 +195,33 @@ int createTextures(int width, int height, struct Shaders shaders, struct Texture
return 0; 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) GLuint createNoiseTexture(int width, int height)
{ {
//return createWhiteNoiseTexture(width, height); // same init steps as with a regular texture
return createBlueNoiseTexture(width, height); 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) GLuint createWriteOnlyTexture(int width, int height)

View File

@ -6,11 +6,8 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengl.h>
#include <cglm/vec2.h>
#include "io.h" #include "io.h"
#include "random.h" #include "noise.h"
#include "clock.h"
struct Shaders struct Shaders
{ {

131
src/noise.c Normal file
View File

@ -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;
}
}
}

13
src/noise.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "GL/glew.h"
#include <cglm/vec2.h>
#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);