glsl - MSAA 和顶点插值导致超出范围的值
问题描述
我正在使用带有顶点着色器和片段着色器的GLSL 。
顶点着色器输出highp float
[0,1] 范围内的a
当它到达片段着色器时,我看到值(在三角形边缘)超过 1.1 不少!
如果我...
- 要么禁用 MSAA
- 或者使用 GLSL插值限定符
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,0,1,1); return; }
果然,使用 MSAA 4x,这是 OpenGL 生成的图像。(观察窗口中心的磁彩色像素。)
我已经排除了非数字值。
GL_VERSION:3.2.0 英伟达 450.51.06
解决方案
如果启用了 MSAA,钳位的 0 到 1 高精度浮点数如何以远大于 1 的值到达片段着色器?
多重采样的核心是超级采样的一种变体:从图元的像素大小区域获取多个样本。对该像素大小区域的空间内的不同位置进行采样以产生结果值。
但是,当您处于图元的边缘时,该像素大小区域中的某些位置超出了图元实际覆盖的区域。在超级采样中很好;你只是不使用这些样本。
但是,多重采样是不同的。在多重采样中,深度样本不同于片段着色器生成的样本。也就是说,系统可能只执行一次 FS,但会获取 4 个深度样本并针对深度缓冲区中的 4 个样本进行测试。通过深度测试的任何样本都从执行的单个 FS 调用中获取其颜色值。如果这 4 个深度样本中的一些在图元区域之外,那很好;他们不算数。
但是,通过将 FS 调用值从深度采样中分离出来,我们现在遇到了一个问题:单个 FS 调用在像素区域内究竟是在哪里执行的?
这就是我们遇到问题的地方。如果 FS 调用在原语区域之外的位置执行,通常会被丢弃。但是如果任何深度样本都在图元区域内,那么这些深度样本仍然需要获取颜色数据。MSAA 的重点是不对每个样本执行 FS,因此它们可能会从在不同位置执行的 FS 调用中获取颜色数据。
理想情况下,它将来自在原语区域内的某个位置上执行的 FS 调用。但硬件不能保证这一点。好吧,无论如何,它不能默认保证它。如果 FS 位置恰好落在基元区域之外,则并非每个算法都有问题。
但有些算法确实存在问题。这就是为什么我们有片段着色器输入的centroid
限定符。它确保将在图元区域内生成特定的插值。
正如您可能已经猜到的那样,这不是默认值,因为它比非centroid
插值慢。因此,仅在需要时使用它。
推荐阅读
- php - 如何列出属于自定义分类的帖子类别
- forms - 如何验证表单字段是否为空
- css - 如何使用 css 编辑材料 ui 表中的行高
- r - 提取固定效应系数时与“EXPR 必须是长度为 1 的向量”相关的错误
- etl - Pentaho 连接到 Sisense elasticCube
- sql - 与关系返回所有行,最大为一列 Sql Sever
- c++ - 通过引用传递向量正在请求 std::allocator
- r - R else if语句中的意外标记“else”
- angular - 使用 Angular 响应式表单动态更改表单字段的颜色
- groovy - 如何向“readProperties 文件”添加其他属性?