首页 > 解决方案 > MSAA 和顶点插值导致超出范围的值

问题描述

我正在使用带有顶点着色器和片段着色器的GLSL 。

顶点着色器输出highp float[0,1] 范围内的a

当它到达片段着色器时,我看到值(在三角形边缘)超过 1.1 不少!

如果我...

如果启用了 MSAA,钳位的 0 到 1 高精度浮点数如何以远大于 1 的值到达片段着色器?

顶点着色器代码:

out highp float lightcontrib2;
...
lightcontrib2 = clamp( irrad, 0.0, 1.0 );

片段着色器代码:

in highp float lightcontrib2;
...
if (lightcontrib2>1.1) { fragColor = vec4(1,0,1,1); return; }

果然,使用 MSAA 4x,这是 OpenGL 生成的图像。(观察窗口中心的磁彩色像素。)

品红色像素

我已经排除了非数字值。

GL_VERSION:3.2.0 英伟达 450.51.06

标签: glslinterpolationmsaa

解决方案


如果启用了 MSAA,钳位的 0 到 1 高精度浮点数如何以远大于 1 的值到达片段着色器?

多重采样的核心是超级采样的一种变体:从图元的像素大小区域获取多个样本。对该像素大小区域的空间内的不同位置进行采样以产生结果值。

但是,当您处于图元的边缘时,该像素大小区域中的某些位置超出了图元实际覆盖的区域。在超级采样中很好;你只是不使用这些样本。

但是,多重采样是不同的。在多重采样中,深度样本不同于片段着色器生成的样本。也就是说,系统可能只执行一次 FS,但会获取 4 个深度样本并针对深度缓冲区中的 4 个样本进行测试。通过深度测试的任何样本都从执行的单个 FS 调用中获取其颜色值。如果这 4 个深度样本中的一些在图元区域之外,那很好;他们不算数。

但是,通过将 FS 调用值从深度采样中分离出来,我们现在遇到了一个问题:单个 FS 调用在像素区域内究竟是在哪里执行的?

这就是我们遇到问题的地方。如果 FS 调用在原语区域之外的位置执行,通常会被丢弃。但是如果任何深度样本都在图元区域内,那么这些深度样本仍然需要获取颜色数据。MSAA 的重点是不对每个样本执行 FS,因此它们可能会从在不同位置执行的 FS 调用中获取颜色数据。

理想情况下,它将来自在原语区域内的某个位置上执行的 FS 调用。但硬件不能保证这一点。好吧,无论如何,它不能默认保证它。如果 FS 位置恰好落在基元区域之外,则并非每个算法都有问题。

但有些算法确实存在问题。这就是为什么我们有片段着色器输入centroid限定符。它确保将在图元区域内生成特定的插值。

正如您可能已经猜到的那样,这不是默认值,因为它比非centroid插值慢。因此,仅在需要时使用它。


推荐阅读