Skip to main content
GameDev.net gamedev.net
🔒 Locked

FBO - 2D - 3D

Started by jhondoe May 3, 2008 at 5:38 AM 0 replies 3.1k views
Original Post
jhondoe
jhondoe
Hi, First the code from this great gamedev tutorial works fine. (as expected :P) So I modified it to illustrate my problem (that I have in an other program). I want to draw a 2D scene in a FBO with an attached texture. Then I want to use this texture on the 6 faces of the cube. I have just change about 5 lines at the beginning of the display callback . I do not understand why GL_PROJECTION and ortho2D are not working. (but it works if I draw a 3D scene in the FBO) Sincerely John

// FBO Example
//
// A demonstration of using an FBO in your own programs.
// Uses GLee for extension setup
// Note: This isn't meant to indicate good programming style, just act as an example
//

#include "stdafx.h"
#include "glee.h"
#include <gl/freeglut.h>
#include <cstdlib>

GLuint fbo;					// Our handle to the FBO
GLuint depthBuffer;			// Our handle to the depth render buffer
GLuint img;					// Our handle to a texture

const int width = 512;		// The hight of the texture we'll be rendering to
const int height = 512;		// The width of the texture we'll be rendering to

// Used for drawing the 3D cube with our rendered texture on it
GLfloat	xrot = 0;			// X Rotation
GLfloat	yrot = 0;			// Y Rotation
GLfloat xspeed = 0.2f;		// X Rotation Speed
GLfloat yspeed = 0.1f;		// Y Rotation Speed

void init(GLvoid)     
{

	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.2f, 0.5f);
	glClearDepth(1.0f);					
	glEnable(GL_DEPTH_TEST);			
	glDepthFunc(GL_LEQUAL);				
	glViewport(0,0,800,600);

	// Setup our FBO
	glGenFramebuffersEXT(1, &fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	// Create the render buffer for depth	
	glGenRenderbuffersEXT(1, &depthBuffer);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);

	// Now setup a texture to render to
	glGenTextures(1, &img);
	glBindTexture(GL_TEXTURE_2D, img);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, 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);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

//  The following 3 lines enable mipmap filtering and generate the mipmap data so rendering works
//	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);

	// And attach it to the FBO so we can render to it
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);

	// Attach the depth render buffer to the FBO as it's depth attachment
	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);
	

	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
		exit(1);
	
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);	// Unbind the FBO for now
}

void ShutDown(GLvoid)
{
	glDeleteFramebuffersEXT(1, &fbo);
	glDeleteRenderbuffersEXT(1, &depthBuffer);
	glDeleteTextures(1,&img);
}

void reshape(int w,int h)			
{
	glViewport( 0, 0, w, h );
	glMatrixMode(GL_PROJECTION);	
	glLoadIdentity();					
	if ( h==0 )							
		gluPerspective(80,(float)w,1.0,5000.0);
	else
		gluPerspective(80,(float)w/(float)h,1.0,5000.0);
	glMatrixMode(GL_MODELVIEW);	
	glLoadIdentity();					
}

void keyboard(unsigned char key,int x,int y)  
{
	switch(key)
	{
	case 27:				// When Escape Is Pressed...
		ShutDown();
		exit(0);			// Exit The Program
		break;				
	default:				
		break;
	}
}

void idle(void)
{
	glutPostRedisplay();
}

void display(void)   
{
	// First we bind the FBO so we can render to it
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
	
	// Save the view port and set it to the size of the texture
	glPushAttrib(GL_VIEWPORT_BIT);  // maybe GL_ALL_ATTRIB_BITS ?
	glViewport(0,0,width,height);
    //glMatrixMode(GL_PROJECTION);  //  why it does not work if uncommented ?
    glLoadIdentity();  
    gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);

	// Then render as normal
	// Today's scene is a wonderful multi-coloured spinning cube ;)
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
	glLoadIdentity();

	glTranslatef(0.0f,0.0f,-2.0f); // If GL_PROJECTION and ortho2D, I do not need to translate it to see it

    glBegin (GL_QUADS);
        glColor3f(0.0f,1.0f,0.0f);
        glVertex2f (-1.0f, -1.0f);
        glVertex2f (-1.0f, 1.0f);
        glVertex2f (1.0f, 1.0f);
        glVertex2f (1.0f, -1.0f);
    glEnd ();


	// Restore old view port and set rendering back to default frame buffer
	glPopAttrib();
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	glClearColor(0.0f, 0.0f, 0.2f, 0.5f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
	glLoadIdentity();
	// Now bind the texture to use it
	glBindTexture(GL_TEXTURE_2D, img);
//	If you enabled the mipmap filtering on setup earlier then you'll need to uncomment the line
//	below so OpenGL can generate all the mipmap data for the new main image each frame
//	glGenerateMipmapEXT(GL_TEXTURE_2D);
	glEnable(GL_TEXTURE_2D);

	glTranslatef(0.0f,0.0f,-2.0f);
	glRotatef(-xrot,1.0f,0.0f,0.0f);
	glRotatef(-yrot,0.0f,1.0f,0.0f);

	glColor4f(1.0f,1.0f,1.0f,1.0f);

	// This time it's a textured spinning cube!
	// The texture being the scene we just rendered!
	glBegin(GL_QUADS);
		// Front Face
		glNormal3f( 0.0f, 0.0f, 1.0);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, -0.5,  0.5);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5, -0.5,  0.5);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5,  0.5,  0.5);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5,  0.5,  0.5);
		// Back Face
		glNormal3f( 0.0f, 0.0f,-1.0);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5, -0.5, -0.5);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5,  0.5, -0.5);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5,  0.5, -0.5);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5, -0.5, -0.5);
		// Top Face
		glNormal3f( 0.0f, 1.0, 0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5,  0.5, -0.5);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5,  0.5,  0.5);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5,  0.5,  0.5);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5,  0.5, -0.5);
		// Bottom Face
		glNormal3f( 0.0f,-1.0, 0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5, -0.5, -0.5);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5, -0.5, -0.5);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5, -0.5,  0.5);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5, -0.5,  0.5);
		// Right face
		glNormal3f( 1.0, 0.0f, 0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5, -0.5, -0.5);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5,  0.5, -0.5);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.5,  0.5,  0.5);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.5, -0.5,  0.5);
		// Left Face
		glNormal3f(-1.0, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5, -0.5, -0.5);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.5, -0.5,  0.5);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5,  0.5,  0.5);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5,  0.5, -0.5);
	glEnd();

	glDisable(GL_TEXTURE_2D);
	
	xrot+=xspeed;
	yrot+=yspeed;

	glutSwapBuffers ( );
	// Swap The Buffers To Not Be Left With A Clear Screen
}

int _tmain(int argc, _TCHAR* argv[])
{
	
	glutInit(&argc, (char**)argv);
	glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE );		// Display Mode
	glutInitWindowSize(800,600);
	glutCreateWindow( "FrameBuffer Object Example - Press ESC to exit" );

	// GLee is used to setup all the extensions available
	if(!GLeeInit())
		exit(2);

	init();
	
	// Setup the various call back functions GLUT requires
	glutDisplayFunc     ( display );  
	glutReshapeFunc     ( reshape );
	glutKeyboardFunc    ( keyboard );
	glutIdleFunc		( idle );
	glutMainLoop        ( );			// Run the main GLUT loop for rendering

	return 0;
}







[Edited by - jhondoe on May 3, 2008 6:57:21 AM]
jhondoe
jhondoe
I found a solution :

replace the beginning of the display callback by those lines:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);    glPushAttrib(GL_VIEWPORT_BIT);    glMatrixMode(GL_PROJECTION);    glPushMatrix();    glLoadIdentity();    gluOrtho2D(0.0, width, 0.0, height);    glMatrixMode(GL_MODELVIEW);    glPushMatrix();    glLoadIdentity();    glViewport(0, 0, width, height );    glClearColor(0.0,0.0,0.0,0.0);    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glColor3f(0.5, 0.0, 0.0);    glDisable(GL_TEXTURE_2D);    glBegin (GL_QUADS);        glVertex2f ((float)width/4.0f, (float)height/4.0f);        glVertex2f ((float)3.0f*width/4.0f, (float)height/4.0f);        glVertex2f ((float)3.0f*width/4.0f, (float)3.0f*height/4.0f);        glVertex2f ((float)width/4.0f, (float)3.0f*height/4.0f);    glEnd ();    glPopMatrix();    glMatrixMode(GL_PROJECTION);    glPopMatrix();    glMatrixMode(GL_MODELVIEW);    glPopAttrib();    glPopAttrib();    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


I am not a pro so any improvement/remarks would be appreciated.

Sincerely

J.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.