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,&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, &vertexAssembly1, NULL );
glShaderSource( vertexShader6, 1, &vertexAssembly6, NULL );
glCompileShader( vertexShader1);
glCompileShader( vertexShader6);
free((void *)vertexAssembly1);
free((void *)vertexAssembly6);
GLint isCompiled;
glGetShaderiv( vertexShader1, GL_COMPILE_STATUS, &isCompiled );
if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog(vertexShader1, 256, NULL, str);
fprintf( stderr, "Vertex shader compile error: %s
", str);
}
glGetShaderiv( vertexShader6, GL_COMPILE_STATUS, &isCompiled );
if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog(vertexShader6, 256, NULL, str);
fprintf( stderr, "Vertex shader compile error: %s
", 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, &fragmentAssembly1, NULL );
glShaderSource( fragmentShader6, 1, &fragmentAssembly6, NULL );
glCompileShader( fragmentShader1 );
glCompileShader( fragmentShader6 );
free((void *)fragmentAssembly1);
free((void *)fragmentAssembly6);
glGetShaderiv( fragmentShader1, GL_COMPILE_STATUS, &isCompiled );
if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog( fragmentShader1, 256, NULL, str );
fprintf( stderr, "Fragment shader compile error: %s
", str );
}
glGetShaderiv( fragmentShader6, GL_COMPILE_STATUS, &isCompiled );
if(isCompiled == GL_FALSE){
char str[256];
glGetShaderInfoLog( fragmentShader6, 256, NULL, str );
fprintf( stderr, "Fragment shader compile error: %s
", 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, &isLinked );
if( isLinked == GL_FALSE ){
char str[256];
glGetProgramInfoLog( programObj1, 256, NULL, str );
fprintf( stderr, "Program object linking error: %s
", str );
}
glGetProgramiv( programObj6, GL_LINK_STATUS, &isLinked );
if( isLinked == GL_FALSE ){
char str[256];
glGetProgramInfoLog( programObj6, 256, NULL, str );
fprintf( stderr, "Program object linking error: %s
", str );
}
}
//Method for deleting texture once they've been used
void FreeTexture( GLuint texture )
{
glDeleteTextures( 1, &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, &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) && (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, &fbo); //Frame buffer
glGenRenderbuffersEXT(1, &depthbuffer); //render buffer
glGenTextures(1, &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_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, img0,0);
//initialize depth renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,windowWidth,windowHeight);
//attach renderbuffer to framebuffer depth buffer
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,depthbuffer);
}
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(&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;
}