簡體   English   中英

OpenGL FBO 在不同的紋理目標中渲染不同的紋理

[英]OpenGL FBO render different textures in different texture targets

我試圖在我的 MSAA FBO 中渲染兩個不同的紋理( GL_COLOR_ATTACHMENT0GL_COLOR_ATTACHMENT1 ),初始化是:

// configure MSAA framebuffer
// --------------------------
glGenFramebuffers(1, &this->_MSAAid);
glBindFramebuffer(GL_FRAMEBUFFER, this->_MSAAid);
// create a multi-sampled color attachment texture
glGenTextures(1, &this->_textureMultisampleID);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, this->_textureMultisampleID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, this->_textureMultisampleID, 0);

glGenTextures(1, &this->_textureObjectIDMultisampled);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, this->_textureObjectIDMultisampled);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, this->_textureObjectIDMultisampled, 0);

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, drawBuffers);

// create an (also multi-sampled) render buffer object for depth and stencil attachments
glGenRenderbuffers(1, &this->_renderBufferObjectID);
glBindRenderbuffer(GL_RENDERBUFFER, this->_renderBufferObjectID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, _frameBufferSize.width, _frameBufferSize.height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, this->_renderBufferObjectID);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    std::cout << "ERROR::FRAMEBUFFER:: MSAA Framebuffer is not complete! Error: " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);

_frameBufferShader->use();
_frameBufferShader->setInt("screenTexture", 0);

然后我想將結果復制到另一個標准 FBO 中,初始化如下:

// framebuffer configuration
// -------------------------
glGenFramebuffers(1, &this->_id);
glBindFramebuffer(GL_FRAMEBUFFER, this->_id);

// create a color attachment texture
glGenTextures(1, &this->_textureID);
glBindTexture(GL_TEXTURE_2D, this->_textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->_textureID, 0);

glGenTextures(1, &this->_textureObjectID);
glBindTexture(GL_TEXTURE_2D, this->_textureObjectID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, _frameBufferSize.width, _frameBufferSize.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, this->_textureObjectID, 0);

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, drawBuffers);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);

_frameBufferShader->use();
_frameBufferShader->setInt("screenTexture", 0);

FBO綁定:

glBindFramebuffer(GL_FRAMEBUFFER, this->_MSAAid);
glViewport(0, 0, this->_frameBufferSize.width, this->_frameBufferSize.height);
glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)

glClearColor(refreshColor.coordinates.x, refreshColor.coordinates.y, refreshColor.coordinates.z, refreshColor.coordinates.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Rendering stuff...

渲染后,我想將兩個緩沖區復制到我的普通 FBO:

glBindFramebuffer(GL_READ_FRAMEBUFFER, this->_MSAAid);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->_id);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, _frameBufferSize.width, _frameBufferSize.height, 0, 0, _frameBufferSize.width, _frameBufferSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

glBindFramebuffer(GL_READ_FRAMEBUFFER, this->_MSAAid);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->_id);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, _frameBufferSize.width, _frameBufferSize.height, 0, 0, _frameBufferSize.width, _frameBufferSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

但由於某種原因,我得到的是在兩個紋理( GL_COLOR_ATTACHMENT0GL_COLOR_ATTACHMENT1 )中寫入了相同的內容,基本上,這兩個紋理是相同的,即使在我的着色器代碼中我 output 將結果轉換為兩個不同顏色的附件,在這里你可以看到我的片段着色器:

#version 330 core
layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec4 idColor;
  
in vec2 Frag_UV;

uniform sampler2D screenTexture;

void main()
{ 
    float gamma = 2.2;
    float exposure = 1.0;
    
    vec4 color = texture(screenTexture, Frag_UV.st);
    // HDR tonemapping
    color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
    // gamma correction
    color.rgb = pow(color.rgb, vec3(1.0 / gamma));
    fragColor = vec4(color.rgb, 1.0);
    idColor = vec4(0, 1, 0, 1.0);
}

這是 output:

輸出 1

我希望在場景 window 中獲得的是顯示帶有顏色附件 0 的紋理,在游戲 window 中顯示帶有顏色附件 1 的紋理!

目前這兩個 windows 顯示:

  • 場景 Window: textureObjectID -> GL_COLOR_ATTACHMENT1
  • 游戲 Window: textureID -> GL_COLOR_ATTACHMENT0

我想要的結果是根據GL_COLOR_ATTACHMENT渲染不同的紋理

此外,我嘗試使用glReadPixel(...)為附件 0 和附件 1 調試所有內容,而我得到的實際上是兩個紋理的相同像素值:

調試錯誤

這是我用於調試的代碼:

glBindFramebuffer(GL_READ_FRAMEBUFFER, this->sceneFrameBuffer->ID);
glReadBuffer(GL_COLOR_ATTACHMENT0);
float pixelColor[4];
glReadPixels(Input::mouse.xPosition, Input::mouse.yPosition, 1, 1, GL_RGBA, GL_FLOAT, &pixelColor);
std::cout << "Pixel Color0: ( " << pixelColor[0] << ", " << pixelColor[1] << ", " << pixelColor[2] << ", " << pixelColor[3] << " )" << std::endl;
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

glBindFramebuffer(GL_READ_FRAMEBUFFER, this->sceneFrameBuffer->ID);
glReadBuffer(GL_COLOR_ATTACHMENT1);
float pixelColors[4];
glReadPixels(Input::mouse.xPosition, Input::mouse.yPosition, 1, 1, GL_RGBA, GL_FLOAT, &pixelColors);
std::cout << "Pixel Color1: ( " << pixelColors[0] << ", " << pixelColors[1] << ", " << pixelColors[2] << ", " << pixelColors[3] << " )" << std::endl;
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

我錯過了什么? 想不通!

(我正在使用 Dear ImGui 在窗口中顯示紋理)

為了給出我想要實現的想法,我找到了一個視頻,它確實實現了我希望實現的想法。

我有兩個幀緩沖區,都用於渲染場景而不是屏幕(正如我錯誤地認為的那樣),所以我必須在用於渲染對象的着色器中指定顏色附件 output不是我用於在我的四邊形( “屏幕四邊形” )上渲染場景的着色器。

屏幕片段着色器:

#version 450 core

layout (location = 0) out vec4 fragColor;
  
in vec2 Frag_UV;

uniform sampler2D screenTexture;

void main()
{ 
    float gamma = 2.2;
    float exposure = 1.0;
    
    vec4 color = texture(screenTexture, Frag_UV.st);
    // HDR tonemapping
    color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
    // gamma correction
    color.rgb = pow(color.rgb, vec3(1.0 / gamma));

    fragColor = vec4(color.rgb, 1.0);
}

我用於渲染對象的 Phong 片段着色器:

#version 450 core

layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 idColor;

//Declaring stuff...

void main()
{
    vec3 viewDir = normalize(viewPos - fs_in.FragPos);
    vec3 result = vec3(0.0, 0.0, 0.0);

    result += calcPointLight(material, pointLight, viewDir);

    idColor = vec4(vID);
    FragColor = vec4(result, 1.0);
}

現在我把所有東西都渲染到了我的GL_COLOR_ATTACHMENT1 ,感謝所有評論的人!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM