FBO: render to texture, wrong texture mapping when drawing rendered texture

I'm using OpengGL on a Mac OS X application to draw texture on a NSOpenGLView .

The app is a movie player. It decodes movie frames into CVOpenGLTextureRef (which are OpenGL texture) and I draw them directly to the view using GL_QUAD . Everything works correctly.

Below is the relevant part of the code.

// "image" is the CVOpenGLTextureRef containing the movie frame as texture
GLenum textureTarget = CVOpenGLTextureGetTarget(image);
GLuint textureName = CVOpenGLTextureGetName(image);

glEnable(textureTarget);
glBindTexture(textureTarget, textureName); 

glBegin(GL_QUADS);
// Draw the quads
//Note: textureTagret is NOT GL_TEXTURE_2D, therefore texture coordinates
//are NOT scaled to [0, 1] 

glTexCoord2f(0.0f, imageRect.size.height);
glVertex2f (0.0f, 0.0f);

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f, windowRect.size.height); 

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (windowRect.size.width, windowRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (windowRect.size.width,0.0f); 

glEnd();
glDisable(textureTarget);
glFlush();

It works just fine and I'm able to resize the window and the texture is mapped correctly to the smaller window.

See here for different window size from full screen to 500x280 pixel: 没有FBO

I now want to use FBO for rendering to texture and I started making a very simple implementation which consists in rendering the movie frame to an off-screen FBO (texture) and than bind that texture to draw on screen.

Here is the code:

// "image" is the CVOpenGLTextureRef containing the movie frame as texture
GLenum textureTarget = CVOpenGLTextureGetTarget(image);
GLuint textureName = CVOpenGLTextureGetName(image);

////////////////////////////////////////////////////////////////////
// the creation on the FBO is done only once on program start:

GLuint fboId;
GLuint textureId;
float targetWidth = 2048;
float targetHeight = 2048;

// create a texture object
glGenTextures(1, &textureId);
glBindTexture(textureTarget, textureId);
glTexParameterf(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(textureTarget, GL_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(textureTarget, 0, GL_RGBA8, targetWidth, targetHeight, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(textureTarget, 0);

// create a framebuffer object
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                           textureTarget, textureId, 0);

// check FBO status
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
    return FALSE;

// switch back to window-system-provided framebuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
///////////////////////////////////////////////////////////////////////////////

// Render to texture

glEnable(textureTarget);
glBindTexture(textureTarget, textureName);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
glClear(GL_COLOR_BUFFER_BIT);   

glBegin(GL_QUADS);
// Draw the quads

glTexCoord2f(0.0f, imageRect.size.height);
glVertex2f (0.0f, 0.0f);        

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f,imageRect.size.height);

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (imageRect.size.width, imageRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (imageRect.size.width,0.0f);

glEnd();
glFlush();

// Bind newly rendered texture
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(textureTarget, textureId);
glGenerateMipmapEXT(textureTarget);

// draw on-screen
glBegin(GL_QUADS);
// Draw the quads
//Note: textureTagret is NOT GL_TEXTURE_2D, therefore texture coordinates
//are NOT scaled to [0, 1] 

glTexCoord2f(0.0f, imageRect.size.height);
glVertex2f (0.0f, 0.0f);

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f, windowRect.size.height); 

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (windowRect.size.width, windowRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (windowRect.size.width,0.0f); 

glEnd();
glDisable(textureTarget);
glFlush();

The code does not work correctly because the image/texture is not only upside-down but texture mapping is also wrong. It works correctly only when the window is full screen, otherwise it behaves really strange.

See image below: 与FBO

As you can see, the texture is scaled correctly inside the window but it gets "cropped" proportionally to the difference between full screen window size and actual window size.

I have tried everything without success.

Since this is one of the first time that I use OpenGL, am I missing something? I'm becoming crazy..


// Render to texture

glEnable(textureTarget);
glBindTexture(textureTarget, textureName);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
glClear(GL_COLOR_BUFFER_BIT);   

我缺少在这里设置视窗和framebuffer对象的投影。

glBegin(GL_QUADS);
// Draw the quads

glTexCoord2f(0.0f, imageRect.size.height);
g    lVertex2f (0.0f, 0.0f);        

glTexCoord2f(0.0f, 0.0f); 
glVertex2f (0.0f,imageRect.size.height);

glTexCoord2f(imageRect.size.width, 0.0f);
glVertex2f (imageRect.size.width, imageRect.size.height);

glTexCoord2f(imageRect.size.width, imageRect.size.height);
glVertex2f (imageRect.size.width,0.0f);

glEnd();
glFlush();
链接地址: http://www.djcxy.com/p/33918.html

上一篇: OpenGL:渲染到FBO时是否支持纹理合并器功能?

下一篇: FBO:在绘制渲染纹理时渲染到纹理,错误的纹理映射