FBO:渲染到纹理,绘制渲染的纹理时错误的纹理映射 [英] FBO: render to texture, wrong texture mapping when drawing rendered texture
问题描述
我正在Mac OS X应用程序上使用OpengGL在NSOpenGLView
上绘制纹理.
I'm using OpengGL on a Mac OS X application to draw texture on a NSOpenGLView
.
该应用是电影播放器.它将电影帧解码为CVOpenGLTextureRef
(它们是OpenGL纹理),然后使用GL_QUAD
将它们直接绘制到视图中.一切正常.
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.
有关从全屏到500x280像素的不同窗口大小,请参见此处:
See here for different window size from full screen to 500x280 pixel:
我现在想使用FBO渲染到纹理,并且我开始做一个非常简单的实现,其中包括将影片帧渲染到屏幕外的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.
这是代码:
// "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.
请参见下图:
如您所见,纹理在窗口内已正确缩放,但它会根据全屏窗口大小与实际窗口大小之间的差异成比例地裁剪".
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.
由于这是我第一次使用OpenGL,我是否缺少某些东西?我快疯了.
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);
我在这里没有设置帧缓冲区对象的视口和投影.
Im missing setting the viewport and the projection for the framebuffer object here.
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();
这篇关于FBO:渲染到纹理,绘制渲染的纹理时错误的纹理映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!