PDA

View Full Version : Framebuffer object + view problems



SkyLagoon
05-13-2010, 07:26 AM
Hi there. I still haven't used framebuffer objects and textures (to be drawn on a quad) long enough to understand exactly what wrong I am doing.

I managed to get it to work once before when I did a multipass rendering with a friend..but the problem then was that the view got extremely zoomed in (both the viewable objects and the skybox I'm inside).

I tried using the same code again with some minor modifications and tried to render my scene to a quad that is drawn (I bind a variable called img0 to the quad which is the texture) just to see if it works (the result should be the exact same scene I had before I used any framebuffer objects and alike) and I get the same problem again..skybox and teapots become zoomed in. I'm not sure what wrong I'm doing since I'm quite new to this.

Any help or suggestion is appreciated. Thanks

Here's the code:


#include <stdlib.h>


#include <GL/glew.h>

#include <GL/gl.h>

#include <GL/glut.h>


#include <stdio.h>
#include <time.h>
#include <sys/stat.h>

#include <math.h>

#include <iostream>



GLuint texture[5];

GLuint windowWidth = 700;
GLuint windowHeight = 700;

int mouse_old_x; //Position of the mouse
int mouse_old_y; // Position of the mouse

bool rotate;

static float xRot;
static float yRot;

GLfloat whiteSpecularLight[] = {1.0, 1.0, 1.0};
GLfloat whiteSpecularMaterial[] = {1.0, 1.0, 1.0};

GLfloat mShininess[] = {50};

GLint programObj1;
GLint programObj6;

GLint location_testTexture;
GLint location_time;
GLint location_center;

GLuint fbo;
GLuint depthbuffer;

GLuint img0; //First offscreen render
GLuint img1; //Second offscreen render

float focalDistance = -7.0f;
float focalRange = 6.0f;

GLint loc;

//Function prototypes

void light(void);
void skybox(void);
void teapots(void);
void drawQuad(void);
void init(void);

//Read shader files

char* readShaderFile(const char *filename) {
FILE *file;
struct stat st;

file = fopen(filename, "r");

if(file == NULL){
fprintf( stderr, "ERROR: Cannot open shader file!");
return 0;
}

stat(filename,&amp;st);

int bytesinfile = st.st_size;
char *buffer = (char*)malloc(bytesinfile+sizeof(char));
int bytesread = fread( buffer, 1, bytesinfile, file);
buffer[bytesread] = 0; // Terminate the string with 0
fclose(file);

return buffer;
}

//Create shaders

void createShaders() {
std::cout<< "Hej create shaaaaaaaaaaaaaaders" << std::endl;
GLint vertexShader1 = glCreateShader(GL_VERTEX_SHADER); //Create vertex shader
GLint vertexShader6 = glCreateShader(GL_VERTEX_SHADER);

const char *vertexAssembly1 = readShaderFile("first.vert"); //Read vertex shader file
const char *vertexAssembly6 = readShaderFile("fifth.vert");
glShaderSource( vertexShader1, 1, &amp;vertexAssembly1, NULL );
glShaderSource( vertexShader6, 1, &amp;vertexAssembly6, NULL );
glCompileShader( vertexShader1);
glCompileShader( vertexShader6);
free((void *)vertexAssembly1);
free((void *)vertexAssembly6);

GLint isCompiled;
glGetShaderiv( vertexShader1, GL_COMPILE_STATUS, &amp;isCompiled );

if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog(vertexShader1, 256, NULL, str);
fprintf( stderr, "Vertex shader compile error: %s\n", str);
}

glGetShaderiv( vertexShader6, GL_COMPILE_STATUS, &amp;isCompiled );

if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog(vertexShader6, 256, NULL, str);
fprintf( stderr, "Vertex shader compile error: %s\n", str);
}


GLint fragmentShader1 = glCreateShader( GL_FRAGMENT_SHADER ); //Create fragmet shader
GLint fragmentShader6 = glCreateShader( GL_FRAGMENT_SHADER );

const char *fragmentAssembly1 = readShaderFile( "first.frag" ); //Read fragment shader file
const char *fragmentAssembly6 = readShaderFile( "renderblur.frag" );
glShaderSource( fragmentShader1, 1, &amp;fragmentAssembly1, NULL );
glShaderSource( fragmentShader6, 1, &amp;fragmentAssembly6, NULL );
glCompileShader( fragmentShader1 );
glCompileShader( fragmentShader6 );
free((void *)fragmentAssembly1);
free((void *)fragmentAssembly6);

glGetShaderiv( fragmentShader1, GL_COMPILE_STATUS, &amp;isCompiled );

if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog( fragmentShader1, 256, NULL, str );
fprintf( stderr, "Fragment shader compile error: %s\n", str );
}

glGetShaderiv( fragmentShader6, GL_COMPILE_STATUS, &amp;isCompiled );
if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog( fragmentShader6, 256, NULL, str );
fprintf( stderr, "Fragment shader compile error: %s\n", str );
}

programObj1 = glCreateProgram();
programObj6 = glCreateProgram();
glAttachShader( programObj1, vertexShader1 );
glAttachShader( programObj6, vertexShader6 );
glAttachShader( programObj1, fragmentShader1 );
glAttachShader( programObj6, fragmentShader6 );

glLinkProgram( programObj1 );
glLinkProgram( programObj6 );
GLint isLinked;
glGetProgramiv( programObj1, GL_LINK_STATUS, &amp;isLinked );

if( isLinked == GL_FALSE ){
char str[256];
glGetProgramInfoLog( programObj1, 256, NULL, str );
fprintf( stderr, "Program object linking error: %s\n", str );
}

glGetProgramiv( programObj6, GL_LINK_STATUS, &amp;isLinked );

if( isLinked == GL_FALSE ){
char str[256];
glGetProgramInfoLog( programObj6, 256, NULL, str );
fprintf( stderr, "Program object linking error: %s\n", str );
}
}

//Method for deleting texture once they've been used


void FreeTexture( GLuint texture )

{

glDeleteTextures( 1, &amp;texture );

}


//Loading the textures that will be used for the skybox


GLuint LoadTexture( const char * filename, int width, int height )

{

GLuint texture;

unsigned char * data;

FILE * file;



//This code read the raw files.

file = fopen( filename, "rb" );

if ( file == NULL ) return 0;

data = (unsigned char *)malloc( width * height * 3 );

fread( data, width * height * 3, 1, file );

fclose( file );



glGenTextures( 1, &amp;texture ); //Generate texture

glBindTexture( GL_TEXTURE_2D, texture ); //Bind texture to texture array declared above

glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); //texture environment parameters



glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );



glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);



glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);



free( data ); //free the texture

return texture; //return whether it was successfull

}


//Keyboard controls


void keyboard(unsigned char key, int x, int y)

{

if(key==27) //27 is ASCI-code for ESC key

{

exit(0); //Exit the program

}

}

void processMouse(int button, int state, int x, int y)
{
if ((state == GLUT_DOWN) &amp;&amp; (button == GLUT_LEFT_BUTTON))
{
rotate=true;
}else
{
rotate=false;
}
mouse_old_x =x;
mouse_old_y =y;

}

void processMouseActiveMotion(int x, int y)
{
float weight =0.2;
if(rotate) {
xRot += (x-mouse_old_x) * weight;
yRot += (y-mouse_old_y) * weight;
}

mouse_old_x =x;
mouse_old_y =y;
}


void initFbo()
{
//Create a framebuffer object
glGenFramebuffersEXT(1, &amp;fbo); //Frame buffer
glGenRenderbuffersEXT(1, &amp;depthbuffer); //render buffer
glGenTextures(1, &amp;img0); //texture
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fbo);

//initialize texture
glBindTexture(GL_TEXTURE_2D, img0);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,windowWidth, windowHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);

//texture parameters
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_MIPMAP_LINEAR);
glGenerateMipmapEXT(GL_TEXTURE_2D);

//attach texture to framebuffer color buffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, img0,0);

//initialize depth renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DE PTH_COMPONENT24,windowWidth,windowHeight);

//attach renderbuffer to framebuffer depth buffer
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL _DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,depthbuf fer);
}

void firstPass()
{
init();
glEnable(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT);
glViewport(0,0,windowWidth, windowHeight);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glLoadIdentity();
//glOrtho(0.0,1.0,0.0,1.0,0.0,1.0);
//glUseProgram(programObj1);
//loc = glGetUniformLocation(programObj1, "focalDistance");
//glUniform1f(loc, focalDistance);
//loc = glGetUniformLocation(programObj1, "focalRange");
//glUniform1f(loc, focalRange);
light();
skybox();

teapots();
}

void blurTestPass()
{
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_DEPTH_TEST);
glDisable(GL_COLOR_MATERIAL);

glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glLoadIdentity();
glOrtho(0.0,1.0,0.0,1.0,0.0,1.0); //Testa ta bort sen
glColor4f(1.0,1.0,1.0,0.0);
glBindTexture(GL_TEXTURE_2D, img0);
glUseProgram(programObj6);
drawQuad();
glDisable(GL_TEXTURE_2D);
glUseProgram(0);
}


void skybox()

{
float quadSize = 1000.0; //Size of each quad

glPushMatrix();



glLoadIdentity(); //Loading identity matrix


gluLookAt(0.0,0.0,0.0,0.0,0.0,1.0,0.0,-1.0,0.0); //Setting up the camera for the scene. The cameras position is located in origo. This is because we want to be inside the skybox.



glPushAttrib(GL_ENABLE_BIT);

glEnable(GL_TEXTURE_2D);

glDisable(GL_LIGHTING);


glColor4f(1,1,1,1); //Set color for the quad



//Create and bind a texture for the front quad

glBindTexture(GL_TEXTURE_2D, texture[0]);

glBegin(GL_QUADS);

glTexCoord2f(0, 0); glVertex3f( quadSize, -quadSize, -quadSize );

glTexCoord2f(1, 0); glVertex3f( -quadSize, -quadSize, -quadSize );

glTexCoord2f(1, 1); glVertex3f( -quadSize, quadSize, -quadSize );

glTexCoord2f(0, 1); glVertex3f( quadSize, quadSize, -quadSize );

glEnd();



//Create and bind a texture for the left quad

glBindTexture(GL_TEXTURE_2D, texture[1]);

glBegin(GL_QUADS);

glTexCoord2f(0, 0); glVertex3f( quadSize, -quadSize, quadSize );

glTexCoord2f(1, 0); glVertex3f( quadSize, -quadSize, -quadSize );

glTexCoord2f(1, 1); glVertex3f( quadSize, quadSize, -quadSize );

glTexCoord2f(0, 1); glVertex3f( quadSize, quadSize, quadSize );

glEnd();



//Create and bind a texture for the back quad

glBindTexture(GL_TEXTURE_2D, texture[2]);

glBegin(GL_QUADS);

glTexCoord2f(0, 0); glVertex3f( -quadSize, -quadSize, quadSize );

glTexCoord2f(1, 0); glVertex3f( quadSize, -quadSize, quadSize );

glTexCoord2f(1, 1); glVertex3f( quadSize, quadSize, quadSize );

glTexCoord2f(0, 1); glVertex3f( -quadSize, quadSize, quadSize );



glEnd();



//Create and bind a texture for the right quad

glBindTexture(GL_TEXTURE_2D, texture[3]);

glBegin(GL_QUADS);

glTexCoord2f(0, 0); glVertex3f( -quadSize, -quadSize, -quadSize );

glTexCoord2f(1, 0); glVertex3f( -quadSize, -quadSize, quadSize );

glTexCoord2f(1, 1); glVertex3f( -quadSize, quadSize, quadSize );

glTexCoord2f(0, 1); glVertex3f( -quadSize, quadSize, -quadSize );

glEnd();



//Create and bind a texture for the top quad

glBindTexture(GL_TEXTURE_2D, texture[4]);

glBegin(GL_QUADS);

glTexCoord2f(0, 1); glVertex3f( -quadSize, quadSize, -quadSize );

glTexCoord2f(0, 0); glVertex3f( -quadSize, quadSize, quadSize );

glTexCoord2f(1, 0); glVertex3f( quadSize, quadSize, quadSize );

glTexCoord2f(1, 1); glVertex3f( quadSize, quadSize, -quadSize );

glEnd();



//Create and bind a texture for the bottom quad

glBindTexture(GL_TEXTURE_2D, texture[5]);

glBegin(GL_QUADS);

glTexCoord2f(0, 0); glVertex3f( -quadSize, -quadSize, -quadSize );

glTexCoord2f(0, 1); glVertex3f( -quadSize, -quadSize, quadSize );

glTexCoord2f(1, 1); glVertex3f( quadSize, -quadSize, quadSize );

glTexCoord2f(1, 0); glVertex3f( quadSize, -quadSize, -quadSize );

glEnd();



// Restore enable bits and matrix

glPopAttrib();

glPopMatrix();



//Return states

glDisable(GL_TEXTURE_2D);

}

//Enable lighting and color material of objects

void init()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
}

//Lighting properties

void light()
{
glLightfv(GL_LIGHT0, GL_SPECULAR, whiteSpecularLight);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, whiteSpecularMaterial);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mShininess);
}


//Render teapots with a rotational value depending on the movement of the mouse


void teapots()

{

//Blue teapot

glPushMatrix();

glColor4f(0.64,0.67,0.84,1.0);

glTranslatef(3.0,0.0,-14.0);
glRotatef(xRot,0.0,1.0,0.0);
glRotatef(yRot,1.0,0.0,0.0);

glutSolidTeapot(1);

glPopMatrix();



//Pink teapot

glPushMatrix();

glColor4f(0.79,0.63,0.72,1.0);

glTranslatef(1.0,0.0,-11.0);
glRotatef(xRot,0.0,1.0,0.0);
glRotatef(yRot,1.0,0.0,0.0);

glutSolidTeapot(1);

glPopMatrix();



//Green teapot

glPushMatrix();

glColor4f(0.64,0.67,0.49,1.0);

glTranslatef(-1.0,0.0,-7.0);
glRotatef(xRot,0.0,1.0,0.0);
glRotatef(yRot,1.0,0.0,0.0);

glutSolidTeapot(1);

glPopMatrix();

}

void drawQuad(void)
{
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2d(0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2d(1, 0);
glTexCoord2f( 1.0f, 1.0f);
glVertex2d(1, 1);
glTexCoord2f(0.0f, 1.0f);
glVertex2d(0, 1);
glEnd();
}



void display()

{

glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glClearDepth(1);
glLoadIdentity();
firstPass();
blurTestPass();

glutSwapBuffers(); //Swap between the two buffers

}



void reshape(int w, int h)

{

glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0,(GLfloat)w/(GLfloat)h,0.1,10000.0);
glMatrixMode(GL_MODELVIEW);
}




int main(int argc, char **argv)

{

glutInit(&amp;argc, argv); //Initialize GLUT

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA| GLUT_DEPTH); //Use a double buffer when displaying frames.

glutInitWindowSize(windowWidth, windowHeight);

glutInitWindowPosition(100, 100);



glutCreateWindow("Test");
init();
glewInit();
initFbo();


glutDisplayFunc(display);
glutIdleFunc (display);


glutReshapeFunc(reshape);

glutMouseFunc(processMouse);
glutMotionFunc(processMouseActiveMotion);


texture[0] = LoadTexture( "skylf.raw", 512, 512 );
texture[1] = LoadTexture( "skyft.raw", 512, 512 );

texture[2] = LoadTexture( "skyrt.raw", 512, 512 );
texture[3] = LoadTexture( "skybk.raw", 512, 512 );
texture[4] = LoadTexture( "skydn.raw", 512, 512 );

texture[5] = LoadTexture( "skyup.raw", 512, 512 );

glutKeyboardFunc(keyboard);



glutMainLoop(); //Start the OpenGL loop-cycle



for(int i=0; i<6; i++)

{

FreeTexture(texture[i]);

}



return 0;

}

Dark Photon
05-13-2010, 07:38 AM
Hi there. I still haven't used framebuffer objects and textures (to be drawn on a quad) long enough to understand exactly what wrong I am doing.

I managed to get it to work once before when I did a multipass rendering with a friend..but the problem then was that the view got extremely zoomed in (both the viewable objects and the skybox I'm inside).
First thing that popped into my mind was wrong glViewport. Looking at your code, you set it when rendering to FBO, but you don't reset it when rendering to window. You need to add a glViewport to your blurTestPass.

And you probably don't want to be mucking with it directly in reshape(). Store it off and use it in blurTestPass later.

Also, in your blurTestPass, you're "trying" to set up an orthographic projection (glOrtho), but you forgot to flip the MatrixMode to PROJECTION. It needs to live there, not MODELVIEW.

SkyLagoon
05-13-2010, 08:45 AM
I'm a little bit confused, just like you said I don't use any glViewport when actually rendering to the window. Do you mean that I should add the exact same glViewport that is set for my FBO? If so wouldn't it be enough by just moving the PopAttrib to the end of blurTestPass?

Or do you mean that I should move the viewport I declare in my reshape function to the blurTestpass? If so should I just put a new PushAttrb and PopAttrb in the blurTestpass?

Also when I putted a glMatrixMode(GL_PROJECTION) right before the ortographic projection the screen turned black instead.

Dark Photon
05-13-2010, 11:42 AM
I'm a little bit confused, just like you said I don't use any glViewport when actually rendering to the window. Do you mean that I should add the exact same glViewport that is set for my FBO? If so wouldn't it be enough by just moving the PopAttrib to the end of blurTestPass?

Or do you mean that I should move the viewport I declare in my reshape function to the blurTestpass?
Do whatever viewport makes sense. If your window and your FBO/texture have the same resolution and you want to draw in the same place, then using the same viewport is fine.


If so should I just put a new PushAttrb and PopAttrb in the blurTestpass?
PushAttrib/PopAttrib are deprecated. I wouldn't start getting used to them.


Also when I putted a glMatrixMode(GL_PROJECTION) right before the ortographic projection the screen turned black instead.
Guess you've got other fish to fry then. I'd trace the logic again and do some reading.