代码之家  ›  专栏  ›  技术社区  ›  Andrew

平面着色需要这么多顶点复制吗?

  •  0
  • Andrew  · 技术社区  · 5 年前

    我对WebGL(1.0)/OpenGL非常陌生,我很难理解平面和平滑着色的顶点,以及在这种情况下,平面着色的数据优化是否可行:

    假设我想使用二十面体(2-细分)。它有42个点,定义了它的80个面。这些点坐标位于单位球面上。

    平坦和平滑的着色icosophers都将出现在同一屏幕上。

    使用平滑着色,法线将与位置矢量相同,因此我可以免费获得它们。所以我可以用42 vec3 两者都在一个缓冲区中 a_position v_normal 索引缓冲区为240 unsigned_byte 为对象访问它们。便宜的!

    但有了平坦的阴影,每个 脸会有自己的正常, 我认为这意味着对于WebGL 1.0,每张脸都有三条重复的法线。80张脸意味着240张 vec3 对于 a_position (有很多重复向量)和240 vec3 对于 a_normal (其中三分之二只是重复向量)。我看不出还有别的办法。另一方面,我可以在同一个缓冲区中同时添加位置和法线数据,而不需要索引缓冲区。

    我已经做到了,而且看起来很快,但我说的对吗?这有关系吗?

    冰圈特性 计数 需要浮动
    面孔 80
    位置(平滑) 42 126(+240指数)
    法线(平滑) 42 0(重复使用位置)
    位置(平坦) 240 720
    正常值(平坦) 240 720

    我觉得我在学习中错过了一些东西,或者这只是OpenGL的现实,我应该习惯它,因为它天生就很快。

    1 回复  |  直到 5 年前
        1
  •  3
  •   datenwolf    5 年前

    你说得对,对于平面着色,你必须复制位置。也就是说,因为顶点是位置、法线和所有其他属性的完整元组。

    然而,这种重复对渲染时间几乎没有影响。是的,它增加了一些内存开销,但就渲染过程而言,相同数量的数据被传输并合并到渲染过程中。事实上,整体上某些属性的重复使缓存更具可预测性,因为不涉及数据间接性(即根据渲染的人脸查找不同的法线)。因此,这实际上具有理论上的性能提升。

    你做得完全正确。

        2
  •  2
  •   gkv311    5 年前

    事实上,最便携的平面着色实现将需要为每个绘制的三角形复制顶点,这会带来内存使用的开销(在复杂几何体的情况下相当大)。它也可能影响渲染性能,但这取决于硬件(现在不应该被注意到)。这就是基本的WebGL 1.0所允许的。

    然而,WebGL 2.0和WebGL 1.0 OES_standard_derivatives 扩展提供了另一种选择-通过导数直接在Fragment Shader中计算三角法线:

    #extension GL_OES_standard_derivatives : enable
    ...
    varying vec4 Position;
    varying vec3 View;
    ...
    void main()
    {
      vec3 Normal = normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));
      if (!gl_FrontFacing) { Normal = -Normal; }
      ...
      gl_FragColor = computeLighting (normalize (Normal), normalize (View), Position);
    

    这需要每个片段的照明(例如。 Phong shading 而不是Gouraud阴影)。着色结果与在CPU上复制顶点和预先计算三角形法线并不完全相同,但视觉效果将是相同的——具有可区分三角形的平面着色。

    实际上, GL_OES_standard_derivatives 被广泛采用。 事实上,桌面OpenGL 2.0中的GLSL 1.1从一开始就支持派生版本(不需要扩展)——只有OpenGL ES 2.0(以及WebGL 1.0)决定将其排除在外。

    然而,有人抱怨各种GPU上的衍生实现。精确的导数计算成本高昂,因此GLSL规范允许返回更快的近似值,这对旧的图形硬件至关重要。在实践中,这种方法对平面遮阳效果很好,尽管有一个 OpenGL ES implementation (Qualcomm) 具有返回值符号翻转的奇怪行为。

    例如,这里有一个 research 几年前为Android设备完成的(不知道WebGL是否会遇到同样的问题——网络浏览器可能会将损坏的实现列入黑名单,或者对已知的驱动程序错误应用一些解决方法): dfdx derivatives issues on Android

    推荐文章