Skip to content

Commit

Permalink
Add FBO feedback sampler feature
Browse files Browse the repository at this point in the history
  • Loading branch information
gustafla committed Aug 6, 2023
1 parent 47c34e1 commit 10cd7e3
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
16 changes: 8 additions & 8 deletions shaders/shader.frag
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ uniform vec2 u_Resolution;
uniform float r_CamFov;
uniform vec3 r_CamPos;
uniform vec3 r_CamTarget;
uniform float r_MotionBlur;

uniform sampler2D u_FeedbackSampler;

#define PI 3.14159265
#define EPSILON 0.001
Expand All @@ -35,11 +38,6 @@ vec3 cameraRay() {
return normalize(vec3(FragCoord * vec2(aspectRatio(), 1.), c));
}

vec3 rotate(vec3 v, vec4 q) {
vec3 t = cross(q.xyz, v) + q.w * v;
return v + 2.*cross(q.xyz, t);
}

float sdSphere( vec3 p, float s ) {
return length(p)-s;
}
Expand Down Expand Up @@ -85,7 +83,9 @@ void main() {

vec3 normal = normal(pos);
float ndotl = max(dot(-normal, vec3(0., -1., 0)), 0.);

FragColor = vec4(normal * ndotl, 1.);
FragColor = vec4(vec3(ndotl), 1.);

vec3 finalColor = vec3(ndotl);
vec2 uv = FragCoord * 0.5 + 0.5;
vec3 previousFrameColor = texture2D(u_FeedbackSampler, uv).rgb;
FragColor = vec4(mix(finalColor, previousFrameColor, r_MotionBlur), 1.);
}
54 changes: 33 additions & 21 deletions src/demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <sync.h>

#define NOISE_SIZE 256
#define FBS 3

#define GET_VALUE(track_name) \
sync_get_val(sync_get_track(rocket, track_name), rocket_row)
Expand All @@ -25,7 +26,7 @@ static const char *vertex_shader_src =

typedef struct {
GLuint framebuffer;
GLuint framebuffer_texture;
GLuint texture;
} fbo_t;

typedef struct {
Expand All @@ -41,32 +42,29 @@ typedef struct {
program_t effect_program;
program_t post_program;
GLuint noise_texture;
fbo_t *post_fb;
fbo_t *output_fb;
fbo_t fbs[FBS];
size_t firstpass_fb_idx;
} demo_t;

static fbo_t *create_framebuffer(GLsizei width, GLsizei height) {
fbo_t *fbo = malloc(sizeof(fbo_t));
if (!fbo) {
return NULL;
}
static fbo_t create_framebuffer(GLsizei width, GLsizei height) {
fbo_t fbo = (fbo_t){0};

glGenFramebuffers(1, &fbo->framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, fbo->framebuffer);
glGenFramebuffers(1, &fbo.framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, fbo.framebuffer);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &fbo->framebuffer_texture);
glBindTexture(GL_TEXTURE_2D, fbo->framebuffer_texture);
glGenTextures(1, &fbo.texture);
glBindTexture(GL_TEXTURE_2D, fbo.texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA,
GL_HALF_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
fbo->framebuffer_texture, 0);
fbo.texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
SDL_Log("FBO not complete\n");
return NULL;
return (fbo_t){0};
}

return fbo;
Expand Down Expand Up @@ -143,8 +141,12 @@ demo_t *demo_init(int width, int height) {

demo_reload(demo);

demo->post_fb = create_framebuffer(width, height);
demo->output_fb = create_framebuffer(width, height);
for (size_t i = 0; i < FBS; i++) {
demo->fbs[i] = create_framebuffer(width, height);
if (demo->fbs[i].framebuffer == 0) {
return NULL;
}
}

glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &demo->noise_texture);
Expand Down Expand Up @@ -219,6 +221,8 @@ void set_noise_texture(demo_t *demo, GLuint program, int texture) {

void demo_render(demo_t *demo, struct sync_device *rocket, double rocket_row) {
static unsigned char noise[NOISE_SIZE * NOISE_SIZE * 4];
const size_t cur_fb_idx = demo->firstpass_fb_idx;
const size_t alt_fb_idx = cur_fb_idx ? 0 : 1;

#ifdef DEBUG
// Early return if shaders are currently unusable
Expand All @@ -244,7 +248,7 @@ void demo_render(demo_t *demo, struct sync_device *rocket, double rocket_row) {

// Effect shader ----------------------------------------------------------

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, demo->post_fb->framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, demo->fbs[cur_fb_idx].framebuffer);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, demo->width, demo->height);

Expand All @@ -256,15 +260,20 @@ void demo_render(demo_t *demo, struct sync_device *rocket, double rocket_row) {
glUniform2f(
glGetUniformLocation(demo->effect_program.handle, "u_Resolution"),
demo->width, demo->height);
set_noise_texture(demo, demo->effect_program.handle, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, demo->fbs[alt_fb_idx].texture);
glUniform1i(
glGetUniformLocation(demo->post_program.handle, "u_FeedbackSampler"),
0);
set_noise_texture(demo, demo->effect_program.handle, 1);

glBindVertexArray(demo->vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);

// Post shader ------------------------------------------------------------

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, demo->output_fb->framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, demo->fbs[2].framebuffer);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, demo->width, demo->height);

Expand All @@ -275,7 +284,7 @@ void demo_render(demo_t *demo, struct sync_device *rocket, double rocket_row) {
glUniform2f(glGetUniformLocation(demo->post_program.handle, "u_Resolution"),
demo->width, demo->height);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, demo->post_fb->framebuffer_texture);
glBindTexture(GL_TEXTURE_2D, demo->fbs[cur_fb_idx].texture);
glUniform1i(
glGetUniformLocation(demo->post_program.handle, "u_InputSampler"), 0);
set_noise_texture(demo, demo->post_program.handle, 1);
Expand All @@ -286,7 +295,7 @@ void demo_render(demo_t *demo, struct sync_device *rocket, double rocket_row) {

// Output blit ------------------------------------------------------------

glBindFramebuffer(GL_READ_FRAMEBUFFER, demo->output_fb->framebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, demo->fbs[2].framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
#ifdef DEBUG
Expand All @@ -300,6 +309,9 @@ void demo_render(demo_t *demo, struct sync_device *rocket, double rocket_row) {
#endif
glBlitFramebuffer(0, 0, w, h, x0, y0, x1, y1, GL_COLOR_BUFFER_BIT,
GL_LINEAR);

// Switch fb to keep render results in memory for feedback effects
demo->firstpass_fb_idx = alt_fb_idx;
}

void demo_deinit(demo_t *demo) {
Expand Down

0 comments on commit 10cd7e3

Please sign in to comment.