简体   繁体   English

在具有多重采样的 GLSL 4.1 片段着色器中使用“丢弃”

[英]Using 'discard' in GLSL 4.1 fragment shader with multisampling

I'm attempting depth peeling with multisampling enabled, and having some issues with incorrect data ending up in my transparent layers.我正在尝试在启用多重采样的情况下进行深度剥离,并且在我的透明图层中出现了错误数据的一些问题。 I use the following to check if a sample (originally a fragment) is valid for this pass:我使用以下内容来检查样本(最初是片段)是否对本次通过有效:

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

Where depthMinima is defined as其中depthMinima定义为

uniform sampler2DMS depthMinima;

I have enabled GL_SAMPLE_SHADING which, if I understand correctly, should result in the fragment shader being called on a per-sample basis.我启用了GL_SAMPLE_SHADING ,如果我理解正确,它应该会导致在每个样本的基础上调用片段着色器。 If this isn't the case, is there a way I can get this to happen?如果不是这种情况,有什么办法可以让这种情况发生吗?

The result is that the first layer or two look right, but beneath that (and I'm doing 8 layers) I start getting junk values - mostly plain blue, sometimes values from previous layers.结果是第一层或第二层看起来是正确的,但在其之下(我正在做 8 层),我开始获得垃圾值 - 主要是纯蓝色,有时是来自前一层的值。

This works fine for single-sampled buffers, but not for multi-sampled buffers.这适用于单采样缓冲区,但不适用于多采样缓冲区。 Does the discard keyword still discard the entire fragment?丢弃关键字是否仍然丢弃整个片段?

I have enabled GL_SAMPLE_SHADING which, if I understand correctly, should result in the fragment shader being called on a per-sample basis.我启用了 GL_SAMPLE_SHADING,如果我理解正确,它应该会导致在每个样本的基础上调用片段着色器。

It's not enough to only enable GL_SAMPLE_SHADING .仅启用GL_SAMPLE_SHADING You also need to set:您还需要设置:

glMinSampleShading(1.0f)

A value of 1.0 indicates that each sample in the framebuffer should be indpendently shaded.值 1.0 表示帧缓冲区中的每个样本都应该独立着色。 A value of 0.0 effectively allows the GL to ignore sample rate shading.值 0.0 有效地允许 GL 忽略采样率阴影。 Any value between 0.0 and 1.0 allows the GL to shade only a subset of the total samples within each covered fragment. 0.0 和 1.0 之间的任何值都允许 GL 仅对每个覆盖片段内的总样本的一个子集进行着色。 Which samples are shaded and the algorithm used to select that subset of the fragment's samples is implementation dependent.哪些样本被着色以及用于选择片段样本的子集的算法取决于实现。

glMinSampleShading glMinSampleShading

In other words 1.0 tells it to shade all samples.换句话说, 1.0告诉它对所有样本进行着色。 0.5 tells it to shade at least half the samples. 0.5告诉它至少遮蔽一半的样本。

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

If either GL_MULTISAMPLE or GL_SAMPLE_SHADING is disabled then sample shading has no effect.如果GL_MULTISAMPLEGL_SAMPLE_SHADING被禁用,则样本着色不起作用。

There'll be multiple fragment shader invocations for each fragment, to which each sample is a subset of the fragment.每个片段都会有多个片段着色器调用,每个样本都是片段的子集。 In other words.换句话说。 Sample shading specifies the minimum number of samples to process for each fragment.样本着色指定要为每个片段处理的最小样本数。

If GL_MIN_SAMPLE_SHADING_VALUE is set to 1.0 then there'll be issued a fragment shader invocation for each sample (within the primitive).如果GL_MIN_SAMPLE_SHADING_VALUE设置为1.0那么将为每个样本(在基元内)发出片段着色器调用。 If its set to 0.5 then there'll be a shader invocation for every second sample.如果它设置为0.5那么每隔一个样本就会有一个着色器调用。

max(ceil(MIN_SAMPLE_SHADING_VALUE * SAMPLES), 1)

Each being evaluated at their sample location ( gl_SamplePosition ).每个都在其样本位置( gl_SamplePosition )进行评估。 With gl_SampleID being the index of the sample that is currently being processed. gl_SampleID是当前正在处理的样本的索引。

Should discard work on a per-sample basis, or does it still only work per-fragment?应该在每个样本的基础上丢弃工作,还是仍然只对每个片段起作用?

With or without sample shading discard still only terminate a single invocation of the shader.有或没有样本着色discard仍然只终止着色器的单个调用。

Resources:资源:

I faced a similar problem when using depth_peeling on a multi-sample buffer.在多样本缓冲区上使用 depth_peeling 时,我遇到了类似的问题。

Some artifacts appears due to the depth_test error when using a multi_sample depth texture from the previous peel and the current fragment depth.使用来自前一个果皮和当前片段深度的 multi_sample 深度纹理时,由于 depth_test 错误,会出现一些伪影。

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

the third argument is the sample you want to use for your comparison which will give a different value from the fragment center.第三个参数是您要用于比较的样本,它将给出与片段中心不同的值。 Like the author said you can use gl_SampleID就像作者说的你可以使用 gl_SampleID

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

This solved my problem but with a huge performance drop, if you have 4 samples you will run your fragment shader 4 times, if 4 have peels it means 4x4 calls.这解决了我的问题,但性能下降很大,如果您有 4 个样本,您将运行片段着色器 4 次,如果 4 个有剥离,则意味着 4x4 调用。 You don't need to set the opengl flags if atleast glEnable(GL_MULTISAMPLE);如果至少glEnable(GL_MULTISAMPLE);你不需要设置 opengl 标志glEnable(GL_MULTISAMPLE); is on开着

Any static use of [gl_SampleID] in a fragment shader causes the entire shader to be evaluated per-sample在片段着色器中对 [gl_SampleID] 的任何静态使用都会导致对每个样本评估整个着色器

I decided to use a different approach and to add a bias when doing the depth comparison我决定使用不同的方法并在进行深度比较时添加偏差

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;

This solve my problem but some artifacts might still appears and you need to adjust your bias in your eye_space units (meter, cm, ...)这解决了我的问题,但可能仍会出现一些伪影,您需要调整您的 eye_space 单位(米,厘米,...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM