MSAA和顶点插值导致值超出范围

问题描述

我正在将GLSL与顶点着色器和片段着色器一起使用。

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

当它到达片段着色器时,我看到的值(在三角形边缘)至少超过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,1,1); return; }

当然,对于MSAA 4x,这是OpenGL生成的图像。 (观察窗口中心的磁性彩色像素。)

magenta pixels

我已经排除了非数字值。

GL_VERSION:3.2.0 NVIDIA 450.51.06

解决方法

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

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

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

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

但是,通过将FS调用值与深度采样相除,我们现在遇到一个问题:单个FS调用恰好在哪里在像素区域内执行?

这就是我们遇到的问题。如果FS调用在原语区域之外的位置执行,则通常会被扔掉。但是,如果在基元区域内有任何深度样本,则这些深度样本仍需要获取颜色数据。而且MSAA的全部目的是不对每个样本执行FS,因此它们可以从在不同位置执行的FS调用中获取颜色数据。

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

但是某些算法确实存在问题。这就是为什么我们有the centroid qualifier for fragment shader inputs。这样可以确保在图元区域内生成特定的插值。

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...