OpenGL无法在只有3个组件时读取帧缓冲附件,但在有4个组件时可以读取。

huangapple go评论58阅读模式
英文:

OpenGL cannot read framebuffer attachment when there are only 3 components, but can read when there's 4 component

问题

我目前正在使用OpenGL进行延迟渲染,我正在尝试将几何通道的位置和法线数据传递到光照通道。

然而,任何不是GL_RGBA类型的帧缓决定不会作为纹理读取时返回空值。我已经发现,任何不具有4个分量的帧缓决定都不起作用。

我该如何修复这个问题?我漏掉了什么?

C++代码:

// 几何缓决定
gbuffer::gbuffer(uint32_t _width, uint32_t _height) {
    // 创建GL缓决定。
    glCreateFramebuffers(1, &handle_);

    // 颜色附件。
    colour_attachments_.resize(num_gbuffer_attachments);
    colour_attachments_[gbuffer_position] = std::make_shared<texture_2d>("position", _width, _height, GL_RGB16F); // 只有3个分量,不起作用。
    colour_attachments_[gbuffer_normal] = std::make_shared<texture_2d>("normal", _width, _height, GL_RGB16F); // 只有3个分量,不起作用。
    colour_attachments_[gbuffer_albedo] = std::make_shared<texture_2d>("albedo_colour", _width, _height, GL_RGBA8); // 4个分量,没有问题。
    colour_attachments_[gbuffer_specular] = std::make_shared<texture_2d>("specular_colour", _width, _height, GL_RGBA8);  // 4个分量,没有问题。
    colour_attachments_[gbuffer_gloss] = std::make_shared<texture_2d>("gloss", _width, _height, GL_R32F); // 只有1个分量,不起作用。
    for (auto i = 0; i < colour_attachments_.size(); ++i) {
        glNamedFramebufferTexture(handle_, GL_COLOR_ATTACHMENT0 + i, colour_attachments_[i]->handle(), 0);
    }

    // 深度模板附件。
    depth_stencil_attachment_ = std::make_shared<texture_2d>("depth_stencil", _width, _height, sized_format::depth24_stencil8);
    glNamedFramebufferTexture(handle_, GL_DEPTH_STENCIL_ATTACHMENT, depth_stencil_attachment_->handle(), 0);
}

GLSL代码:

uniform sampler2D u_texture_gbuffer_position;
uniform sampler2D u_texture_gbuffer_normal;
uniform sampler2D u_texture_gbuffer_albedo;
uniform sampler2D u_texture_gbuffer_specular;
uniform sampler2D u_texture_gbuffer_gloss;

const vec3 position = texture(u_texture_gbuffer_position, io_tex_coord.xy).rgb; // 全是零。
const vec3 normal = texture(u_texture_gbuffer_normal, io_tex_coord.xy).rgb; // 全是零。
const vec4 albedo = texture(u_texture_gbuffer_albedo, io_tex_coord.xy); // 有正确的值。
const vec4 specular = texture(u_texture_gbuffer_specular, io_tex_coord.xy); // 有正确的值。
const float gloss = texture(u_texture_gbuffer_gloss, io_tex_coord.xy).r; // 全是零。
英文:

I'm currently working on deferred rendering in OpenGL, and I'm currently trying to pass position and normal data from the geometry pass to the lighting pass.

However, any framebuffer attachments that aren't of type GL_RGBA give empty values when read as a texture. I've managed to boil it down to the fact that any framebuffer attachments that do not have 4 components simply do not work.

How can I fix this? What am I missing?

C++ Code:

// Geometry Buffer
gbuffer::gbuffer(uint32_t _width, uint32_t _height) {
    // Create GL buffer.
    glCreateFramebuffers(1, &handle_);

    // Colour attachments.
    colour_attachments_.resize(num_gbuffer_attachments);
    colour_attachments_[gbuffer_position] = std::make_shared<texture_2d>("position", _width, _height, GL_RGB16F); // Only 3 components, does not work.
    colour_attachments_[gbuffer_normal] = std::make_shared<texture_2d>("normal", _width, _height, GL_RGB16F); // Only 3 components, does not work.
    colour_attachments_[gbuffer_albedo] = std::make_shared<texture_2d>("albedo_colour", _width, _height, GL_RGBA8); // 4 components, no problem.
    colour_attachments_[gbuffer_specular] = std::make_shared<texture_2d>("specular_colour", _width, _height, GL_RGBA8);  // 4 components, no problem.
    colour_attachments_[gbuffer_gloss] = std::make_shared<texture_2d>("gloss", _width, _height, GL_R32F); // Only 1 component, does not work.
    for (auto i = 0; i < colour_attachments_.size(); ++i) {
        glNamedFramebufferTexture(handle_, GL_COLOR_ATTACHMENT0 + i, colour_attachments_[i]->handle(), 0);
    }

    // Depth-Stencil attachments.
    depth_stencil_attachment_ = std::make_shared<texture_2d>("depth_stencil", _width, _height, sized_format::depth24_stencil8);
    glNamedFramebufferTexture(handle_, GL_DEPTH_STENCIL_ATTACHMENT, depth_stencil_attachment_->handle(), 0);
}

GLSL Code:

uniform sampler2D u_texture_gbuffer_position;
uniform sampler2D u_texture_gbuffer_normal;
uniform sampler2D u_texture_gbuffer_albedo;
uniform sampler2D u_texture_gbuffer_specular;
uniform sampler2D u_texture_gbuffer_gloss;

const vec3 position = texture(u_texture_gbuffer_position, io_tex_coord.xy).rgb; // All zeros.
const vec3 normal = texture(u_texture_gbuffer_normal, io_tex_coord.xy).rgb; // All zeroes.
const vec4 albedo = texture(u_texture_gbuffer_albedo, io_tex_coord.xy); // Has correct values.
const vec4 specular = texture(u_texture_gbuffer_specular, io_tex_coord.xy); // Has correct values.
const float gloss = texture(u_texture_gbuffer_gloss, io_tex_coord.xy).r; // All zeroes.

答案1

得分: 0

我修复了这个问题。GL_BLEND被启用,这意味着任何 alpha 值为 0 的片段实际上被丢弃了。

所以,即使我只写入了一个或三个分量的纹理,因为它们的默认 alpha 值是 0.0f,甚至它们的 RGB 值也因某种原因被丢弃了。

所以解决方案是在几何通道期间禁用 GL_BLEND,以确保所有纹理被正确写入,而不会丢弃它们的值。

英文:

I fixed the issue. GL_BLEND was enabled, which means that any fragments with an alpha value of 0 is essentially discarded.

So even though I was writing to a texture with only 1 or 3 components, because by default their alpha value was 0.0f, even their RGB value was discarded for some reason.

So the solution was to disable GL_BLEND during my geometry pass to ensure that all textures are written to correctly without their values being discarded.

huangapple
  • 本文由 发表于 2023年2月7日 01:57:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75364920.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定