【问题标题】:CSAA/MSAA and specular lightsCSAA/MSAA 和镜面光
【发布时间】:2014-02-04 10:01:43
【问题描述】:

我已经在一些变体中实现了对 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 结果似乎更好(但仍不能令人信服):

【问题讨论】:

  • 您好,您的图片链接已损坏,您可以修复它们吗?我有兴趣看看:)
  • 您好,我只是去寻找我的硬盘上的图像...我记得我之前将它们上传到我的 AWS,但是当我不久前进行一些清理时它们似乎被删除了,我在我的硬盘上也找不到它们了现在正在寻找(抱歉,当我转移到另一个项目时,我似乎抹去了我的大脑记忆哈哈)
  • 大声笑,好吧,没关系,我不想让你太无聊 :) 无论如何,如果你能写一些关于你实现的抗锯齿技术的总结,我将不胜感激
  • 哦,我确实设法再次找到了那些照片(只是不在我预期的地方,哈哈)......所以我再次上传它们,即应该再次正常工作

标签: opengl glsl msaa


【解决方案1】:

这不是答案;更像是对 cme​​ts 的冗长请求。

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

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

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

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

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

【讨论】:

  • @andon-m-coleman 请参阅我上面的帖子的编辑,我通过 FBO 添加了对 CSAA 的支持以及您提到的扩展。同样,FBO(图像右侧)的结果似乎比通过上下文(左侧)更好
  • P.S 我稍后会阅读示例着色等,感谢您的提示,但首先我想弄清楚我目前哪里出了问题,以及为什么我的镜面光照会导致这些问题
猜你喜欢
  • 2012-10-28
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
  • 2015-08-29
  • 2020-07-24
相关资源
最近更新 更多