FBO:渲染到纹理,绘制渲染的纹理时错误的纹理映射 [英] FBO: render to texture, wrong texture mapping when drawing rendered texture

查看:370
本文介绍了FBO:渲染到纹理,绘制渲染的纹理时错误的纹理映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆