【问题标题】:Pixel fill percentage by geometry for GLSL pixel shaderGLSL 像素着色器的几何像素填充百分比
【发布时间】:2023-02-23 00:33:41
【问题描述】:

是否有可能在 GLSL 像素着色器中从 0 到 1 计算一个像素被它绘制的几何图形填充的程度?

简单示例:空间中的立方体将在 2d 屏幕空间中大部分 100% 填充在立方体 2d 投影的内部,但从技术上讲,边界周围的这些像素可以由几何体本身部分填充(在 0.0 和 1.0 之间)

我知道多重采样和抗锯齿处理这个问题,但这是一个特定的计算应用程序,我们无法承受太多额外的处理。我需要确定实际的小数填充值。

在实际用例中,几何形状并不简单,不能可靠地假设为特定形状。

研究多重采样,因为这是我知道的唯一可能有帮助的内置方法。

【问题讨论】:

  • GL_POLYGON_SMOOTH 将计算三角形的分析覆盖率;但它对复杂的形状根本没有用。如果您想要一个快速简单的解决方案,多重采样是您最好的选择。
  • 谢谢,您能否详细说明 GL_POLYGON_SMOOTH 方法?
  • 您只需执行 glEnable(GL_POLYGON_SMOOTH),OpenGL 会将片段 alpha 乘以分析覆盖率。你无法控制它。没什么可细说的。我告诉过你这没有用。您真的应该更好地描述您要解决的问题。例如。你说的是在太空中画一个立方体。但是 OpenGL 不知道如何绘制立方体;相反,它一次光栅化一个三角形。因此,如果您确实需要覆盖立方体而不是单个图元,OpenGL 无法为您完成。还要解释为什么多重采样不能降低成本;它很便宜。
  • 感谢您的信息。听起来多重采样是唯一可行的选择。我们在一个复杂的不一致模型上获取纹理中的状态值,并根据角度和光照将它们绘制到屏幕上。轮廓别名正在降低准确性。如果 MS 便宜,我们会尝试。理想情况是在片段着色器内部,我们可以访问一个从 0 到 1 的分析覆盖值,这样我们就可以在数学中使用它来计算状态输出,它用于状态计算本身。
  • 这是什么意思? “状态值”、“不一致的模型”?您应该知道,即使您在片段着色器中获得的 MS 覆盖率也在深度测试之前。

标签: opengl glsl fragment-shader


【解决方案1】:

GL_PLOYGON_SMOOTH

OpenGL 确实支持使用 glEnable(GL_POLYGON_SMOOTH) 对单个三角形进行分析抗锯齿。然而,它在片段着色器执行后就已经将覆盖应用到 alpha。因此,要使用它,您需要一次将一个三角形光栅化为纹理,然后运行第二遍从该纹理读取覆盖值。 “一次一个三角形”的要求是处理相邻三角形之间的共享边。沿共享边的像素将被光栅化两次,并且不可能合并覆盖范围以沿共享边产生 1.0 值,同时在其他地方保持正确。

这些限制是 OpenGL 的这个特性很少被使用的部分原因。

保守光栅 + 重心

GL_POLYGON_SMOOTH 的替代方法是将保守光栅化与手动检查重心坐标相结合。最高效的方法是使用 GL_NV_conservative_rasterGL_NV_fragment_shader_barycentric 扩展。在没有扩展的情况下,使用几何着色器和插值属性可以使用未扩展的 OpenGL 实现相同的效果,尽管它会带来性能损失。

这将消除一次将一个三角形渲染到临时纹理中的需要,而是允许在一个批次中处理所有几何体。但是,它仍然存在相同的问题,即共享三角形边缘上的像素将使用部分覆盖值进行多次光栅化,并且没有办法以稳健的方式组合这些像素。

多重采样

看来多重采样是你所需要的。归根结底,这正是它要解决的问题。当然,它不会为您提供分析覆盖所能提供的全部精度,但它会正确处理共享边。

但是,请记住,您在片段着色器中获得的覆盖率值先于深度测试。因此你将要需要实施两遍解决方案。在第一遍将所有几何体渲染到一个临时的多重采样纹理中。然后运行第二遍,从纹理中读取覆盖范围(和其他属性)并运行您需要该覆盖范围的任何代码。


该答案完全基于您了解“渲染立方体时”或“其他复杂几何体”的覆盖值的请求。在不知道您需要什么覆盖值的情况下,我无法提供任何替代方法来解决您的实际问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 2017-07-14
    相关资源
    最近更新 更多