Skip to content

Instantly share code, notes, and snippets.

@davertron
Created April 13, 2011 00:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save davertron/916742 to your computer and use it in GitHub Desktop.
Save davertron/916742 to your computer and use it in GitHub Desktop.
My First Attempt At Using OpenGL FBO's and Shaders
#ifdef WIN32
# include "windows.h"
#endif
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <GL/glew.h>
#include <GL/glut.h>
#include <SDL/SDL.h>
#define W_WIDTH 800
#define W_HEIGHT 600
using namespace std;
// GLOBALS
bool key[321];
int FRAMES = 0;
float FPS = 0;
time_t LAST_FRAME_TIME;
float texture_offsets[50];
GLuint frag_shader_id;
GLuint vert_shader_id;
GLuint shader_program_id;
GLuint tex_id;
GLuint fbo_id;
bool loadShaderSource(const string& filename, string &source){
std::ifstream file;
file.open(filename.c_str());
if(!file){
return false;
}
std::stringstream stream;
stream << file.rdbuf();
file.close();
source = stream.str();
return true;
}
void updateFPS(){
FRAMES++;
time_t now = time(NULL);
time_t difference = now - LAST_FRAME_TIME;
if(difference >= 1){
float percentOfSecond = 1 / difference;
LAST_FRAME_TIME = now;
FPS = percentOfSecond * FRAMES;
FRAMES = 0;
}
}
void applicationInit(){
LAST_FRAME_TIME = time(NULL);
// Seed random number generator
srand((unsigned)time(0));
// Set up kernel weights and calculate texture offsets
const int KERNEL_SIZE = 9;
const float step_w = 1.0 / W_WIDTH;
const float step_h = 1.0 / W_HEIGHT;
const GLfloat kernel_weights[KERNEL_SIZE] = {
1.0/16.0, 2.0/16.0, 1.0/16.0,
2.0/16.0, 4.0/16.0, 2.0/16.0,
1.0/16.0, 2.0/16.0, 1.0/16.0
};
const GLfloat texture_offsets[KERNEL_SIZE * 2] = {
-step_w, -step_h,
0.0, -step_h,
step_w, -step_h,
-step_w, 0.0,
0.0, 0.0,
step_w, 0.0,
-step_w, step_h,
0.0, step_h,
step_w, step_h
};
GLuint kw = glGetUniformLocation(shader_program_id, "kernel_weights");
GLuint to = glGetUniformLocation(shader_program_id, "texture_offsets");
glUseProgram(shader_program_id);
glUniform1fv(kw, 9, kernel_weights);
glUniform2fv(to, 9, texture_offsets);
glUseProgram(0);
}
bool events(){
SDL_Event event;
int keycode;
if(SDL_PollEvent(&event)){
switch(event.type){
case SDL_KEYDOWN:
keycode = event.key.keysym.sym;
switch(keycode){
case SDLK_q:
return false;
break;
}
break;
case SDL_QUIT:
return false;
break;
}
}
return true;
}
void setupProjection(){
glViewport(0, 0, W_WIDTH, W_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 20, 20, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
}
void renderBitmapString(float x, float y, float z, void *font, char *string){
char *c;
glRasterPos3f(x, y, z);
for(c=string; *c != '\0'; c++){
glutBitmapCharacter(font, *c);
}
}
void drawFPS(){
char fpsString[99];
sprintf(fpsString, "FPS: %4.2f", FPS);
glLineWidth(1.0);
glColor3f(16.0/255.0, 237.0/255.0, 5.0/255.0);
renderBitmapString(0.0, 1.0, 0.0, GLUT_BITMAP_HELVETICA_18, fpsString);
}
void drawSquares(){
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glVertex3f(3.0, 3.0, 0.0);
glVertex3f(15.0, 3.0, 0.0);
glVertex3f(15.0, 15.0, 0.0);
glVertex3f(3.0, 15.0, 0.0);
glColor3f(0.0, 1.0, 0.75);
glVertex3f(6.0, 6.0, 0.0);
glVertex3f(18.0, 6.0, 0.0);
glVertex3f(18.0, 18.0, 0.0);
glVertex3f(6.0, 18.0, 0.0);
glEnd();
}
void update(){
updateFPS();
}
void drawTexturedQuad(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, W_WIDTH, W_HEIGHT);
glOrtho(0, 1, 1, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glBindTexture(GL_TEXTURE_2D, tex_id);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 1.0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
void draw(){
setupProjection();
// Bind and render to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
drawSquares();
drawFPS();
// Unbind FBO, data is now in a texture, use our shader to blur it and
// render it to a quad
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(shader_program_id);
drawTexturedQuad();
glUseProgram(0);
}
void main_loop_function(){
while(events()){
update();
draw();
SDL_GL_SwapBuffers();
}
}
// Initialize OpenGL perspective matrix
void GL_Setup(int width, int height){
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 20, 20, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0, 0.0, 0.0, 0.0);
// Load gaussian blur shader
string gaussian_vert;
string gaussian_frag;
if(loadShaderSource("gaussian.vs", gaussian_vert) && loadShaderSource("gauss2.fs", gaussian_frag)){
const char* frag_source = gaussian_frag.c_str();
const char* vert_source = gaussian_vert.c_str();
vert_shader_id = glCreateShader(GL_VERTEX_SHADER);
frag_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
int status;
glShaderSource(vert_shader_id, 1, &vert_source, NULL);
glCompileShader(vert_shader_id);
glGetShaderiv(vert_shader_id, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
int logLength;
GLcharARB *log;
log = new GLcharARB[1024];
glGetInfoLogARB(shader_program_id, 1024, &logLength, log);
if(logLength > 0){
cout << "Shader info: " << log << endl;
exit(-1);
}
}
glShaderSource(frag_shader_id, 1, &frag_source, NULL);
glCompileShader(frag_shader_id);
glGetShaderiv(vert_shader_id, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
int logLength;
GLcharARB *log;
log = new GLcharARB[1024];
glGetInfoLogARB(shader_program_id, 1024, &logLength, log);
if(logLength > 0){
cout << "Shader info: " << log << endl;
exit(-1);
}
}
shader_program_id = glCreateProgram();
glAttachShader(shader_program_id, vert_shader_id);
glAttachShader(shader_program_id, frag_shader_id);
glLinkProgram(shader_program_id);
int logLength;
GLcharARB *log;
log = new GLcharARB[1024];
glGetProgramInfoLog(shader_program_id, 1024, &logLength, log);
if(logLength > 0){
cout << "Program info: " << log << endl;
exit(-1);
}
} else {
cout << "Could not load shader." << endl;
exit(-1);
}
// Enable texturing and create a texture object that we'll later attach to
// our FBO
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Create fbo
glGenFramebuffers(1, &fbo_id);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE){
cout << "Fucked up the framebuffer setup dude: " << status << endl;
exit(-2);
}
}
int main(int argc, char** argv){
if(SDL_Init(SDL_INIT_VIDEO) != 0){
printf("Unable to initialize SDL: %s\n", SDL_GetError());
}
const SDL_VideoInfo* info = SDL_GetVideoInfo();
int vidFlags = SDL_OPENGL;
if(info->hw_available){
vidFlags |= SDL_HWSURFACE;
} else {
vidFlags |= SDL_SWSURFACE;
}
int bpp = info->vfmt->BitsPerPixel;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_SetVideoMode(W_WIDTH, W_HEIGHT, bpp, vidFlags);
glewInit();
GL_Setup(W_WIDTH, W_HEIGHT);
glutInit(&argc, argv);
applicationInit();
main_loop_function();
return 0;
}
#define KERNEL_SIZE 9
uniform sampler2D sampler0;
uniform float kernel_weights[KERNEL_SIZE];
uniform vec2 texture_offsets[KERNEL_SIZE];
void main(void)
{
vec2 offset[KERNEL_SIZE];
int i;
vec4 sum = vec4(0.0);
for(i = 0; i < KERNEL_SIZE; i++){
vec4 tmp = texture2D(sampler0, gl_TexCoord[0].st + texture_offsets[i]);
sum += tmp * kernel_weights[i];
}
gl_FragColor = sum;
}
void main(){
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
@mizmaar3
Copy link

do you have any idea what prob is it ?

@davertron
Copy link
Author

Sorry, no, it works fine on my linux machine. If you can get some debug information, like an error or something, that would be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment