问题描述
我正在将GLSL与顶点着色器和片段着色器一起使用。
顶点着色器输出highp float
,范围为[0,1]
当它到达片段着色器时,我看到的值(在三角形边缘)至少超过1.1!
如果我...这个问题就消失了
- 禁用MSAA
- 或使用GLSL interpolation qualifier
flat
禁用插值。
如果启用了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生成的图像。 (观察窗口中心的磁性彩色像素。)
我已经排除了非数字值。
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
插值要慢。因此,仅在需要时使用它。