【问题标题】:How to do a branchless discard?如何进行无分支丢弃?
【发布时间】:2021-05-03 16:51:39
【问题描述】:

我有一个相当基本的片段着色器,它可以从纹理中采样并根据样本更改分配的固定颜色。如果我从纹理中采样,我会进行 alpha 检查并丢弃低 alpha 值。有没有办法让这个过程无分支?

#version 460 core
layout (location = 0) out vec4 FragColor;

uniform vec4 color;
uniform sampler2D tex;
uniform bool useTex;
in vec2 texCoords;

void main() {
   vec4 tex = texture(tex, texCoords);
   if(useTex && tex.a < 0.1) { discard; }
   vec4 outColor = mix(color, color * tex, int(useTex));
   FragColor = outColor;
}

【问题讨论】:

  • 我认为这是不可能的。为什么你希望它成为可能?
  • alpha 为 0 的像素与不存在的像素不同。 stackoverflow.com/questions/27575878/…
  • @DogaOruc:让我再解释一下:“分支”是什么意思?你指的是performance cost of conditions吗? having a discard in your shader at all的性能成本?还是别的什么?
  • 您有没有想过您的“无分支”混合解决方案实际上比使用适当的分支更糟糕?在你的情况下,一个包含整个 texture 调用的统一分支会更有意义,如果你真的很幸运,着色器编译器甚至可能会看到,但我不会打赌。
  • GPU 上分支的问题是控制流发散,其中 GPU 必须执行两个分支,只是因为组中的任何单个调用都需要它。您的无分支解决方案是始终无条件地执行两个代码路径。但是,原始分支永远不会导致控制流发散,因为条件 useTex 是统一的。

标签: opengl glsl opengl-3 opengl-4


【解决方案1】:

我建议始终绑定一个纹理,至少一个 1x1 的纹理与颜色 (1, 1, 1, 1)。使用这种方法,您可以完全省略 useTex,并且着色器更加简单:

#version 460 core

layout (location = 0) out vec4 FragColor;

uniform vec4 color;
uniform sampler2D tex;
in vec2 texCoords;

void main() 
{
    vec4 outColor = color * texture(tex, texCoords);
    if (outColor.a < 0.1)
        discard;
    FragColor = outColor;
}

如果您可以使用Blending 而不是discard,则可以进一步简化着色器:

#version 460 core

layout (location = 0) out vec4 FragColor;

uniform vec4 color;
uniform sampler2D tex;
in vec2 texCoords;

void main() 
{
    FragColor = color * texture(tex, texCoords);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-19
    • 2021-11-07
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 2014-03-31
    相关资源
    最近更新 更多