Navigation Menu

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

Hi

im trying to run your code but getting error :-s
on RELEASE: MSVCRT.lib(crtexe.obj) : error LNK2001: unresolved external symbol _main
on DEBUG: MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

googled allot but unable to fix it

plateform: win7, VC++ 2010 express

@davertron
Copy link
Author

I think I was having that issue at one point and can't quite remember exactly how I fixed it, but it has something to do with the type of the program you have it set to. I believe it should be built as a windows console application, NOT a normal windows application. I believe you can also fix it by going to the properties of your project and telling it what the entry point of the application is (i.e. it's trying to start your program by looking for something else when it should be looking for main).

Google around a bit and if you still can't fix it let me know.

@davertron
Copy link
Author

Also, I just updated the code so that I calculate texture offsets and kernel weights in the main program instead of the shader, since they only need to be calculated once.

@mizmaar3
Copy link

Hi

yes all i got from googling is to change Properties>linker>system>SubSystem to "Console"... but its already console in my project
I've tried this code as new win32 console app as well, with both PRE COMPILED HEADER and and EMPTY PROJECT just in case if that was a problem, but getting same error.

@mizmaar3
Copy link

how can i change the "entry point of the application" ?

@davertron
Copy link
Author

Actually, what might be happening is you might not be adding the correct settings for linking with SDL. When I get home I'll boot up my windows machine and let you know what I have set, but I do remember now that when using SDL you have to make sure you include all of the SDL libs and headers and everything correctly or else you'll get this error.

@mizmaar3
Copy link

as far as i know, my SDL header linking is correct
please explain if their is something special in linking

@davertron
Copy link
Author

What I was thinking of was make sure you have both SDL.lib AND SDLmain.lib. I didn't have SDLmain.lib initially, and I was getting the same error. I have those specified in my Project Properties -> Configuration Properties -> Linker -> Input -> Additional Dependencies.

@davertron
Copy link
Author

Also, I seem to have Configuration Properties -> Linker -> System -> Subsystem set to "Windows", not "Console" as I mentioned above, you might want to give that a shot.

@mizmaar3
Copy link

Hello

I was busy somewhere else. I've tried this today it works.. but straing thing happen, the output window just come and disappear
I've tries system("pause); to stop screen but getting same result.
any idea why im getting this ?

@davertron
Copy link
Author

Sounds like you're probably getting a segfault or something, can you see what the output is?

@mizmaar3
Copy link

cant see anything.. white window just blink and disappear

@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