我正在尝试通过FBO将RTT通过C ++ MFC应用程序中的适当像素格式使用OpenGL添加到我的应用程序中。我已经将RTO工作的另一个基于SDL的应用程序复制了FBO代码。我正在使用glew访问OpenGL驱动程序。
在创建,激活,停用和渲染FBO时,我已经对所有OpenGL调用结果进行了广泛测试,并且没有任何错误。
当将渲染缓冲区从GL_BACK切换到渲染FBO的颜色附件时,似乎没有任何东西可以写入颜色缓冲区 - 甚至glClearColor()似乎也无法使用它。
这是因为Windows像素格式不允许我渲染到FBO吗?由于渲染缓冲区切换都是通过OpenGL进行的,我怀疑是这种情况,但我绝对不知道为什么RTT在我的应用程序中不起作用。
我可能需要寻找什么指针?
标题文件:
#ifndef __FBO_H
#define __FBO_H
#include <windows.h>
#include <stddef.h>
#define MAX_COLOR_BUFFERS 16
typedef struct tFrameBuffer {
GLuint hFBO; // OpenGL FBO handle
GLuint hColorBuffers [MAX_COLOR_BUFFERS]; // color buffer handles
GLuint bufferIds [MAX_COLOR_BUFFERS]; // color buffer attachment ids
GLuint hDepthBuffer; // depth buffer handle
GLuint hStencilBuffer; // stencil buffer handle
int nColorBuffers; // number of available color buffers
int nBuffer; // currently selected color buffer(s)
int nType; // depth buffer type (depth only / depth + stencil)
int nWidth; // render buffer width
int nHeight; // render buffer height
int bActive; // FBO is draw buffer
GLenum nStatus; // result of availability test
} tFrameBuffer;
class CFBO {
private:
tFrameBuffer m_info;
public:
CFBO () { Init (); }
~CFBO () { Destroy (); }
static bool Setup (void);
void Init (void);
int Create (int nWidth, int nHeight, int nType = 1, int nColorBuffers = 1);
void Destroy (void);
int Available (void);
int Enable (int nColorBuffers = 0);
int Disable (void);
inline GLuint Handle (void) { return m_info.hFBO; }
void SelectColorBuffers (int nBuffer = 0);
void CFBO::Draw (CRect viewport);
private:
int CreateColorBuffers (int nBuffers);
int CreateDepthBuffer (void);
void AttachBuffers (void);
};
#endif //__FBO_H
实现:
//---------------------------------------------------------------------------
int CFBO::Available (void)
{
if (!Handle ()) // no FBO generated
return 0;
switch (m_info.nStatus = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT)) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
return 1;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
return -1;
default:
return -1;
}
}
//---------------------------------------------------------------------------
void CFBO::Init (void)
{
memset (&m_info, 0, sizeof (m_info));
m_info.nBuffer = 0x7FFFFFFF;
}
//---------------------------------------------------------------------------
// Create nBuffers color buffers for the FBO
// The texture handle is stored in m_info.hColorBuffers, the color attachment
// id in m_info.bufferIds
// This method can be overriden to create different kinds of render targets
int CFBO::CreateColorBuffers (int nBuffers)
{
if (!nBuffers)
return 1;
GLint nMaxBuffers;
glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS_EXT, &nMaxBuffers);
if (nMaxBuffers > MAX_COLOR_BUFFERS)
nMaxBuffers = MAX_COLOR_BUFFERS;
else if (nBuffers > nMaxBuffers)
nBuffers = nMaxBuffers;
m_info.nColorBuffers =
m_info.nColorBuffers = nBuffers;
m_info.nFirstBuffer = 0;
glGenTextures (nBuffers, m_info.hColorBuffers);
glEnable (GL_TEXTURE_2D);
glActiveTexture (GL_TEXTURE0);
for (int i = 0; i < nBuffers; i++) {
glBindTexture (GL_TEXTURE_2D, m_info.hColorBuffers [i]);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, m_info.nWidth, m_info.nHeight,
0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
m_info.bufferIds [i] = GL_COLOR_ATTACHMENT0_EXT + i;
}
return glGetError () ? 0 : 1;
}
// -----------------------------------------------------------------------
// Create depth texture
// (depth only: nType == 0, depth + stencil: nType == 1)
#define GL_DEPTH_STENCIL_EXT 0x84F9
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
#define GL_DEPTH24_STENCIL8_EXT 0x88F0
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
GLuint CreateDepthTexture (int nType, int nWidth, int nHeight)
{
if (!(nWidth && nHeight))
return 0;
GLuint hDepthBuffer;
glEnable (GL_TEXTURE_2D);
glActiveTexture (GL_TEXTURE0);
glGenTextures (1, &hDepthBuffer);
if (glGetError ())
return hDepthBuffer = 0;
glBindTexture (GL_TEXTURE_2D, hDepthBuffer);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
if (nType == 1) // depth + stencil
glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, nWidth, nHeight, 0,
GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
else
glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, nWidth, nHeight, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
if (glGetError ()) {
glDeleteTextures (1, &hDepthBuffer);
return hDepthBuffer = 0;
}
glBindTexture (GL_TEXTURE_2D, 0);
return hDepthBuffer;
}
//------------------------------------------------------------------------
int CFBO::CreateDepthBuffer (void)
{
// depth buffer
if (!(m_info.hDepthBuffer =
CreateDepthTexture (m_info.nType, m_info.nWidth, m_info.nHeight)))
return 0;
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, m_info.hDepthBuffer, 0);
if (m_info.nType) // stencil buffer
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_TEXTURE_2D,
m_info.hStencilBuffer = m_info.hDepthBuffer, 0);
return glGetError () ? 0 : 1;
}
//------------------------------------------------------------------------
// Attach render buffers
void CFBO::AttachBuffers (void)
{
for (int i = 0; i < m_info.nColorBuffers; i++)
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, m_info.bufferIds [i],
GL_TEXTURE_2D, m_info.hColorBuffers [i], 0);
// depth + stencil buffer
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, m_info.hDepthBuffer, 0);
if (m_info.nType)
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_TEXTURE_2D,
m_info.hStencilBuffer = m_info.hDepthBuffer, 0);
}
//------------------------------------------------------------------------
// Create an FBO with width nWidth, height nHeight, depth (nType == 0) or
// depth + stencil (nType == 1) buffer
// and one or more color buffers (nColorBuffers)
int CFBO::Create (int nWidth, int nHeight, int nType, int nColorBuffers)
{
Destroy ();
// compute power of two >= nWidth and nHeight
m_info.nWidth = Pow2ize (nWidth);
m_info.nHeight = Pow2ize (nHeight);
m_info.nType = nType;
m_info.hDepthBuffer = 0;
m_info.hStencilBuffer = 0;
glGenFramebuffersEXT (1, &m_info.hFBO);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, m_info.hFBO);
if (!(CreateColorBuffers (nColorBuffers) && CreateDepthBuffer ())) {
Destroy ();
return 0;
}
AttachBuffers ();
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
if (!Available ()) {
Destroy ();
return 0;
}
return 1;
}
//------------------------------------------------------------------------
void CFBO::Destroy (void)
{
if (m_info.hFBO) {
if (m_info.nColorBuffers) {
glDeleteTextures (m_info.nColorBuffers, m_info.hColorBuffers);
memset (m_info.hColorBuffers, 0, sizeof (m_info.hColorBuffers));
m_info.nColorBuffers = 0;
}
if (m_info.hDepthBuffer) {
glDeleteTextures (1, &m_info.hDepthBuffer);
glDeleteRenderbuffersEXT (1, &m_info.hDepthBuffer);
m_info.hDepthBuffer =
m_info.hStencilBuffer = 0;
}
glDeleteFramebuffersEXT (1, &m_info.hFBO);
m_info.hFBO = 0;
}
}
//---------------------------------------------------------------------------
// depending on nBuffer, select the first, a single specified or a range
// of color buffer als draw buffers. m_info.bufferIds contains the color
// attachment number (GL_COLOR_ATTACHMENT0, etc).
void CFBO::SelectColorBuffers (int nBuffer)
{
if ((m_info.nColorBuffers == 1) || (nBuffer >= m_info.nColorBuffers))
glDrawBuffer (m_info.bufferIds [nBuffer = 0]); // single buffer/invalid index
else if (nBuffer < 0)
glDrawBuffers (m_info.nColorBuffers, m_info.bufferIds); // use all buffers
else
glDrawBuffer (m_info.bufferIds [nBuffer]); // use the specified color buffer
m_info.nBuffer = nBuffer;
}
//---------------------------------------------------------------------------
int CFBO::Enable (int nColorBuffers)
{
if (m_info.bActive)
return 1;
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, m_info.hFBO);
SelectColorBuffers (nColorBuffers);
glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
return m_info.bActive = 1;
}
//---------------------------------------------------------------------------
int CFBO::Disable (void)
{
if (!m_info.bActive)
return 1;
m_info.nBuffer = 0x7FFFFFFF;
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer (GL_BACK);
glReadBuffer (GL_BACK);
m_info.bActive = 0;
return 1;
}
//---------------------------------------------------------------------------
void CFBO::Draw (CRect viewport)
{
float uMax = float (viewport.Width ()) / float (m_info.nWidth);
float vMax = float (viewport.Height ()) / float (m_info.nHeight);
float texCoord [4][2] = {{0.0, 0.0},{0.0, vMax},{uMax, vMax},{uMax, 0.0}};
float vertices [4][2] = {{0.0f, 0.0f},{0.0f, 1.0f},{1.0f, 1.0f},{1.0f, 0.0f}};
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glEnable (GL_TEXTURE_2D);
glActiveTexture (GL_TEXTURE0);
glClientActiveTexture (GL_TEXTURE0);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glEnableClientState (GL_VERTEX_ARRAY);
glTexCoordPointer (2, GL_FLOAT, 0, texCoord);
glVertexPointer (2, GL_FLOAT, 0, vertices);
glBindTexture (GL_TEXTURE_2D, m_info.hColorBuffers [0]);
glColor3f (1.0f, 1.0f, 1.0f);
glDisable (GL_BLEND);
glDrawArrays (GL_QUADS, 0, 4);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glDisableClientState (GL_VERTEX_ARRAY);
}
//---------------------------------------------------------------------------
应用:
CFBO m_renderBuffers;
m_renderBuffers.Create (GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN), 1, 2);
...
//-----------------------------------------------------------------------
void CRendererGL::BeginRender (bool bOrtho)
{
SetupProjection (bOrtho);
m_renderBuffers.Enable ();
}
//-----------------------------------------------------------------------
void CRendererGL::EndRender (bool bSwapBuffers)
{
for (int i = 0; i < 3; i++) {
glActiveTexture (GL_TEXTURE0 + i);
glClientActiveTexture (GL_TEXTURE0 + i);
glDisableClientState (GL_COLOR_ARRAY);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glDisableClientState (GL_VERTEX_ARRAY);
glDisable (GL_TEXTURE_2D);
}
shaderManager.Deploy (-1);
glDisable (GL_DEPTH_TEST);
if (bSwapBuffers) {
m_renderBuffers.Disable ();
m_renderBuffers.Draw (Viewport ());
SwapBuffers (m_glHDC);
}
}
//-----------------------------------------------------------------------
答案 0 :(得分:2)
我知道了。我知道这肯定是愚蠢的事。
将颜色缓冲区渲染为GL_BACK时,而不是
glActiveTexture (GL_TEXTURE0);
glClientActiveTexture (GL_TEXTURE0);
glEnable (GL_TEXTURE_2D);
我写过
glEnable (GL_TEXTURE_2D);
glActiveTexture (GL_TEXTURE0);
glClientActiveTexture (GL_TEXTURE0);
首先必须在启用或禁用纹理之前指定TMU。
我不明白的原因是为什么我的问题已经被三次贬低了。