generate noise texture and sample for randomness
This commit is contained in:
parent
c848616928
commit
7f84ffd551
|
@ -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,10 +198,12 @@ 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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
37
src/gfx.c
37
src/gfx.c
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
28
src/main.c
28
src/main.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue