【问题标题】:OpenGL texture artifactingOpenGL纹理伪影
【发布时间】:2022-01-21 04:51:50
【问题描述】:

我已经为 2D 实现了一个简单的批处理渲染设置。它似乎正在工作,除了一些看起来像在单个表面上进行 Z 战斗的工件。

TL;博士?我录制了a video,展示了我所看到的以及“修复”它的方法。

绑定了三个纹理:

  • 1x1 大小的纯白色纹理
  • 草木平铺的“背景”纹理
  • 一个简单的木箱

有些四边形只有纹理,有些只用纯色着色,还有一些是纹理和着色的。

这是顶点着色器:

#version 460 core

layout(location = 0) in vec3  _position;
layout(location = 1) in vec4  _color;
layout(location = 2) in vec2  _texture_coords;
layout(location = 3) in int   _texture_index;
layout(location = 4) in float _tiling_factor;

uniform mat4 viewproj_matrix;

out vec4     color;
out vec2     texture_coords;
out flat int texture_index;
out float    tiling_factor;

void main()
{
    color          = _color;
    texture_coords = _texture_coords;
    texture_index  = _texture_index;
    tiling_factor  = _tiling_factor;
    
    gl_Position = viewproj_matrix * vec4(_position, 1.0);
}

片段着色器:

#version 460 core

layout(location = 0) out vec4 final_color;

in vec4     color;
in vec2     texture_coords;
in flat int texture_index;
in float    tiling_factor;

uniform sampler2D textures[32];

void main()
{
    final_color = (
        texture(textures[texture_index], texture_coords * tiling_factor) * color
    );
}

当然,这很简单。不过我也是新手,这么简单就好。这种行为似乎与采样多个纹理有关。我这么说是因为,正如我在视频中演示的那样,如果我只对三个绑定纹理中的一个进行采样,伪影就会消失。当我强制批次大小为单个四边形时,这种情况也会自行解决。

这里是绘制平面阴影四边形的代码:

void Renderer2D::draw_quad(const RenderAPI &api, const glm::vec3 &position,
                        const glm::vec4 &color,
                        const float rotation, const glm::vec3 &scale) {
    if(_batch.quad_count >= _batch.max_quads) {
        _flush_and_reset();
    }

    _batch.api = &api;

    glm::mat4 transform = glm::translate(_ident, position) *
                        glm::rotate(_ident, glm::radians(rotation), _z_axis) *
                        glm::scale(_ident, scale);

    for(uint32_t corner = 0; corner < _corners_per_quad; corner++) {
        _batch.vertex_buffer_ptr->position = transform * _vertex_coords[corner];
        _batch.vertex_buffer_ptr->color         = color;
        _batch.vertex_buffer_ptr->texture_coord = _texture_coords[corner];
        _batch.vertex_buffer_ptr->texture_index = _white_texture_index;
        _batch.vertex_buffer_ptr->tiling_factor = _default_tiling;

        _batch.vertex_buffer_ptr++;
    }

    _batch.quad_count++;

    _stats.quad_count++;
}

如果您对更多内容感兴趣,这里是the whole Renderer2D class。希望这是足够的信息,但整个 shebang 中也没有那么多代码。

我正在努力寻找解决问题的角度。欢迎任何指导、理论、指针或猜测。我期待着加强我的 GPU/3D 数学/等调试技能。 =)

【问题讨论】:

    标签: c++ opengl glsl glm-math


    【解决方案1】:

    看起来您正试图在单个 invocation group 中渲染多个纹理。这意味着您正在使用不是dynamically uniform 的变量对纹理进行采样。这会导致采样丢失implicit derivatives,事实上它们变得未定义。

    有很多方法可以拆分调用组,这样您就可以以动态统一的方式对纹理进行采样。您可以使用 3D 纹理来保存所有不同的纹理,尽管这要求所有纹理的大小相同,或者使用纹理图集。另一种方法是为每个独特的纹理使用单独的绘制调用,或者更好地使用MultiDraw 命令,这是同一件事,但可以将多个绘制调用组合成一个,同时保持调用组分开。

    【讨论】:

    • 这是一个非常详细和慷慨的教育答案。太感谢了!我将继续阅读和学习,并带着我的结果回到这个话题。再次谢谢你。 =)
    猜你喜欢
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 2018-07-03
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多