首页 文章

在OpenGL中高效渲染透明地形

提问于
浏览
0

我正在编写一个可视化洞穴的OpenGL程序,因此当我想象表面地形时,我想让它透明,所以你可以看到下面的洞穴 . 我假设我可以将数字高程模型中的数据标准化为以规则间距对齐到X / Z轴的网格,并将每个网格单元渲染为两个三角形 . 使用对齐的网格,我可以避免在应用画家算法时进行排序的成本(以确保适当的透明效果);相反,我可以逐行渲染单元格,从最远的行和每行的最远单元格开始 .

这一切都很好,但我对OpenGL专家的问题是,我怎样才能使用OpenGL最有效地绘制地形(以及可以扩展到高分辨率地形的方式)?必须有一个比为每个网格单元调用 glDrawElements() 更好的方法 . 以下是我尝试过的一些方法,'s why I'米问专家):

glMultiDrawElements创意

  • 将所有地形坐标放在顶点缓冲区中

  • 将所有坐标索引放在元素缓冲区中

  • 要绘制,请按所需顺序将每个单元格的起始索引写入数组,并使用该数组调用 glMultiDrawElements .

这似乎相当不错,但我想知道是否有任何方法可以避免每帧都将索引数组转移到显卡,所以我提出了以下想法:

统一缓冲区构思

这似乎是使用OpenGL的一种落后方式,但只是把它放在那里......

  • 将地形坐标放在一个统一缓冲区中的二维数组中

  • 将坐标索引偏移0..5放在顶点缓冲区中(我知道它们必须是浮点数)

  • 调用 glDrawArraysInstanced - 每个实例将是一个网格单元格

  • 顶点着色器检查相机相对于地形的位置,并确定如何对单元格进行排序,将 gl_instanceId 映射到统一缓冲区中单元格的第一个坐标的索引,并将 gl_Position 设置为此索引处的坐标索引偏移属性

我认为可能会有一些闪亮的新OpenGL 4.0功能,我不知道它会比这些方法更优雅 . 我很感激任何提示!

1 回答

  • 1

    glMultiDrawElements() 方法听起来很合理 . 我会首先实现它,并将其用作基线,您可以比较,如果您尝试更复杂的方法 .

    如果你有机会让它更快将取决于绘制调用的处理是否是渲染中的一个重要瓶颈 . 除非您渲染的三角形非常小,和/或您的片段着色器非常简单,否则您很可能会受到片段处理的限制 . 如果您拥有可以收集数据并识别瓶颈的分析工具,那么您可以更加有针对性地进行优化工作 . 当然,总有一种低技术方法:如果让窗口变小可以改善你的表现,那么你很可能会受到限制 .

    回到你的问题:既然你问过闪亮的新GL4功能,你可以检查的另一种方法是间接渲染,使用 glDrawElementsIndirect() . 除了更灵活之外,与 glMultiDrawElements() 的主要区别在于,每个绘制所使用的参数(如您的情况下的起始索引)可以来自缓冲区 . 如果映射此缓冲区,则可能会阻止一个副本,并将起始索引直接写入缓冲区 . 您甚至可以将它与持久缓冲区映射(查找 GL_MAP_PERSISTENT_BIT )结合使用,这样您就不必每次都映射和取消映射缓冲区 .

    你的统一缓冲想法听起来很有趣 . 我有点怀疑它会表现得更好,但这只是一种感觉,而不是基于任何数据或直接经验 . 所以我认为你绝对应该尝试一下,并报告它的运作情况!

    如果您还没有考虑并拒绝它们,那么您还可以查看与顺序无关的透明度渲染方法 . 例如,alpha-to-coverage非常容易实现,如果您仍然使用MSAA,几乎是免费的 . 基于我的有限尝试,它不会产生非常高质量的透明效果,但如果它适用于您的用例,它可能非常有吸引力 . 另一种与顺序无关的透明度技术是深度剥离 .

    如果某些自我推销是可以接受的,我在前面的答案中写了一些透明度渲染方法的概述:OpenGL ES2 Alpha test problems .

相关问题