how to render to texture?

hi,guy!
there are some quetions about using user-define framebuffer.
i want to render some graphics to a texture,but when i call glClear(GL_COLOR_BUFFER_BIT),that Framebuffer background color becomes white,and texture is disappeared.this result is wrong if i don’t call glClear(GL_COLOR_BUFFER_BIT).i want that user-define framebuffer’background color to be the texture at begin rendering any times,how should i do?do i need to call glFramebufferTexture2D() at any times rendering?thanks!please view the code as following:


             glUseProgram(program2);
             glBindFramebuffer(GL_FRAMEBUFFER,myFramebuffer);
            glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            glViewport(0,0,600,600);
            glActiveTexture(GL_TEXTURE0);
            glEnable(GL_TEXTURE_2D);
		     glBindTexture(GL_TEXTURE_2D, texId);

            glutWireTeapot(0.5);
			//glDrawArrays(GL_QUADS,0,4);
             glUseProgram(program);
             glUniform1i(UniformDiffuse,0);
	        glActiveTexture(GL_TEXTURE0);
	        glEnable(GL_TEXTURE_2D);
	        glBindTexture(GL_TEXTURE_2D,texId);

             glBindFramebuffer(GL_FRAMEBUFFER,0);
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            glViewport(0,0,600,600);
           glBindVertexArray(arraybuffer);
           glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexbuffer);
            glDrawArrays(GL_QUADS,0,4);

            glActiveTexture(GL_TEXTURE0);
		     glBindTexture(GL_TEXTURE_2D, 0);

try this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

its work for me :wink:

I’m afraid I have no idea really what your asking, and your code is just as confused as your question.

Usually you would set the framebuffer clear colour to black so that what you draw to the texture(framebuffer) is the result of your draw commands and nothing else.

Your code is a real mess. Your binding shaders

glUseProgram(program);
within the framebuffer and then not drawing anything. So what’s the point?

thanks for your reply! it doesn’t work for me. just see a white quad. :stuck_out_tongue:

i want to draw a teapot on the texture,and draw a quad by the texture. what should i do? thanks!

i cant understand what you try to do in your code but what you need to do is write this before the render:
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, yourframebuffer);
and this after the render:
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
try to re-orginaize your code.

i do it by following your way,but it’s the same wrong.please have a look my code:


    //Create texture

    GLuint texId=LoadTexture("kueken256-rgb8.tga");
    if(texId==0)
    {
        return 0;
    }


    //create FrameBuffer
    GLuint framebuffer;
    glGenFramebuffersEXT(1,&framebuffer);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,framebuffer);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,texId,0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
    if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)!=GL_FRAMEBUFFER_COMPLETE_EXT)
    {
        return 0;
    }



//////////////////////////////////////////////////////////////////////////


    /* program main loop */
    while (!bQuit)
    {
        /* check for messages */
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            /* handle or dispatch messages */
            if (msg.message == WM_QUIT)
            {
                bQuit = TRUE;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        else
        {

            
            //draw a teapot on the texture
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,framebuffer);
            glViewport(0,0,600,600);
            glClearColor( 1, 1, 0, 1 );
	        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	        glutWireTeapot(0.5);
           
           //draw a quad on screen
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
	        glActiveTexture(GL_TEXTURE0);
	        glEnable(GL_TEXTURE_2D);
	        glBindTexture(GL_TEXTURE_2D,texId);
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
            glViewport(0,0,600,600);
            glBegin(GL_QUADS);
             glTexCoord2f(0.0,0.0);
             glVertex3d(1.0,1.0,0.0);

             glTexCoord2f(1.0,0.0);
             glVertex3d(-1.0,1.0,0.0);

             glTexCoord2f(1.0,1.0);
             glVertex3d(-1.0,-1.0,0.0);

             glTexCoord2f(0.0,1.0);
             glVertex3d(1.0,-1.0,0.0);
            glEnd();

            glActiveTexture(GL_TEXTURE0);
		     glBindTexture(GL_TEXTURE_2D, 0);
            SwapBuffers(hDC);
        }
    }

    /* shutdown OpenGL */
    DisableOpenGL(hwnd, hDC, hRC);

    /* destroy the window explicitly */
    DestroyWindow(hwnd);

    return msg.wParam;
}

what kind of projection matrix are you using when rendering:

  1. the teapot
  2. the quad

Looks like you are rendering a tiny little quad

      glBegin(GL_QUADS);
         glTexCoord2f(0.0,0.0);
         glVertex3d(1.0,1.0,0.0);
         glTexCoord2f(1.0,0.0);
         glVertex3d(-1.0,1.0,0.0);
         glTexCoord2f(1.0,1.0);
         glVertex3d(-1.0,-1.0,0.0);
         glTexCoord2f(0.0,1.0);
         glVertex3d(1.0,-1.0,0.0);
        glEnd();

becuase you have not used glOrtho to setup a “2D” projection.

i had set projection elsewhere,like this:


	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45,1.0,0.1,10);
	gluLookAt(0.0,0.0,-4.0, 0.0, 0.0, 3.0, 0.0, 1.0, 0.0);
	glMatrixMode(GL_MODELVIEW);

i couldn’t see the texture image,just could see a while teapot and a yellow quad when running the program. i mean that i want to draw a while teapot on the image at first,then map the image drawn to the quad.

For initialization I prefer to use SDL:



SDL_Init(SDL_INIT_EVERYTHING);

SDL_WM_SetCaption("Next Game", NULL);

SDL_SetVideoMode(600, 400, 32, SDL_OPENGL);

glClearColor(0,0,0,1); 

glViewport(0,0,600,400);

glShadeModel(GL_SMOOTH);

glMatrixMode(GL_PROJECTION);
 
glLoadIdentity();

glDisable(GL_DEPTH_TEST);

return 0;
}


This is my function to load textures “Thanks Red…youtube”

I hope this get you some light
(Sorry if it did not fit on screen) .



//Could be a header or included on main.cpp after preprocesor 
  section.


GLuint LoadTexture( const string &fileName )
{
  SDL_Surface *image = IMG_Load( fileName.c_str() );
 
  SDL_DisplayFormatAlpha(image);
 
  unsigned object(0);
 
  glGenTextures(1, &object);
 
  glBindTexture(GL_TEXTURE_2D, object);
 
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,    
                  GL_LINEAR);

  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,  
                  GL_LINEAR);
 
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,   
                  GL_CLAMP_TO_EDGE);
  
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,  
                  GL_CLAMP_TO_EDGE);
   
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image -> w, image ->  
               h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image ->              
               pixels);
 
  //Free surface
  SDL_FreeSurface(image);
 
  return object;
}

Then for Wrapping the object with the texture.




//main.cpp Before the main loop:

unsigned int texname = LoadTexture("Directory of the image");


//Sum cordinates and measures:

float myX = 300;
float myY = 250;
float width = 100;
float height = 100;


//On the drawing zone, usually within main loop but after event    
  handling.


 glPushMatrix(); //Start Phase

 glOrtho(0,600,400,0,-1,1);
  
 glEnable(GL_TEXTURE_2D);
 glBindTexture(GL_TEXTURE_2D, texname);  
 
 glBegin(GL_QUADS);
  

 //We set the cordinates of the texture and also we draw/render 
   the object


 glTexCoord2d(0,0); glVertex2f(myX, myY);
 glTexCoord2d(1,0); glVertex2f(myX + width, myY);
 glTexCoord2d(1,1); glVertex2f(myX + width, myY + height);
 glTexCoord2d(0,1); glVertex2f(myX, myY + height);
 

 glEnd();
 
 glDisable(GL_TEXTURE_2D);
 
 glPopMatrix();
 
 SDL_GL_SwapBuffers();   





i mean that i want to draw a while teapot on the image at first,then map the image drawn to the quad.

You mean you want to use the off-screen FBO texture as a source texture when rendering to the quad?

Simple, just bind it.
glBindTexture(GL_TEXTURE_2D, FBO_TexID);

where FBO_TexID is the texture object attached to the framebuffer (assuming you did create a Framebuffer with colour attachments rather than colour renderbuffers).

yes.i do it like that,but i fail. please check my code. has any problem?thank you!


 //Create texture

    GLuint texId=LoadTexture("kueken256-rgb8.tga");
    if(texId==0)
    {
        return 0;
    }


    //create FrameBuffer
    GLuint framebuffer;
    glGenFramebuffersEXT(1,&framebuffer);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,framebuffer);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,texId,0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
    if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)!=GL_FRAMEBUFFER_COMPLETE_EXT)
    {
        return 0;
    }



//////////////////////////////////////////////////////////////////////////


    /* program main loop */
    while (!bQuit)
    {
        /* check for messages */
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            /* handle or dispatch messages */
            if (msg.message == WM_QUIT)
            {
                bQuit = TRUE;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        else
        {

            
            //draw a teapot on the texture
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,framebuffer);
            glViewport(0,0,600,600);
            glClearColor( 1, 1, 0, 1 );
	        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	        glutWireTeapot(0.5);
           
           //draw a quad on screen
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
	        glActiveTexture(GL_TEXTURE0);
	        glEnable(GL_TEXTURE_2D);
	        glBindTexture(GL_TEXTURE_2D,texId);
            glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
            glViewport(0,0,600,600);
            glBegin(GL_QUADS);
             glTexCoord2f(0.0,0.0);
             glVertex3d(1.0,1.0,0.0);

             glTexCoord2f(1.0,0.0);
             glVertex3d(-1.0,1.0,0.0);

             glTexCoord2f(1.0,1.0);
             glVertex3d(-1.0,-1.0,0.0);

             glTexCoord2f(0.0,1.0);
             glVertex3d(1.0,-1.0,0.0);
            glEnd();

            glActiveTexture(GL_TEXTURE0);
		     glBindTexture(GL_TEXTURE_2D, 0);
            SwapBuffers(hDC);
        }
    }

    /* shutdown OpenGL */
    DisableOpenGL(hwnd, hDC, hRC);

    /* destroy the window explicitly */
    DestroyWindow(hwnd);

    return msg.wParam;

i do it like that,but i fail.

What happens? What do you see?
How do you know the FBO rendering actually happens?

Why don’t you create a depth buffer (depth render buffer) for your RTT?
If you want examples, they are at http://www.opengl.org/wiki/GL_EXT_framebuffer_object

What happens? What do you see?
How do you know the FBO rendering actually happens?

I render a teapot to the texture,then render a quad to the colorbuffer by mapping the texture,and see a yellow quad and a white teapot,but can’t see the texture image.if I don’t call the glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ) in the FBO rendering code segment,I can see a quad with the texture image and a mess white teapot.

Here is some code I use for framebuffer. Perhaps it will help understand.


LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        //standard windows callback function.  I initGL here after it's created
        //don't have to follow this way
	switch(message) {
		case WM_CREATE:
			hDC = GetDC(hwnd);
			windowCreated=true;
			initGL();
			break;
        }
}
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow) {
        ..//Create window and all that
        ..//
        while (1) {
            drawScene(); // I use threads so simplifying this loop.  Code the loop how you like
        }
} 



GLuint fbo[1], fbtex[1];
int initGL(void) {
	//...
        createFramebuffer(fbo[0], fbtex[0]);
        createFramebuffer(fbo[1], fbtex[1]);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void drawScene(void) {
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[0]); // bind the first frame buffer
	glBindTexture(GL_TEXTURE_2D, backTexture);  //bind the texture you want to draw your scene with

        //draw your stuff on the frame buffer
        glPushMatrix();
        glTranslatef(currentX,currentY,currentZ);
        //..
        //draw how you wish here gl_begin/gl_end or vbo or arrays etc
        //end of drawing
        //..
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]); // I bind a second frame buffer.  You can skip this and go back to main though
        glBindTexture(GL_TEXTURE_2D, fbtex[0]); //I just bound the texture that was saved when drawing to fbo[0]
        //...
        //draw stuff on this buffer using the first buffer as a texture
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Set to zero.  We are back at the main frame buffer
        glBindTexture(GL_TEXTURE_2D, fbtex[1]); // This time I set the texture to what is in the second frame buffer
                                                // The second frame buffer contains what was drawn with the first fb texture
                                                // Plus what I drew on top of that (I'm using my method to blur the scene)
        //...
        //draw stuff using the second frame buffer texture.  In my case it's just a fullscreen quad with the blurred image I made
        glPopMatrix();
        //clean up draw arrays, etc
}
                                               

void createFramebuffer(GLuint& fbo, GLuint &fbtex) {
	glGenTextures(1, &fbtex);
	glBindTexture(GL_TEXTURE_2D, fbtex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, currentWidth, currentHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(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);
	glGenFramebuffers(1, &fbo);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbtex, 0);
	{
		GLenum status;
		status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
		switch (status) {
			case GL_FRAMEBUFFER_COMPLETE:
				break;
			case GL_FRAMEBUFFER_UNSUPPORTED:
				output << "Error: unsupported framebuffer format" << endl;
				exit(0);
			default:
				output << "Error: invalid framebuffer config" << endl;
				exit(0);
		}
	}
}