1

我在一些变体中实现了对 MSAA 的支持:

它可以使用基于上下文(通过在设置上下文时调用 wglChoosePixelFormatARB 并将相应的参数列表传递给它)或通过启用 MSAA 渲染到 FBO(创建一个带有颜色和深度渲染缓冲区附件的多采样 FBO,以及另一个带有颜色附件的 FBO用于解决),并且抗锯齿似乎在整体上起作用。

然而,当我启用抗锯齿时,我发现了一些似乎与镜面反射照明有关的伪影。这对于基于上下文的 CSAA 来说是最差的,对于基于上下文的 MSAA 来说非常糟糕,但是当我在渲染到我的 FBO 时使用 MSAA 时会好得多。

对于我用于测试的其中一种飞机模型,它非常引人注目,尤其是在发动机气缸和一些“电线”周围(它们实际上不是线,而是细气缸):

结果比较

正如您在图像上看到的,当我关闭镜面反射光时,问题几乎消失了,但我不太确定是什么原因造成的。

上面的图像使用这个着色器代码来计算镜面反射(在所有灯光的循环内):

if( matShininess > 0.0 )
{
    vec3 reflectionCamSpace = reflect(-lightDirectionCamSpace, faceNormal);
    vec3 surfToViewerCamSpace = normalize (-vertPositionCamSpace);
    float dotSpecular = max( 0.0, dot (reflectionCamSpace, surfToViewerCamSpace) );
    float specularFactor = pow( dotSpecular, matShininess );
    specularTerm += vec3(lgt.specular * specularFactor); 
}

不同的照明模型之间似乎也存在很大差异:

照明模型

左侧使用上述代码进行镜面高光,而右侧使用此代码(再次在主光循环内,迭代所有灯光)

if( matShininess > 0.0 )
{
    vec3 surfToViewerCamSpace = normalize (-vertPositionCamSpace);
    vec3 halfAngle = normalize(lightDirectionCamSpace + surfToViewerCamSpace);
    float specularFactor = dot(faceNormal, halfAngle);
    specularFactor = clamp(specularFactor, 0, 1);
    specularFactor = lightDot != 0.0 ? specularFactor : 0.0;
    specularFactor = pow(specularFactor, matShininess);
    specularTerm += vec3(lgt.specular * specularFactor);
}

所以我想知道为什么在使用基于 FBO 的 MSAA 和基于上下文的 MSAA 时会有如此大的差异。还有我做错了什么我的镜面高光首先造成了问题?

编辑:按照下面帖子的要求,我还添加了一个测试,用于通过上下文和 FBO 比较 16xQ CSAA 的结果(对于 FBO,我只是使用 RenderbufferStorageMultisampleCoverageNV 而不是 glRenderbufferStorageMultisample)。同样,FBO 结果似乎更好(但仍不令人信服):

16xQ CSAA Ctx 与 FBO

4

1 回答 1

1

这不是答案;更像是一个冗长的评论请求。

样本着色可能会有所帮助,您可以告诉 GL 多次评估着色器,而不是对每个片段进行一次计算并将结果传递给所有样本(如果覆盖率允许这种优化)。使用 MSAA,着色器仅针对其图元完全覆盖一个像素的片段进行一次评估。每个样本的深度/模板样本是唯一的,这有助于边缘混叠,但在着色器本身内发生的任何混叠(例如纹理混叠、镜面高光等)都无法使用纯 MSAA 进行校正。

样本着色有效地将 MSAA 转换为介于 MSAA(多个样本可能被着色一次)到 SSAA(1:1 样本:着色比)之间的东西。为什么您的问题只显示使用默认帧缓冲区执行的 MSAA 解析,我不能说。但是样本阴影应该会有所帮助。

至于 CSAA,这完全超出了未扩展 GL 所能控制的范围。vanilla GL管道中的任何地方都没有CSAA的概念。NV_framebuffer_multisample_coverage如果你使用 NV 的扩展,你可以使用 FBO 来实现它。

老实说,这些天我几乎总是偏爱基于 FBO 的抗锯齿。如果这样做,您不必为最终用户重新创建渲染上下文来更改 AA 设置,这意味着如果用户开始尝试性能/图像质量的配置设置,则重新加载的资源会大大减少。这是一个更加灵活的设计,您甚至可以在现代硬件上使用 FBO 进行 MSAA 延迟着色,这要归功于多重采样纹理提取(您可以在着色器级别实现解析)。

我很想知道您是否经历过基于上下文和基于 FBO 的 CSAA 之间的任何差异,或者明确设置着色样本的最小数量是否有任何影响。

于 2014-02-04T18:27:36.147 回答