PDA

View Full Version : how to render to texture?



Andrinyang
07-15-2011, 01:18 AM
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);

shlomip
07-15-2011, 01:54 AM
try this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

its work for me ;)

BionicBytes
07-15-2011, 02:06 AM
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?

Andrinyang
07-15-2011, 02:11 AM
try this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

its work for me ;)


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

Andrinyang
07-15-2011, 02:34 AM
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?


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

shlomip
07-15-2011, 04:19 AM
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.

Andrinyang
07-15-2011, 07:18 AM
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,framebuffe r);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_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,framebuffe r);
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;
}

BionicBytes
07-15-2011, 08:49 AM
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.

Andrinyang
07-15-2011, 09:56 AM
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.

Leandro220
07-15-2011, 10:07 AM
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();

BionicBytes
07-15-2011, 10:11 AM
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).

Andrinyang
07-15-2011, 10:33 PM
You mean you want to use the off-screen FBO texture as a source texture when rendering to the quad?


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,framebuffe r);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_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,framebuffe r);
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;

BionicBytes
07-16-2011, 10:10 AM
i do it like that,but i fail.
What happens? What do you see?
How do you know the FBO rendering actually happens?

V-man
07-16-2011, 07:31 PM
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

Andrinyang
07-17-2011, 12:54 AM
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.

Mctittles
07-17-2011, 08:09 AM
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);
}
}
}