加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – COLOR_ATTACHMENT – 如何在Framebuffer对象中渲染多个纹理

发布时间:2020-12-16 07:12:26 所属栏目:百科 来源:网络整理
导读:我试图渲染多个纹理作为COLOR_ATTACHMENTs没有成功.我从显示它们得到的只是一个黑色屏幕(带有红色清晰填充)意味着我的纹理被读取但是“空”. 我的伪代码是:将3个纹理附加到FBO,纹理索引为1,2和3,颜色附件分别为0,1和2.作为测试用例,我尝试将场景渲染为3种颜
我试图渲染多个纹理作为COLOR_ATTACHMENTs没有成功.我从显示它们得到的只是一个黑色屏幕(带有红色清晰填充)意味着我的纹理被读取但是“空”.

我的伪代码是:将3个纹理附加到FBO,纹理索引为1,2和3,颜色附件分别为0,1和2.作为测试用例,我尝试将场景渲染为3种颜色附件,以便它们能够保存相同的精确数据.然后在着色器通道2(使用2Dsampler)读取这些纹理中的任何一个并在四边形上显示它们.

我对这2个额外颜色附件的初衷是将它们用作使用GPU乒乓技术的随机数据缓冲区.到目前为止,我只是将它们用作纹理克隆用于测试目的.

当尝试从GL_TEXTURE1(COLOR_ATTACHMENT0)读取时,一切正常,但不是来自其他2(黑屏).

代码 :

// Texture indices - inside a 'myGlut' struct
GLenum skyboxTextureIndex = GL_TEXTURE0;
GLenum colorTextureIndex = GL_TEXTURE1;
unsigned int colorTextureIndexInt = 1;
GLenum depthTexture1Index = GL_TEXTURE2;
unsigned int depthTexture1IndexInt = 2;
GLenum depthTexture2Index = GL_TEXTURE3;
unsigned int depthTexture2IndexInt = 3;

//** Below is inside 'main()' **//

// Create frame buffer
myGlut.frameBuffer = glutils::createFrameBuffer();

// Create texture to hold color buffer
glActiveTexture(myGlut.colorTextureIndex);
glBindTexture(GL_TEXTURE_2D,myGlut.colorTexture);
myGlut.colorTexture = glutils::createTextureAttachment(myGlut.camera -> getRenderResizedWidthPx(),myGlut.camera -> getRenderResizedHeightPx());
glutils::bindTextureAttachment(GL_COLOR_ATTACHMENT0,myGlut.colorTexture);

// Create 1st texture to hold depth buffer wannabe :>
glActiveTexture(myGlut.depthTexture1Index);
glBindTexture(GL_TEXTURE_2D,myGlut.depthTexture1);
myGlut.depthTexture1 = glutils::createTextureAttachment(myGlut.camera -> getRenderResizedWidthPx(),myGlut.camera -> getRenderResizedHeightPx());
glutils::bindTextureAttachment(GL_COLOR_ATTACHMENT1,myGlut.depthTexture1);

// Create 2nd texture to hold depth buffer wannabe :>
glActiveTexture(myGlut.depthTexture2Index);
glBindTexture(GL_TEXTURE_2D,myGlut.depthTexture2);
myGlut.depthTexture2 = glutils::createTextureAttachment(myGlut.camera -> getRenderResizedWidthPx(),myGlut.camera -> getRenderResizedHeightPx());
glutils::bindTextureAttachment(GL_COLOR_ATTACHMENT2,myGlut.depthTexture2);

// Check FBO
if (!glutils::checkFBOStatus()) return 0;

使用glutils :: functions

// Clear screen
void glutils::clearScreen (float r,float g,float b,float a) {
    glClearColor(r,g,b,a);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

// Bind select framebuffer
void glutils::bindFrameBuffer(int frameBuffer,int width,int height) {
    glBindFramebuffer(GL_FRAMEBUFFER,frameBuffer);
    glViewport(0,width,height);
}

// Create frame buffer
GLuint glutils::createFrameBuffer() {
    GLuint frameBuffer;
    glGenFramebuffers(1,&frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER,frameBuffer);
    return frameBuffer;
}

// Create a texture attachment
GLuint glutils::createTextureAttachment(int width,int height) {
    GLuint texture;
    glGenTextures(1,&texture);
    glBindTexture(GL_TEXTURE_2D,texture);
    glTexImage2D(GL_TEXTURE_2D,GL_RGB,height,GL_UNSIGNED_BYTE,NULL);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    return texture;
}

// Bind a texture attachment to select framebuffer
void glutils::bindTextureAttachment (GLenum colorAttachment,GLuint texture) {
    glFramebufferTexture2D(GL_FRAMEBUFFER,colorAttachment,GL_TEXTURE_2D,texture,0);
}

// Check current frame buffer status
bool glutils::checkFBOStatus () {
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        std::cerr << "##### ERROR : Frambuffer not complete... #####" << std::endl;
        return false;
    }
    else return true;
}

然后过剩显示功能:

// Clear screen
glutils::clearScreen(1.f,0.f,1.f);

// Bind to custom framebuffer
glutils::bindFrameBuffer(myGlut.frameBuffer,myGlut.camera -> getScreenWidthPx(),myGlut.camera -> getScreenHeightPx());

// Set draw context
GLuint drawBuffers[2];
if (myGlut.depthTextureSwitch) {    drawBuffers[0] = GL_COLOR_ATTACHMENT0;
                                    drawBuffers[1] = GL_COLOR_ATTACHMENT2;
} else {                            drawBuffers[0] = GL_COLOR_ATTACHMENT0;
                                    drawBuffers[1] = GL_COLOR_ATTACHMENT1;
} glDrawBuffers(2,drawBuffers);

// Use main program and bind uniforms
glUseProgram(myGlut.theProgram);
myGlut.refreshUniformsPass_1();

// Draw quad to sample
glutils::drawQuad();

// Unbind custom framebuffer -> use default (screen)
glutils::unbindCurrentFrameBuffer(myGlut.camera -> getScreenWidthPx(),myGlut.camera -> getScreenHeightPx());

// Use secondary program and bind uniforms
glUseProgram(myGlut.theProgram2);
myGlut.refreshUniformsPass_2();

// Draw quad to apply texture to
glutils::drawQuad();

// Switch
myGlut.depthTextureSwitch = !myGlut.depthTextureSwitch;

// Display & loop
glutSwapBuffers();
glutPostRedisplay();

相关的均匀绑定 – >通过1

glUniform1i(glGetUniformLocation(myGlut.theProgram,"depthTexture"),!myGlut.depthTextureSwitch ? myGlut.depthTexture2IndexInt : myGlut.depthTexture1IndexInt);

相关着色器代码 – >通过1

layout (location = 0) out vec4 outputColor;
layout (location = 1) out vec4 outputDepth1;
layout (location = 2) out vec4 outputDepth2;
uniform sampler2D depthTexture;

void main() {
    // ...
    outputColor = someColor;
    outputDepth1 = someColor;
    outputDepth2 = someColor;
}

相关的均匀绑定 – >通过2

glUniform1i(glGetUniformLocation(myGlut.theProgram2,"texFramebuffer"),myGlut.depthTextureSwitch ? myGlut.depthTexture1IndexInt : myGlut.depthTexture2IndexInt);

使用相关着色器代码 – >通过2

uniform sampler2D texFramebuffer;
out vec4 outputColor;
// ...
void main() {
    outputColor = texture(texFramebuffer,vec2(gl_FragCoord.x / screenWidthPx * resRatio,gl_FragCoord.y / screenHeightPx * resRatio));
}

简而言之:我的GL_TEXTURE0保持场景,而GL_TEXTURE1和GL_TEXTURE2为黑色.为什么?

解决方法

我终于找到了罪魁祸首.因为我在循环display()函数中绑定了framebuffer,所以在绑定FBO之后我也需要绑定纹理附件.改为

// Bind to custom framebuffer
glutils::bindFrameBuffer(myGlut.frameBuffer,myGlut.camera -> getScreenHeightPx());

// Bind to select attachments
glutils::bindTextureAttachment(GL_COLOR_ATTACHMENT0,myGlut.colorTexture);
if (!myGlut.depthTextureSwitch) glutils::bindTextureAttachment(GL_COLOR_ATTACHMENT1,myGlut.depthTexture1);
else glutils::bindTextureAttachment(GL_COLOR_ATTACHMENT1,myGlut.depthTexture2);

允许我渲染所有需要的颜色附件.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读