generate noise texture and sample for randomness

This commit is contained in:
ktyl 2021-08-09 15:49:05 +01:00
parent c848616928
commit 7f84ffd551
4 changed files with 102 additions and 21 deletions

View File

@ -2,6 +2,8 @@
#include sphere.glsl #include sphere.glsl
layout(local_size_x = 1, local_size_y = 1) in; // size of local work group - 1 pixel
// TODO: do i actually need explicit location descriptors? // TODO: do i actually need explicit location descriptors?
layout (location = 1) uniform vec4 _t; layout (location = 1) uniform vec4 _t;
@ -16,14 +18,17 @@ layout (location = 8) uniform vec3 _camll;
layout (location = 9) uniform vec3 _cpos; layout (location = 9) uniform vec3 _cpos;
layout (location = 10) uniform vec3 _tpos; // target layout (location = 10) uniform vec3 _tpos; // target
const int SPHERES = 250; // 253 is the maximum?? TODO: use uniform buffer objects // 253 is the maximum?? TODO: use uniform buffer objects
const int SPHERES = 250;
layout (location = 12) uniform int _activeSpheres; layout (location = 12) uniform int _activeSpheres;
layout (location = 13) uniform Sphere _spheres[SPHERES]; layout (location = 13) uniform Sphere _spheres[SPHERES];
uniform vec4 _seed; uniform vec4 _seed;
layout(local_size_x = 1, local_size_y = 1) in; // size of local work group - 1 pixel
layout(rgba32f, binding = 0) uniform image2D img_output; // rgba32f defines internal format, image2d for random write to output texture layout(rgba32f, binding = 0) uniform image2D img_output; // rgba32f defines internal format, image2d for random write to output texture
layout(binding=1) uniform sampler2D _noise; // noise texture
const float INF = 1000.0; const float INF = 1000.0;
const float PI = 3.14159; const float PI = 3.14159;
@ -144,14 +149,34 @@ RayHit trace(Ray ray)
return hit; return hit;
} }
vec2 pixelUv()
{
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
ivec2 dims = imageSize(img_output);
vec2 uv;
uv.x = (float(pixelCoords.x * 2 - dims.x) / dims.x) * dims.x/dims.y; // account for aspect ratio
uv.y = (float(pixelCoords.y * 2 - dims.y) / dims.y);
return uv;
}
vec4 sampleNoise()
{
return texture(_noise, pixelUv());
}
float random(vec2 st) float random(vec2 st)
{ {
st += gl_GlobalInvocationID.xy; //st += gl_GlobalInvocationID.xy;
st += _seed.xy; //st += _seed.xy;
st += _seed.zw; //st += _seed.zw;
normalize(st); //normalize(st);
return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123); vec2 nuv = texture(_noise, st.xy).xy;
return fract(sin(dot(nuv,vec2(12.9898,78.233)))*43758.5453123);
} }
float sdot(vec3 x, vec3 y, float f = 1.0) float sdot(vec3 x, vec3 y, float f = 1.0)
@ -173,15 +198,17 @@ mat3 getTangentSpace(vec3 normal)
vec3 sampleHemisphere(vec3 normal) vec3 sampleHemisphere(vec3 normal)
{ {
float cosTheta = random(normal.xy); vec4 noise = sampleNoise();
float cosTheta = random(normalize(normal.xy+noise.xy));
float sinTheta = sqrt(max(0.0,1.0-cosTheta*cosTheta)); float sinTheta = sqrt(max(0.0,1.0-cosTheta*cosTheta));
float phi = 2.0*PI*random(normal.yx); float phi = 2.0*PI*random(normalize(normal.yz+noise.xw));
vec3 tangentSpaceDir = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta); vec3 tangentSpaceDir = vec3(cos(phi)*sinTheta, sin(phi)*sinTheta, cosTheta);
// convert direction from tangent space to world space // convert direction from tangent space to world space
mat3 ts = getTangentSpace(normal); mat3 ts = getTangentSpace(normal);
return ts* tangentSpaceDir; return ts * tangentSpaceDir;
} }
vec3 scatterLambert(inout Ray ray, RayHit hit) vec3 scatterLambert(inout Ray ray, RayHit hit)
@ -213,13 +240,10 @@ void main()
// get index in global work group ie xy position // get index in global work group ie xy position
ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy); ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
ivec2 dims = imageSize(img_output); // fetch image dimensions vec2 uv = pixelUv();
vec2 uv;
uv.x = (float(pixel_coords.x * 2 - dims.x) / dims.x) * dims.x/dims.y; // account for aspect ratio
uv.y = (float(pixel_coords.y * 2 - dims.y) / dims.y);
int samples = 2; int samples = 2;
int bounces = 3; int bounces = 2;
for (int i = 0; i < samples; i++) for (int i = 0; i < samples; i++)
{ {
@ -244,6 +268,8 @@ void main()
//pixel = vec4(hit.albedo,1.0); //pixel = vec4(hit.albedo,1.0);
//pixel *= (1.0-depth); //pixel *= (1.0-depth);
//pixel = texture(_noise, uv);
// output to a specific pixel in the image // output to a specific pixel in the image
imageStore(img_output, pixel_coords, pixel); imageStore(img_output, pixel_coords, pixel);
} }

View File

@ -1,4 +1,5 @@
#include "gfx.h" #include "gfx.h"
#include "random.h"
#include "stb_image.h" #include "stb_image.h"
float vertices[] = { float vertices[] = {
@ -58,6 +59,10 @@ SDL_Window* gfxInit(int width, int height)
glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &uniformLocations); glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &uniformLocations);
printf("max uniform locations %d\n", uniformLocations); printf("max uniform locations %d\n", uniformLocations);
int imageUnits;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &imageUnits);
printf("max texture image units %d\n", imageUnits);
return sdlWindow; return sdlWindow;
} }
@ -191,6 +196,38 @@ void createTextureFromFile(const char* imagePath)
stbi_image_free(data); stbi_image_free(data);
} }
// creates a noise texture in active texture 1
GLuint createNoiseTexture(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[width*height*channels];
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);
return texture;
}
GLuint createWriteOnlyTexture(int width, int height) GLuint createWriteOnlyTexture(int width, int height)
{ {
GLuint texture; GLuint texture;

View File

@ -7,12 +7,14 @@
#include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengl.h>
#include "io.h" #include "io.h"
#include "random.h"
SDL_Window* gfxInit(int width, int height); SDL_Window* gfxInit(int width, int height);
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath); unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath);
unsigned int compileComputeShaderProgram(); unsigned int compileComputeShaderProgram();
GLuint createNoiseTexture(int width, int height);
void createTextureFromFile(const char* path); void createTextureFromFile(const char* path);
GLuint createWriteOnlyTexture(int width, int height); GLuint createWriteOnlyTexture(int width, int height);
void printWorkGroupLimits(); void printWorkGroupLimits();

View File

@ -13,9 +13,14 @@ void updateUniforms(GLuint shaderProgram);
int main() int main()
{ {
randomInit();
// create a window and opengl context // create a window and opengl context
SDL_Window* window = gfxInit(WIDTH, HEIGHT); SDL_Window* window = gfxInit(WIDTH, HEIGHT);
// generate noise
GLuint noise = createNoiseTexture(WIDTH, HEIGHT);
// create a texture for the compute shader to write to // create a texture for the compute shader to write to
GLuint textureOutput = createWriteOnlyTexture(WIDTH, HEIGHT); GLuint textureOutput = createWriteOnlyTexture(WIDTH, HEIGHT);
printWorkGroupLimits(); printWorkGroupLimits();
@ -27,18 +32,21 @@ int main()
"bin/shader.vert", "bin/shader.vert",
"bin/shader.frag"); "bin/shader.frag");
glBindTexture(GL_TEXTURE_2D, noise);
int noiseLoc = glGetUniformLocation(computeProgram, "_noise");
glUniform1i(noiseLoc, noise);
// initialise quad // initialise quad
initBuffers(); initBuffers();
setVertexAttributes(); setVertexAttributes();
int frames = 0;
// render loop // render loop
while (!checkQuit()) while (!checkQuit())
{ {
glUseProgram(computeProgram);
updateUniforms(computeProgram);
// dispatch compute shader // dispatch compute shader
glUseProgram(computeProgram);
updateUniforms(computeProgram);
glDispatchCompute((GLuint)WIDTH, (GLuint)HEIGHT, 1); glDispatchCompute((GLuint)WIDTH, (GLuint)HEIGHT, 1);
// make sure we're finished writing to the texture before trying to read it // make sure we're finished writing to the texture before trying to read it
@ -46,15 +54,23 @@ int main()
// normal drawing pass // normal drawing pass
glUseProgram(quadProgram); glUseProgram(quadProgram);
glActiveTexture(GL_TEXTURE0); // use computed texture
glBindTexture(GL_TEXTURE_2D, textureOutput);
// bind texture written to by compute stage to 2d target
glBindTexture(GL_TEXTURE_2D, textureOutput);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// swip swap // swip swap
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(window);
frames++;
} }
float elapsed = now();
printf("%d frames in %f seconds (avg: %f fps)\n",
frames,
elapsed,
(float)frames/elapsed);
return 0; return 0;
} }