使用' discard'在具有多重采样

时间:2017-04-12 08:58:18

标签: opengl glsl fragment-shader multisampling

我尝试在启用多重采样的情况下尝试深度剥离,并且在透明层中出现一些错误数据的问题。我使用以下内容检查样本(最初是片段)是否对此传递有效:

float depth = texelFetch(depthMinima, ivec2(gl_FragCoord.xy), gl_SampleID).r;
if (gl_FragCoord.z <= depth)
{
    discard;
}

depthMinima定义为

uniform sampler2DMS depthMinima;

我启用了GL_SAMPLE_SHADING,如果我理解正确的话,应该导致在每个样本的基础上调用片段着色器。如果不是这样的话,有没有办法让这件事发生?

结果是第一层或第二层看起来正确,但在那之下(我做了8层)我开始得到垃圾值 - 大部分是纯蓝色,有时是前一层的值。

这适用于单采样缓冲区,但不适用于多采样缓冲区。 discard关键字是否仍会丢弃整个片段?

2 个答案:

答案 0 :(得分:1)

  

我启用了GL_SAMPLE_SHADING,如果我理解正确的话,应该导致基于每个样本调用片段着色器。

仅启用GL_SAMPLE_SHADING是不够的。您还需要设置:

glMinSampleShading(1.0f)
  

值1.0表示帧缓冲区中的每个样本都应该是独立着色的。值0.0有效地允许GL忽略采样率着色。 0.0到1.0之间的任何值都允许GL仅遮蔽每个覆盖片段中的总样本的子集。哪些样本带阴影,用于选择片段样本子集的算法取决于实现。

     

- glMinSampleShading

换句话说,1.0告诉它遮蔽所有样本。 0.5告诉它至少遮半样品。

// Check the current value
GLfloat value;
glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE, &value);

如果GL_MULTISAMPLEGL_SAMPLE_SHADING被禁用,则样本着色无效。

每个片段都会有多个片段着色器调用,每个片段都是片段的子集。换一种说法。样本着色指定了每个片段要处理的最小样本数。

如果GL_MIN_SAMPLE_SHADING_VALUE设置为1.0,则会为每个样本(在基元内)发出片段着色器调用。 如果设置为0.5,那么每隔一个样本就会有一个着色器调用。

max(ceil(MIN_SAMPLE_SHADING_VALUE * SAMPLES), 1)

每个人都在他们的样本位置(gl_SamplePosition)进行评估。 gl_SampleID是当前正在处理的样本的索引。

  

应该逐个丢弃工作,还是只能按片段工作?

使用或不使用样本着色discard仍然只会终止对着色器的单次调用。

资源:

答案 1 :(得分:0)

在多样本缓冲区上使用depth_peeling时,我遇到了类似的问题。

当使用来自先前果皮的多样本深度纹理和当前片段深度时,由于depth_test错误而出现一些伪像。

vec4 previous_peel_depth_tex = texelFetch(previous_peel_depth, coord, 0);

第三个参数是您要用于比较的样本,它将提供与片段中心不同的值。就像作者所说的,您可以使用gl_SampleID

vec4 previous_peel_depth_tex = texelFetch(previous_peel_depth, ivec2(gl_FragCoord.xy), gl_SampleID);

这解决了我的问题,但是性能下降很大,如果有4个样本,则片段着色器将运行4次,如果有4个剥离,则意味着4x4调用。如果至少打开glEnable(GL_MULTISAMPLE);,则无需设置opengl标志

在片段着色器中任何静态使用[gl_SampleID]都会导致整个 要对每个样本进行评估的着色器

我决定使用其他方法,并在进行深度比较时增加偏差

float previous_linearized = linearize_depth(previous_peel_depth_tex.r, near, far);
float current_linearized = linearize_depth(gl_FragCoord.z, near, far);

float bias_meter = 0.05;
bool belong_to_previous_peel = delta_depth < bias_meter;

这解决了我的问题,但某些伪影可能仍然出现,您需要以eye_space单位(米,厘米,...)调整偏差