generate noise texture and sample for randomness
This commit is contained in:
parent
c848616928
commit
7f84ffd551
|
@ -2,6 +2,8 @@
|
|||
|
||||
#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?
|
||||
layout (location = 1) uniform vec4 _t;
|
||||
|
||||
|
@ -16,14 +18,17 @@ layout (location = 8) uniform vec3 _camll;
|
|||
layout (location = 9) uniform vec3 _cpos;
|
||||
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 = 13) uniform Sphere _spheres[SPHERES];
|
||||
|
||||
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(binding=1) uniform sampler2D _noise; // noise texture
|
||||
|
||||
const float INF = 1000.0;
|
||||
const float PI = 3.14159;
|
||||
|
@ -144,14 +149,34 @@ RayHit trace(Ray ray)
|
|||
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)
|
||||
{
|
||||
st += gl_GlobalInvocationID.xy;
|
||||
st += _seed.xy;
|
||||
st += _seed.zw;
|
||||
normalize(st);
|
||||
//st += gl_GlobalInvocationID.xy;
|
||||
//st += _seed.xy;
|
||||
//st += _seed.zw;
|
||||
//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)
|
||||
|
@ -173,15 +198,17 @@ mat3 getTangentSpace(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 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);
|
||||
|
||||
// convert direction from tangent space to world space
|
||||
mat3 ts = getTangentSpace(normal);
|
||||
return ts* tangentSpaceDir;
|
||||
return ts * tangentSpaceDir;
|
||||
}
|
||||
|
||||
vec3 scatterLambert(inout Ray ray, RayHit hit)
|
||||
|
@ -213,13 +240,10 @@ void main()
|
|||
// get index in global work group ie xy position
|
||||
ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
ivec2 dims = imageSize(img_output); // fetch image dimensions
|
||||
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);
|
||||
vec2 uv = pixelUv();
|
||||
|
||||
int samples = 2;
|
||||
int bounces = 3;
|
||||
int bounces = 2;
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
{
|
||||
|
@ -244,6 +268,8 @@ void main()
|
|||
//pixel = vec4(hit.albedo,1.0);
|
||||
//pixel *= (1.0-depth);
|
||||
|
||||
//pixel = texture(_noise, uv);
|
||||
|
||||
// output to a specific pixel in the image
|
||||
imageStore(img_output, pixel_coords, pixel);
|
||||
}
|
||||
|
|
37
src/gfx.c
37
src/gfx.c
|
@ -1,4 +1,5 @@
|
|||
#include "gfx.h"
|
||||
#include "random.h"
|
||||
#include "stb_image.h"
|
||||
|
||||
float vertices[] = {
|
||||
|
@ -58,6 +59,10 @@ SDL_Window* gfxInit(int width, int height)
|
|||
glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &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;
|
||||
}
|
||||
|
||||
|
@ -191,6 +196,38 @@ void createTextureFromFile(const char* imagePath)
|
|||
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 texture;
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
#include <SDL2/SDL_opengl.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "random.h"
|
||||
|
||||
SDL_Window* gfxInit(int width, int height);
|
||||
|
||||
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath);
|
||||
unsigned int compileComputeShaderProgram();
|
||||
|
||||
GLuint createNoiseTexture(int width, int height);
|
||||
void createTextureFromFile(const char* path);
|
||||
GLuint createWriteOnlyTexture(int width, int height);
|
||||
void printWorkGroupLimits();
|
||||
|
|
28
src/main.c
28
src/main.c
|
@ -13,9 +13,14 @@ void updateUniforms(GLuint shaderProgram);
|
|||
|
||||
int main()
|
||||
{
|
||||
randomInit();
|
||||
|
||||
// create a window and opengl context
|
||||
SDL_Window* window = gfxInit(WIDTH, HEIGHT);
|
||||
|
||||
// generate noise
|
||||
GLuint noise = createNoiseTexture(WIDTH, HEIGHT);
|
||||
|
||||
// create a texture for the compute shader to write to
|
||||
GLuint textureOutput = createWriteOnlyTexture(WIDTH, HEIGHT);
|
||||
printWorkGroupLimits();
|
||||
|
@ -27,18 +32,21 @@ int main()
|
|||
"bin/shader.vert",
|
||||
"bin/shader.frag");
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, noise);
|
||||
int noiseLoc = glGetUniformLocation(computeProgram, "_noise");
|
||||
glUniform1i(noiseLoc, noise);
|
||||
|
||||
// initialise quad
|
||||
initBuffers();
|
||||
setVertexAttributes();
|
||||
|
||||
int frames = 0;
|
||||
// render loop
|
||||
while (!checkQuit())
|
||||
{
|
||||
glUseProgram(computeProgram);
|
||||
|
||||
updateUniforms(computeProgram);
|
||||
|
||||
// dispatch compute shader
|
||||
glUseProgram(computeProgram);
|
||||
updateUniforms(computeProgram);
|
||||
glDispatchCompute((GLuint)WIDTH, (GLuint)HEIGHT, 1);
|
||||
|
||||
// make sure we're finished writing to the texture before trying to read it
|
||||
|
@ -46,15 +54,23 @@ int main()
|
|||
|
||||
// normal drawing pass
|
||||
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);
|
||||
|
||||
// swip swap
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue