FBO: рендеринг в текстуру, неправильное отображение текстуры при рисовании рендеринг текстуры
Я использую OpengGL в приложении Mac OS X для рисования текстуры на NSOpenGLView
,
Приложение представляет собой проигрыватель фильмов. Он декодирует кадры фильма в CVOpenGLTextureRef
(которые являются текстурой OpenGL), и я рисую их прямо на вид, используя GL_QUAD
, Все работает правильно.
Ниже приведена соответствующая часть кода.
// "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();
Это работает просто отлично, и я могу изменить размер окна, и текстура правильно сопоставлена с меньшим окном.
Смотрите здесь для другого размера окна от полного экрана до 500x280 пикселей:
Теперь я хочу использовать FBO для рендеринга в текстуру, и я начал делать очень простую реализацию, состоящую в том, чтобы визуализировать кадр фильма за пределами экрана FBO (текстуру) и затем связать эту текстуру для рисования на экране.
Вот код:
// "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();
Код не работает правильно, потому что изображение / текстура не только перевернуты, но и наложение текстуры также неверно. Он работает правильно только когда окно полноэкранное, в противном случае он ведет себя очень странно.
Смотрите изображение ниже:
Как видите, текстура внутри окна корректно масштабируется, но она "обрезается" пропорционально разнице между полноэкранным размером окна и фактическим размером окна.
Я попробовал все без успеха.
Поскольку я впервые использую OpenGL, я что-то упустил? Я схожу с ума..
1 ответ
// 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); 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();