【问题标题】:OpenGL: Single vertex attribute for multiple vertices?OpenGL:多个顶点的单个顶点属性?
【发布时间】:2018-06-02 06:35:23
【问题描述】:

我有一个接受以下属性的顶点着色器:

  • a_posCoord: 顶点位置
  • a_texCoord:纹理坐标(传递给片段着色器)
  • a_alpha:透明度因子(传递给片段着色器)

我正在渲染的对象都是“广告牌”(一对直角三角形组成一个矩形)。

我正在使用对 glDrawArrays 的一次调用来渲染 许多 广告牌,每个广告牌都可能具有唯一的 alpha 值。一个广告牌有 6 个顶点。下面是一些伪代码来说明我如何为单个广告牌组织顶点属性缓冲区:

vertexAttributes = [

  px1,py1,pz1, // vertex 1: a_posCoord
  tx1,ty1,     // vertex 1: a_texCoord
  alpha,       // vertex 1: a_alpha

  px2,py2,pz2, // vertex 2: a_posCoord
  tx2,ty2,     // vertex 2: a_texCoord
  alpha,       // vertex 2: a_alpha

  px3,py3,pz3, // vertex 3: a_posCoord
  tx3,ty3,     // vertex 3: a_texCoord
  alpha,       // vertex 3: a_alpha

  px4,py4,pz4, // vertex 4: a_posCoord
  tx4,ty4,     // vertex 4: a_texCoord
  alpha,       // vertex 4: a_alpha

  px5,py5,pz5, // vertex 5: a_posCoord
  tx5,ty5,     // vertex 5: a_texCoord
  alpha,       // vertex 5: a_alpha

  px6,py6,pz6, // vertex 6: a_posCoord
  tx6,ty6,     // vertex 6: a_texCoord
  alpha        // vertex 6: a_alpha

  // ... Many more billboards not shown ...
];

注意相同的 alpha 值如何重复 6 次,每个顶点一次。

有没有一种方法可以为所有 6 个顶点指定一个属性,而无需为每个单独的顶点重复它?

为了减小缓冲区的大小,我希望我的顶点属性缓冲区看起来像这样:

vertexAttributes = [
  px1,py1,pz1, // vertex 1: a_posCoord
  tx1,ty1,     // vertex 1: a_texCoord

  px2,py2,pz2, // vertex 2: a_posCoord
  tx2,ty2,     // vertex 2: a_texCoord

  px3,py3,pz3, // vertex 3: a_posCoord
  tx3,ty3,     // vertex 3: a_texCoord

  px4,py4,pz4, // vertex 4: a_posCoord
  tx4,ty4,     // vertex 4: a_texCoord

  px5,py5,pz5, // vertex 5: a_posCoord
  tx5,ty5,     // vertex 5: a_texCoord

  px6,py6,pz6, // vertex 6: a_posCoord
  tx6,ty6,     // vertex 6: a_texCoord

  alpha        // vertex 1-6: a_alpha

  // ... Many more billboards not shown ...
];

不管怎样,我目前的解决方案工作得很好,但让我觉得很脏。我才刚刚开始掌握使用 glVertexAttribPointer 的方法,想知道它是否以某种方式支持这样的东西,或者是否有其他方法或技术可以用来实现不那么暴力的东西。


这是一个更具体的 WebGL 问题,但我对一般意义上的 OpenGL 感到好奇。

我知道几何着色器确实是我在这个特定示例中所需要的,但这是不可能的,因为它们目前在 WebGL 中不受支持。

【问题讨论】:

  • 确实非常接近重复,但我想保持开放几天看看是否还有其他知识,因为我的问题更具体一些,有人可能有一种我不知道的完全不同的方法。我猜在 WebGL 使用 ES3 的几何着色器支持之前,我将不得不坚持使用冗余数据。
  • 我注意到 glVertexBindingDivisor 不是 WebGL 1.0 或 ES 2.0(我正在使用)的一部分... :(

标签: opengl-es webgl shader vertex


【解决方案1】:

顶点不是位置 顶点是由多个属性组成的长向量。改变一个单一的属性,你最终会得到一个不同的顶点。所以不,你不能对多个顶点使用单个顶点属性,因为这在语义上没有意义。

然而,较新版本的 OpenGL 可以设置某个顶点属性的缓冲区偏移前进的速率。实际上,这意味着给定顶点数组的数据在属性的缓冲区偏移量增加之前被复制到 n 个顶点。设置这个除数的函数是glVertexAttribDivisor。在您的情况下,您将为 alpha 数组设置 6 的绑定除数。但重要的是,这不会对多个顶点使用单个属性,但它会使 OpenGL 执行您为您执行的重复操作。

【讨论】:

  • 我认为同样重要的是要注意这种重复仅在渲染期间发生,因此使用绑定除数 6 存储的 alpha 值将使用更少的内存。 (除非我严重误解了这个功能!)
  • OpenGL 进行复制而不是对多个顶点使用单个属性的缺点是什么?这是否意味着GPU上的顶点缓冲区以某种方式扩展并且没有节省内存?如果不是,那么可观察到的区别是什么?
  • “实际上,这意味着给定顶点数组的数据在属性的缓冲区偏移量增加之前被复制到 n 个顶点。”这不是真的,除数仅适用于实例索引,而不适用于顶点索引。可以通过实例化每个广告牌来解决 OP 的特定问题,但没有在答案中明确提及实例化,它是 quite misleading
【解决方案2】:

如果每个顶点的某些顶点属性是恒定的,为什么不使用统一变量?如果它是恒定的,它是均匀的!通过这种方式,您只需设置一次统一值,您的数据集就会减少。

【讨论】:

  • 这行不通,因为我只为包含 许多 个广告牌的整个缓冲区对象调用 glDrawArrays 一次,每个广告牌都有自己的 alpha 值。
  • 我不清楚。确实,我觉得你运气不好!对不起。
  • 是的——重读我的问题后,我意识到我没有强调重要部分。不过还是谢谢!
【解决方案3】:

我通过实例渲染实现了这个效果。 glVertexAttribDivisor(1); 使 openGL 每个实例读取一次顶点属性。如果您的公告牌具有不同的几何形状,您可以考虑将模型矩阵作为属性传递给与 alpha 相同的方式。

【讨论】:

  • 这似乎不受 WebGL 支持,但我会调查一下。谢谢!
【解决方案4】:

几个想法:

1.) 咬紧牙关并更新顶点缓冲区,但仅在 alpha 发生变化时更新。

2.) 将四边形列表分成批次,并且只重建发生变化的批次..

3.) 控制广告牌的数量并将 alpha 值数组绑定到统一... 在顶点数据的 alpha 中,或者在一些未使用的通道/附加通道中,存储 该广告牌的 alpha 索引,在您的统一数组中。 至少这样你可能只上传 n 个 alpha 值。

4.) 结合 2 和 3...

我只是在胡乱猜测......我想看看其他人是否有好的解决方案!

【讨论】:

    【解决方案5】:

    我没有详细研究过这个,但我认为你也可以使用glDrawElementsInstanced。有了这个,您可以将您的 alpha 值放入一个大的统一数组中,并且实例索引将以某种方式传递给着色器。看看这个:

    http://sol.gfxile.net/instancing.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多