refactor shaders, implement depth buffer
This commit is contained in:
parent
c4b74458a8
commit
cdc4aea9d5
|
@ -1,2 +1,4 @@
|
||||||
const float INF = 1000.0;
|
const float INF = 17.0;
|
||||||
const float PI = 3.14159;
|
const float PI = 3.14159;
|
||||||
|
const int SAMPLES = 1;
|
||||||
|
const int BOUNCES = 4;
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
vec2 pixelUv()
|
vec2 pixelUv(ivec2 pixelCoords, ivec2 dims)
|
||||||
{
|
{
|
||||||
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
|
|
||||||
|
|
||||||
ivec2 dims = imageSize(img_output);
|
|
||||||
|
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
uv.x = (float(pixelCoords.x * 2 - dims.x) / dims.x) * dims.x/dims.y; // account for aspect ratio
|
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);
|
uv.y = (float(pixelCoords.y * 2 - dims.y) / dims.y);
|
||||||
|
|
|
@ -12,7 +12,11 @@ mat3 getTangentSpace(vec3 normal)
|
||||||
|
|
||||||
vec3 sampleHemisphere(vec3 normal)
|
vec3 sampleHemisphere(vec3 normal)
|
||||||
{
|
{
|
||||||
vec2 uv = pixelUv();
|
// TODO: make independent of this image uniform
|
||||||
|
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
ivec2 dims = imageSize(img_output);
|
||||||
|
|
||||||
|
vec2 uv = pixelUv(pixelCoords, dims);
|
||||||
uv += _seed.xy;
|
uv += _seed.xy;
|
||||||
|
|
||||||
vec4 noise = sampleNoise(uv);;
|
vec4 noise = sampleNoise(uv);;
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
layout(local_size_x = 1, local_size_y = 1) in; // size of local work group - 1 pixel
|
layout(local_size_x = 1, local_size_y = 1) in; // size of local work group - 1 pixel
|
||||||
|
|
||||||
|
// gbuffer?
|
||||||
|
layout(rgba32f, binding = 2) readonly uniform image2D _g0;
|
||||||
|
|
||||||
// final output
|
// final output
|
||||||
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
|
||||||
|
|
||||||
|
@ -35,18 +38,18 @@ void main()
|
||||||
// base pixel colour for the image
|
// base pixel colour for the image
|
||||||
vec4 pixel = vec4(0.0, 0.0, 0.0, 1.0);
|
vec4 pixel = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
vec2 uv = pixelUv();
|
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
ivec2 dims = imageSize(img_output);
|
||||||
|
|
||||||
int samples = 1;
|
vec2 uv = pixelUv(pixelCoords, dims);
|
||||||
int bounces = 4;
|
|
||||||
|
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < SAMPLES; i++)
|
||||||
{
|
{
|
||||||
// create a ray from the uv
|
// create a ray from the uv
|
||||||
Ray ray = createCameraRay(uv);
|
Ray ray = createCameraRay(uv);
|
||||||
|
|
||||||
// trace the rays path around the scene
|
// trace the rays path around the scene
|
||||||
for (int j = 0; j < bounces; j++)
|
for (int j = 0; j < BOUNCES; j++)
|
||||||
{
|
{
|
||||||
RayHit hit = trace(ray);
|
RayHit hit = trace(ray);
|
||||||
|
|
||||||
|
@ -55,7 +58,16 @@ void main()
|
||||||
if (length(ray.energy) < 0.001) break;
|
if (length(ray.energy) < 0.001) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pixel.xyz /= samples;
|
pixel.xyz /= SAMPLES;
|
||||||
|
|
||||||
|
vec4 d = imageLoad(_g0, ivec2(gl_GlobalInvocationID.xy));
|
||||||
|
float depth = d.x;
|
||||||
|
|
||||||
|
pixel.xyz = mix(pixel.xyz, vec3(0), depth);
|
||||||
|
|
||||||
|
//pixel.a = 1.0;
|
||||||
|
|
||||||
|
//pixel.xyz = texture(_g0, uv).xyz;
|
||||||
|
|
||||||
// output to a specific pixel in the image
|
// output to a specific pixel in the image
|
||||||
imageStore(img_output, ivec2(gl_GlobalInvocationID.xy), pixel);
|
imageStore(img_output, ivec2(gl_GlobalInvocationID.xy), pixel);
|
||||||
|
|
|
@ -1,3 +1,48 @@
|
||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
|
// writes first hit information into buffers to accelerate later passes
|
||||||
|
|
||||||
|
// local work group
|
||||||
|
layout(local_size_x = 1, local_size_y = 1) in;
|
||||||
|
|
||||||
|
layout (rgba32f, binding = 2) uniform image2D g0_output;
|
||||||
|
|
||||||
|
#include func.glsl
|
||||||
|
#include constants.glsl
|
||||||
|
#include time.glsl
|
||||||
#include sphere.glsl
|
#include sphere.glsl
|
||||||
|
#include ray.glsl
|
||||||
|
#include intersect.glsl
|
||||||
|
#include random.glsl
|
||||||
|
#include camera.glsl
|
||||||
|
#include image.glsl
|
||||||
|
#include scene.glsl
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// x normal.x
|
||||||
|
// y normal.y
|
||||||
|
// z normal.z
|
||||||
|
// w depth
|
||||||
|
|
||||||
|
vec4 pixel= vec4(0);
|
||||||
|
ivec2 pixelCoords = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
ivec2 dims = imageSize(g0_output);
|
||||||
|
vec2 uv = pixelUv(pixelCoords, dims);
|
||||||
|
|
||||||
|
Ray ray = createCameraRay(uv);
|
||||||
|
RayHit hit = trace(ray);
|
||||||
|
|
||||||
|
//pixel.xyz = hit.normal;
|
||||||
|
|
||||||
|
// TODO: non-linear depth
|
||||||
|
float n = 1;
|
||||||
|
float f = INF;
|
||||||
|
float z = hit.distance;
|
||||||
|
|
||||||
|
float depth = (1.0/z-1.0/n)/(1.0/n-1.0/f);
|
||||||
|
|
||||||
|
pixel.x = z/f;
|
||||||
|
|
||||||
|
imageStore(g0_output, pixelCoords, pixel);
|
||||||
|
}
|
||||||
|
|
77
src/gfx.c
77
src/gfx.c
|
@ -14,11 +14,8 @@ unsigned int indices[] = {
|
||||||
1, 2, 3
|
1, 2, 3
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_Window* sdlWindow;
|
|
||||||
SDL_GLContext* sdlContext;
|
SDL_GLContext* sdlContext;
|
||||||
|
|
||||||
GLuint compileShader(const char* path, GLenum type);
|
|
||||||
|
|
||||||
SDL_Window* gfxInit(int width, int height)
|
SDL_Window* gfxInit(int width, int height)
|
||||||
{
|
{
|
||||||
// load sdl modules
|
// load sdl modules
|
||||||
|
@ -33,7 +30,7 @@ SDL_Window* gfxInit(int width, int height)
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||||
|
|
||||||
sdlWindow = SDL_CreateWindow(
|
SDL_Window *sdlWindow = SDL_CreateWindow(
|
||||||
"oglc",
|
"oglc",
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
|
@ -62,19 +59,36 @@ SDL_Window* gfxInit(int width, int height)
|
||||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &imageUnits);
|
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &imageUnits);
|
||||||
printf("max texture image units %d\n", imageUnits);
|
printf("max texture image units %d\n", imageUnits);
|
||||||
|
|
||||||
|
printWorkGroupLimits();
|
||||||
|
|
||||||
return sdlWindow;
|
return sdlWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath)
|
int compileShaders(struct Shaders *shaders)
|
||||||
|
{
|
||||||
|
// everything is renderered onto the surface of one quad
|
||||||
|
shaders->quad = compileQuadShaderProgram("bin/shader.vert", "bin/shader.frag");
|
||||||
|
|
||||||
|
// preprass writes first-pass information into buffers for later acceleration
|
||||||
|
shaders->prepass = compileComputeShaderProgram("bin/rtpre.compute");
|
||||||
|
|
||||||
|
// lighting traces multiple bounces of light around the scene
|
||||||
|
shaders->lighting = compileComputeShaderProgram("bin/rt.compute");
|
||||||
|
|
||||||
|
// TODO: actually make sure all the shaders compile
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint compileQuadShaderProgram(const char* vsPath, const char* fsPath)
|
||||||
{
|
{
|
||||||
GLuint vs = compileShader(vsPath, GL_VERTEX_SHADER);
|
GLuint vs = compileShader(vsPath, GL_VERTEX_SHADER);
|
||||||
GLuint fs = compileShader(fsPath, GL_FRAGMENT_SHADER);
|
GLuint fs = compileShader(fsPath, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
unsigned int shaderProgram = glCreateProgram();
|
GLuint shaderProgram = glCreateProgram();
|
||||||
glAttachShader(shaderProgram, vs);
|
glAttachShader(shaderProgram, vs);
|
||||||
glAttachShader(shaderProgram, fs);
|
glAttachShader(shaderProgram, fs);
|
||||||
|
|
||||||
// TODO: check program linking success
|
// TODO: check program linking success textur
|
||||||
glLinkProgram(shaderProgram);
|
glLinkProgram(shaderProgram);
|
||||||
|
|
||||||
GLint result = GL_FALSE;
|
GLint result = GL_FALSE;
|
||||||
|
@ -99,7 +113,7 @@ unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath)
|
||||||
return shaderProgram;
|
return shaderProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int compileComputeShaderProgram(const char* computeShaderPath)
|
GLuint compileComputeShaderProgram(const char* computeShaderPath)
|
||||||
{
|
{
|
||||||
GLuint cs = compileShader(computeShaderPath, GL_COMPUTE_SHADER);
|
GLuint cs = compileShader(computeShaderPath, GL_COMPUTE_SHADER);
|
||||||
GLuint computeProgram = glCreateProgram();
|
GLuint computeProgram = glCreateProgram();
|
||||||
|
@ -160,15 +174,40 @@ void setVertexAttributes()
|
||||||
// color
|
// color
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3*sizeof(float)));
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3*sizeof(float)));
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// uv
|
// uv
|
||||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6*sizeof(float)));
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6*sizeof(float)));
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int createTextures(int width, int height, struct Shaders shaders, struct Textures* textures)
|
||||||
|
{
|
||||||
|
// generate noise
|
||||||
|
textures->noise = createNoiseTexture(width, height);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,textures->noise);
|
||||||
|
int loc = glGetUniformLocation(shaders.lighting, "_noise");
|
||||||
|
glUniform1i(loc, textures->noise);
|
||||||
|
|
||||||
|
// create a texture for the compute shader to write to
|
||||||
|
textures->target = createWriteOnlyTexture(width, height);
|
||||||
|
|
||||||
|
textures->g0 = createTexture(width, height);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// creates a noise texture in active texture 1
|
// creates a noise texture in active texture 1
|
||||||
GLuint createNoiseTexture(int width, int height)
|
GLuint createNoiseTexture(int width, int height)
|
||||||
{
|
{
|
||||||
|
|
||||||
// same init steps as with a regular texture
|
// same init steps as with a regular texture
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
glGenTextures(1, &texture);
|
glGenTextures(1, &texture);
|
||||||
|
@ -216,9 +255,27 @@ GLuint createWriteOnlyTexture(int width, int height)
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// creates an empty texture in GL_TEXTURE2 unit
|
||||||
|
GLuint createTexture(int width, int height)
|
||||||
|
{
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
//glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
// an empty image
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||||
|
glBindImageTexture(2, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
void initBuffers()
|
void initBuffers()
|
||||||
{
|
{
|
||||||
unsigned int VAO, VBO, EBO;
|
GLuint VAO, VBO, EBO;
|
||||||
glGenVertexArrays(1, &VAO); // vertex array object
|
glGenVertexArrays(1, &VAO); // vertex array object
|
||||||
glGenBuffers(1, &VBO); // vertex buffer object
|
glGenBuffers(1, &VBO); // vertex buffer object
|
||||||
glGenBuffers(1, &EBO); // element buffer object
|
glGenBuffers(1, &EBO); // element buffer object
|
||||||
|
|
35
src/gfx.h
35
src/gfx.h
|
@ -9,15 +9,46 @@
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
|
||||||
|
struct Shaders
|
||||||
|
{
|
||||||
|
GLuint quad;
|
||||||
|
GLuint prepass;
|
||||||
|
GLuint lighting;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Textures
|
||||||
|
{
|
||||||
|
// texture that ultimately gets drawn to the framebuffer
|
||||||
|
GLuint target;
|
||||||
|
|
||||||
|
// TODO: blue noise, pink noise!
|
||||||
|
// noise texture to help with randomness
|
||||||
|
GLuint noise;
|
||||||
|
|
||||||
|
// additional view space information
|
||||||
|
//
|
||||||
|
// x depth
|
||||||
|
// y -
|
||||||
|
// z -
|
||||||
|
// w -
|
||||||
|
GLuint g0;
|
||||||
|
};
|
||||||
|
|
||||||
SDL_Window* gfxInit(int width, int height);
|
SDL_Window* gfxInit(int width, int height);
|
||||||
|
|
||||||
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath);
|
int compileShaders(struct Shaders *shaders);
|
||||||
unsigned int compileComputeShaderProgram();
|
GLuint compileQuadShaderProgram(const char* vsPath, const char* fsPath);
|
||||||
|
GLuint compileComputeShaderProgram(const char* csPath);
|
||||||
|
|
||||||
|
int createTextures(int width, int height, struct Shaders shaders, struct Textures* textures);
|
||||||
GLuint createNoiseTexture(int width, int height);
|
GLuint createNoiseTexture(int width, int height);
|
||||||
|
GLuint createTexture(int width, int height);
|
||||||
GLuint createWriteOnlyTexture(int width, int height);
|
GLuint createWriteOnlyTexture(int width, int height);
|
||||||
|
GLuint compileShader(const char* path, GLenum type);
|
||||||
|
|
||||||
void printWorkGroupLimits();
|
void printWorkGroupLimits();
|
||||||
|
|
||||||
|
// quad initialisation
|
||||||
void setVertexAttributes();
|
void setVertexAttributes();
|
||||||
void initBuffers();
|
void initBuffers();
|
||||||
|
|
||||||
|
|
81
src/main.c
81
src/main.c
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
@ -5,72 +6,76 @@
|
||||||
|
|
||||||
#include "sphere.h"
|
#include "sphere.h"
|
||||||
#include "cam.h"
|
#include "cam.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
const int WIDTH = 420;
|
const int WIDTH = 420;
|
||||||
const int HEIGHT = 420;
|
const int HEIGHT = 420;
|
||||||
|
|
||||||
void updateUniforms(GLuint shaderProgram);
|
void updateUniforms(GLuint shaderProgram);
|
||||||
|
|
||||||
struct TextureIDs
|
SDL_Window *window;
|
||||||
{
|
|
||||||
GLuint output; // the texture that ultimately gets rendered
|
|
||||||
GLuint noise;
|
|
||||||
} textureIds;
|
|
||||||
|
|
||||||
int main()
|
struct Shaders shaders;
|
||||||
|
struct Textures textures;
|
||||||
|
|
||||||
|
void initialise()
|
||||||
{
|
{
|
||||||
printf("GL_TEXTURE0: %d\n", GL_TEXTURE0);
|
window = gfxInit(WIDTH, HEIGHT);
|
||||||
printf("GL_TEXTURE1: %d\n", GL_TEXTURE1);
|
|
||||||
|
|
||||||
randomInit();
|
randomInit();
|
||||||
|
|
||||||
// create a window and opengl context
|
|
||||||
SDL_Window* window = gfxInit(WIDTH, HEIGHT);
|
|
||||||
|
|
||||||
// compile shader programs
|
|
||||||
unsigned int computeProgram = compileComputeShaderProgram(
|
|
||||||
"bin/rt.compute");
|
|
||||||
unsigned int quadProgram = compileQuadShaderProgram(
|
|
||||||
"bin/shader.vert",
|
|
||||||
"bin/shader.frag");
|
|
||||||
|
|
||||||
// generate noise
|
|
||||||
textureIds.noise = createNoiseTexture(WIDTH, HEIGHT);
|
|
||||||
glBindTexture(GL_TEXTURE_2D,textureIds.noise);
|
|
||||||
int noiseLoc = glGetUniformLocation(computeProgram, "_noise");
|
|
||||||
glUniform1i(noiseLoc, textureIds.noise);
|
|
||||||
|
|
||||||
// create a texture for the compute shader to write to
|
|
||||||
textureIds.output = createWriteOnlyTexture(WIDTH, HEIGHT);
|
|
||||||
printWorkGroupLimits();
|
|
||||||
|
|
||||||
// initialise quad
|
// initialise quad
|
||||||
initBuffers();
|
initBuffers();
|
||||||
setVertexAttributes();
|
setVertexAttributes();
|
||||||
|
|
||||||
int frames = 0;
|
// compile shader programs
|
||||||
// render loop
|
compileShaders(&shaders);
|
||||||
while (!checkQuit())
|
createTextures(WIDTH, HEIGHT, shaders, &textures);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
initialise();
|
||||||
|
|
||||||
|
int frames;
|
||||||
|
for (frames = 0; !checkQuit(); frames++)
|
||||||
{
|
{
|
||||||
// dispatch compute shader
|
GLuint shader;
|
||||||
glUseProgram(computeProgram);
|
|
||||||
updateUniforms(computeProgram);
|
// prepass
|
||||||
|
// TODO: write output to different texture than main output
|
||||||
|
shader = shaders.prepass;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textures.g0);
|
||||||
|
glUseProgram(shader);
|
||||||
|
updateUniforms(shader);
|
||||||
|
glDispatchCompute((GLuint)WIDTH, (GLuint)HEIGHT, 1);
|
||||||
|
|
||||||
|
// make sure we're finished writing to the texture before trying to read it
|
||||||
|
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||||
|
|
||||||
|
// dispatch compute shaders
|
||||||
|
shader = shaders.lighting;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textures.target);
|
||||||
|
glUseProgram(shader);
|
||||||
|
updateUniforms(shader);
|
||||||
|
//int loc = glGetUniformLocation(shader, "_g0");
|
||||||
|
//glUniform1i(loc, textures.g0);
|
||||||
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
|
||||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||||
|
|
||||||
// normal drawing pass
|
// normal drawing pass
|
||||||
glUseProgram(quadProgram);
|
shader = shaders.quad;
|
||||||
|
glUseProgram(shader);
|
||||||
|
|
||||||
// bind texture written to by compute stage to 2d target
|
// bind texture written to by compute stage to 2d target
|
||||||
glBindTexture(GL_TEXTURE_2D, textureIds.output);
|
|
||||||
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();
|
float elapsed = now();
|
||||||
|
|
Loading…
Reference in New Issue