Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 彩色附件';s-如何将多个纹理渲染为帧缓冲区对象内的颜色附件?_C++_Opengl_Framebuffer_Fbo - Fatal编程技术网

C++ 彩色附件';s-如何将多个纹理渲染为帧缓冲区对象内的颜色附件?

C++ 彩色附件';s-如何将多个纹理渲染为帧缓冲区对象内的颜色附件?,c++,opengl,framebuffer,fbo,C++,Opengl,Framebuffer,Fbo,我试图将多个纹理渲染为COLOR\u附件s,但没有成功。我从显示它们中得到的只是一个黑色屏幕(带有红色的清晰填充),这意味着我的纹理已被读取,但“为空” 我的伪代码是:分别使用纹理索引1、2和3以及颜色附件0、1和2将3个纹理附加到FBO。作为一个测试用例,我尝试将我的场景渲染到3个颜色附件,以便它们应该包含相同的精确数据。然后在着色器过程2(使用2Dsampler)读取其中任何一个纹理,并将其显示在四元网格上 我对这两个额外颜色附件的最初意图是使用GPU乒乓技术将它们用作随机数据缓冲区。到目前

我试图将多个纹理渲染为
COLOR\u附件
s,但没有成功。我从显示它们中得到的只是一个黑色屏幕(带有红色的清晰填充),这意味着我的纹理已被读取,但“为空”

我的伪代码是:分别使用纹理索引1、2和3以及颜色附件0、1和2将3个纹理附加到FBO。作为一个测试用例,我尝试将我的场景渲染到3个颜色附件,以便它们应该包含相同的精确数据。然后在着色器过程2(使用2Dsampler)读取其中任何一个纹理,并将其显示在四元网格上

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

当尝试从
GL\u TEXTURE1
COLOR\u 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::
函数

// 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, 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, 0, GL_RGB, width, height, 0, GL_RGB, 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;
}
相关统一绑定->通过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);
uniform sampler2D texFramebuffer;
out vec4 outputColor;
// ...
void main() {
    outputColor = texture(texFramebuffer, vec2(gl_FragCoord.x / screenWidthPx * resRatio, gl_FragCoord.y / screenHeightPx * resRatio));
}
使用相关着色器代码->通过2

glUniform1i(glGetUniformLocation(myGlut.theProgram2, "texFramebuffer"), myGlut.depthTextureSwitch ? myGlut.depthTexture1IndexInt : myGlut.depthTexture2IndexInt);
uniform sampler2D texFramebuffer;
out vec4 outputColor;
// ...
void main() {
    outputColor = texture(texFramebuffer, vec2(gl_FragCoord.x / screenWidthPx * resRatio, gl_FragCoord.y / screenHeightPx * resRatio));
}

简而言之:我的
GL_纹理0
保留场景,而
GL_纹理1
GL_纹理2
为黑色。为什么?我终于找到了罪犯。因为我在循环
display()
函数中绑定帧缓冲区,所以在绑定FBO之后,我还需要绑定纹理附件。改为

// Bind to custom framebuffer
glutils::bindFrameBuffer(myGlut.frameBuffer, myGlut.camera -> getScreenWidthPx(), 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);

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

基于
glDrawBuffers()
调用,您只渲染到2个纹理。对于过程2,您使用的是未渲染到的纹理。确实,我正在读取未渲染到的纹理,但这是(预期的)并且是由于“乒乓”渲染技术。所以这意味着我应该只在第一帧得到一个黑屏。因为在第2帧,我渲染到纹理2(打开)并从纹理1读取-我在第1帧渲染到的,依此类推。。。真正的问题是,我的渲染一直是黑色的,好像从来没有渲染过
GL_TEXTURE1
GL_TEXTURE2
。为什么?如果我尝试不断地从
GL_TEXTURE1
GL_TEXTURE2
读取,我会得到一个恒定的黑屏。只采样一个纹理(texFramebuffer),您不需要不同的ActiveTexture(tex插槽),令人困惑…是的,你是对的。但我需要在着色器过程1处读取
depthTexture1
depthTexture2
。因此使用了3个纹理槽。你需要的槽数与#TextureName相同,换句话说,#槽=#单个过程中采样的纹理。但是如果你真的想绑定3个纹理以避免调用bindTexture betw即使通过了,你也可以,但你必须声明3个不同的统一事实上,FBO附件保持不变,不需要重新设置。至少,如果你自己不在某个地方分离它们的话。很难从目前给出的代码片段中看出实际情况。我正在实现一个GPU乒乓()所以我需要在每一帧切换附件。例如:从0&1+写入到2@frame 1,从0&2+写入到1@frame to等等…问题是:我无法在一次过程中读取和写入纹理,因此乒乓球解决方案。无需重新附加。您所需的只是切换绘图缓冲区。顺便说一句,取决于在您实际执行的操作中,甚至可能在同一过程中读取和写入同一纹理。GL在某些特定条件下允许这样做。切换绘图缓冲区正是我开始做的事情,但由于某些原因,它对我不起作用…即绑定
main()中的所有内容
-纹理和颜色附件-以及在
display()
内切换绘图缓冲区都不起作用。