0
我在Mac上的OpenGL 3.3有一個令人困惑的情況。我創建了一個具有五個連接點的FBO,大小爲512x512。我構建了一個着色器,用於爲我的幾何體寫入gl_FragData [0-4]以獲得漫反射,法線,位置,鏡面反射和發射。當我渲染場景後緩衝區和渲染目標正在更新,即使我只綁定了FBO!OpenGL FBO與MRT寫回緩衝區
下面是一些代碼:
void OpenGLESDriver::setFrameBufferAttachments(u32 nAttachments, const u32* aAttachments){
pushText("setFrameBufferAttachments");
#if USE_MRT
GLint max;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max);
GLenum aBuffers[max];
if(nAttachments > max){
nAttachments = max;
}
for(u32 i=0; i<nAttachments; ++i){
aBuffers[i] = GL_COLOR_ATTACHMENT0+aAttachments[i];
}
for(u32 i=nAttachments; i<max; ++i){
aBuffers[i] = GL_NONE;
}
glDrawBuffers(max, aBuffers);
glAssert();
#else
glDrawBuffer(GL_COLOR_ATTACHMENT0+aAttachments[0]);
glAssert();
#endif
popText();
}
而且FBO粘結劑:
bool OpenGLESDriver::setFrameBuffer(const FrameBuffer::handle& hFrameBuffer){
if(hFrameBuffer){
pushText("setFrameBuffer");
glBindFramebuffer(GL_FRAMEBUFFER, hFrameBuffer->toFBO());
glAssert();
if(!hFrameBuffer->toColorTargets().empty()){
u32 nAttachments = hFrameBuffer->toColorTargets().size();
u32 aAttachments[nAttachments];
for(u32 i=0; i<nAttachments; ++i){
aAttachments[i] = i;
}
setFrameBufferAttachments(nAttachments, aAttachments);
}else{
setFrameBufferAttachments(0, 0);
}
int w = hFrameBuffer->toDepthTexture()->toWidth();
int h = hFrameBuffer->toDepthTexture()->toHeight();
glViewport(0, 0, w, h);
glAssert();
//clear out all texture stages because we don't want a left over
//frame buffer texture being bound to the shader.
for(u32 i=0; i<Material::kMaxSamplers; ++i){
setTextureStage(i, 0);
}
popText();
return true;
}
return false;
}
我創建FBO有:
FrameBuffer::handle OpenGLESDriver::createFrameBuffer(const FrameBuffer::ColorTargets& vColorTargets, const DepthTarget::handle& hDT){
//--------------------------------------------------------------------
// Save off default FBO.
//--------------------------------------------------------------------
if(s_iFBOMaster < 0){
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &s_iFBOMaster);
glAssert();
}
//--------------------------------------------------------------------
// Generate frame buffer object.
//--------------------------------------------------------------------
GLuint fbo;
glGenFramebuffers(1, &fbo);
glAssert();
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glAssert();
//--------------------------------------------------------------------
// Attach color RBO.
//--------------------------------------------------------------------
FrameBuffer::ColorTargets::const_iterator itCT = vColorTargets.getIterator();
u32 mrtIndex = 0;
while(itCT){
const ColorTarget::handle& hCT = itCT++;
if(!hCT){
continue;
}
if(hCT->toTexID()){
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0+mrtIndex,
GL_TEXTURE_2D,
hCT->toTexID(),
0);
}else if(hCT->toRBO()){
glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0+mrtIndex,
GL_RENDERBUFFER,
hCT->toRBO());
}else{
DEBUG_ASSERT_ALWAYS("No color texture or RBO to attach!");
}
glAssert();
++mrtIndex;
if(!checkFBStatus()){
e_log("GL", "Couldn't create color attachment!");
hCT.as<ColorTarget>()->toFlags()->bFailed = true;
}
}
//--------------------------------------------------------------------
// Attach depth RBO.
//--------------------------------------------------------------------
if(hDT){
if(hDT->toTexID()){
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
hDT->toTexID(),
0);
}else if(hDT->toRBO()){
glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER,
hDT->toRBO());
}else{
DEBUG_ASSERT_ALWAYS("No depth texture or RBO to attach!");
}
glAssert();
if(!checkFBStatus()){
e_log("GL", "Couldn't create depth attachment!");
hDT.as<DepthTarget>()->toFlags()->bFailed = true;
}
}
//--------------------------------------------------------------------
// New handle.
//--------------------------------------------------------------------
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glAssert();
FrameBuffer::handle hFrameBuffer = e_new(FrameBuffer);
hFrameBuffer->setColorTargets(vColorTargets);
hFrameBuffer->setDepthTarget(hDT);
hFrameBuffer->setFBO(u32(fbo));
return hFrameBuffer;
}
我回去與後臺緩衝區:
void OpenGLESDriver::setDefaultTarget(){
pushText("setDefaultTarget");
glBindFramebuffer(GL_FRAMEBUFFER, 0);//s_iFBOMaster);
glAssert();
glViewport(0, 0, IEngine::cxView(), IEngine::cyView());
glAssert();
popText();
}
所以最終的渲染代碼如下所示:
pushText("Render MRT pass");
if(setFrameBuffer(m_tPostFx.buffers[0])){
setColorMask(true, true, true, true);
clearZ();
enableZBuffer(false);
setColor(color);
clearMRT(m_tPostFx.clearMRTShader);
enableZBuffer(true);
drawMRTPass();
}
popText();
,由於某種原因後緩衝器被渲染到還有FBO。我一定錯過了一些東西,但沒有弄清楚什麼。任何人都可以看到我做錯了什麼?
我實際上有點困惑,爲什麼_this_' GLenum aBuffers [max];'編譯'max'不是一個常量。我假設'USE_MRT'是未定義的,它是'setFrameBufferAttachments'中我們應該關注的第二個代碼分支? – 2015-02-05 20:29:53
在C++ 11 max中不需要是常量。誠然,它不在Visual Studio下編譯,但是這個代碼適用於Android和OSX。沒關係,因爲我的Win32渲染器使用DirectX,而我的iOS使用的是Metal。 Win32代碼不會訴諸於這種欺騙。 – toymaker 2015-02-09 15:55:40