Skip to content

Instantly share code, notes, and snippets.

@roxlu
Created November 25, 2012 22:21
Show Gist options
  • Save roxlu/4145654 to your computer and use it in GitHub Desktop.
Save roxlu/4145654 to your computer and use it in GitHub Desktop.
Blur shader 2 passing, ping pong attachments
#include <Blur.h>
#define ASSERT_BLUR_SETUP() { \
if(!is_setup) { \
printf("ERROR: not setup.\n"); \
return; \
} \
}
Blur::Blur()
:blur_vbo(0)
,blur_vao(0)
,blur_shader_v(0)
,blur_shader_h(0)
,blur_depth(0)
,fbo_w(0)
,fbo_h(0)
,is_setup(false)
,tex_uniform(0)
{
blur_tex[0] = blur_tex[1] = 0;
}
Blur::~Blur() {
}
void Blur::setup(int fboW, int fboH) {
fbo_w = fboW;
fbo_h = fboH;
setupFBO();
setupShaders();
setupVBO();
is_setup = true;
}
void Blur::setupFBO() {
glGenFramebuffers(1, &blur_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blur_fbo);
glGenRenderbuffers(1, &blur_depth);
glBindRenderbuffer(GL_RENDERBUFFER, blur_depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, fbo_w, fbo_h);
createTexture(blur_tex[0]);
createTexture(blur_tex[1]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, blur_depth);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blur_tex[0], 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, blur_tex[1], 0);
eglCheckFramebufferStatus();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Blur::setupShaders() {
GLuint blur_pass_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint blur_ver_shader = glCreateShader(GL_FRAGMENT_SHADER);
GLuint blur_hor_shader = glCreateShader(GL_FRAGMENT_SHADER);
const char* vss = BLUR_VS.c_str();
const char* hor_fss = BLUR_HOR_FS.c_str();
const char* ver_fss = BLUR_VER_FS.c_str();
glShaderSource(blur_pass_shader, 1, &vss, NULL);
glShaderSource(blur_ver_shader, 1, &ver_fss, NULL);
glShaderSource(blur_hor_shader, 1, &hor_fss, NULL);
glCompileShader(blur_pass_shader); eglGetShaderInfoLog(blur_pass_shader);
glCompileShader(blur_ver_shader); eglGetShaderInfoLog(blur_ver_shader);
glCompileShader(blur_hor_shader); eglGetShaderInfoLog(blur_hor_shader);
// Vertical blur
blur_shader_v = glCreateProgram();
glAttachShader(blur_shader_v, blur_pass_shader);
glAttachShader(blur_shader_v, blur_ver_shader);
glBindAttribLocation(blur_shader_v, 0, "a_pos");
glBindAttribLocation(blur_shader_v, 1, "a_tex");
glLinkProgram(blur_shader_v); eglGetError();
glUseProgram(blur_shader_v);
glUniform1i(glGetUniformLocation(blur_shader_v, "u_tex"), 0);
glUniform1f(glGetUniformLocation(blur_shader_v, "u_blur_size"), 1.0f/fbo_h);
// Horizontal blur
blur_shader_h = glCreateProgram();
glAttachShader(blur_shader_h, blur_pass_shader);
glAttachShader(blur_shader_h, blur_hor_shader);
glBindAttribLocation(blur_shader_h, 0, "a_pos");
glBindAttribLocation(blur_shader_h, 1, "a_tex");
glLinkProgram(blur_shader_h); eglGetError();
glUseProgram(blur_shader_h);
glUniform1i(glGetUniformLocation(blur_shader_h, "u_tex"), 0);
glUniform1f(glGetUniformLocation(blur_shader_h, "u_blur_size"), 1.0f/fbo_w);
}
void Blur::setupVBO() {
GLfloat quad[] = {
-1.0f, -1.0f, 0.0f, 0.0f, // BL
1.0f, -1.0f, 1.0f, 0.0f, // BR
1.0f, 1.0f, 1.0f, 1.0f, // TR
1.0f, 1.0f, 1.0f, 1.0f, // TR
-1.0f, 1.0f, 0.0f, 1.0f, // TL
-1.0f, -1.0f, 0.0f, 0.0f // BL
};
glGenVertexArraysAPPLE(1, &blur_vao);
glBindVertexArrayAPPLE(blur_vao);
glGenBuffers(1, &blur_vbo);
glBindBuffer(GL_ARRAY_BUFFER, blur_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 6, quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); // pos
glEnableVertexAttribArray(1); // tex
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*) 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*) (sizeof(GLfloat) * 2));
}
void Blur::bind() {
ASSERT_BLUR_SETUP();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blur_fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearColor(0.0f, 0.0f, 0.0f,1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
}
void Blur::unbind() {
ASSERT_BLUR_SETUP();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Blur::draw() {
ASSERT_BLUR_SETUP();
glBindVertexArrayAPPLE(blur_vao);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blur_fbo);
// Ping....
// Draw into ATTACHMNET 1 (blur_tex[1]), sample from blur_tex[0] ==> scene
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glUseProgram(blur_shader_h);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, blur_tex[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// Pong....
// Draw into ATTACHMENT 0 (blur_tex[0]), sample from blur_tex[1] ==> scene + horizontal blur
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glUseProgram(blur_shader_v);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, blur_tex[1]);
glDrawArrays(GL_TRIANGLES, 0, 6);
// draw full screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK_LEFT);
glBindTexture(GL_TEXTURE_2D, blur_tex[1]);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
// --------
void Blur::createTexture(GLuint& tex) {
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo_w, fbo_h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
}
#ifndef ROXLU_BLURH
#define ROXLU_BLURH
#include <roxlu/Roxlu.h>
#include <string>
const std::string BLUR_VS = "" \
"attribute vec4 a_pos;" \
"attribute vec2 a_tex;" \
"varying vec2 v_tex; " \
" " \
" void main() { " \
" gl_Position = a_pos; " \
" v_tex = a_tex; " \
" } " \
"";
// blur from: http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
const std::string BLUR_HOR_FS = "" \
" uniform sampler2D u_tex; " \
" uniform float u_blur_size; " \
" varying vec2 v_tex; " \
" " \
" void main() { " \
" vec4 sum = vec4(0.0); " \
" sum += texture2D(u_tex, vec2(v_tex.x - 4.0 * u_blur_size, v_tex.y)) * 0.05; "\
" sum += texture2D(u_tex, vec2(v_tex.x - 3.0 * u_blur_size, v_tex.y)) * 0.09; " \
" sum += texture2D(u_tex, vec2(v_tex.x - 2.0 * u_blur_size, v_tex.y)) * 0.12; " \
" sum += texture2D(u_tex, vec2(v_tex.x - u_blur_size, v_tex.y)) * 0.15; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y)) * 0.16; " \
" sum += texture2D(u_tex, vec2(v_tex.x + u_blur_size, v_tex.y)) * 0.15; " \
" sum += texture2D(u_tex, vec2(v_tex.x + 2.0 * u_blur_size, v_tex.y)) * 0.12; " \
" sum += texture2D(u_tex, vec2(v_tex.x + 3.0 * u_blur_size, v_tex.y)) * 0.09; " \
" sum += texture2D(u_tex, vec2(v_tex.x + 4.0 * u_blur_size, v_tex.y)) * 0.05; " \
" gl_FragColor = sum; " \
" } " \
"";
const std::string BLUR_VER_FS = "" \
" uniform sampler2D u_tex; " \
" uniform float u_blur_size; " \
" varying vec2 v_tex; " \
" " \
" void main() { " \
" vec4 sum = vec4(0.0); " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y - 4.0 * u_blur_size)) * 0.05; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y - 3.0 * u_blur_size)) * 0.09; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y - 2.0 * u_blur_size)) * 0.12; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y - u_blur_size)) * 0.15; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y)) * 0.16; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y + u_blur_size)) * 0.15; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y + 2.0* u_blur_size)) * 0.12; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y + 3.0* u_blur_size)) * 0.09; " \
" sum += texture2D(u_tex, vec2(v_tex.x, v_tex.y + 4.0* u_blur_size)) * 0.05; " \
" gl_FragColor = sum; " \
" } " \
"";
class Blur {
public:
Blur();
~Blur();
void setup(int fboW, int fboH);
void bind();
void unbind();
void draw();
private:
void setupFBO();
void setupVBO();
void setupShaders();
void createTexture(GLuint& tex);
private:
bool is_setup;
int fbo_w;
int fbo_h;
GLuint blur_vbo;
GLuint blur_vao;
GLuint blur_shader_v;
GLuint blur_shader_h;
GLuint blur_fbo;
GLuint blur_depth;
GLuint blur_tex[2];
GLuint tex_uniform;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment