GPU Gems1 - 7 无数波动草叶的渲染

本文部分参照该文章https://zhuanlan.zhihu.com/p/35974789

1.引言

本章介绍了一种灵活的,广泛应用的草模拟。该方案渲染的草不仅生长得自然,也能够逼真地在风中舞动,而且性能很高。

2.概述

首先,需要意识到,对单个草叶的细节建模意义不大,因为那样大片草地需要的多边形数目会太多。所以,我们必须建立一个符合以下条件的简单而有用的替代方案:

  • 许多草的叶片必须由少数多边形表示。
  • 草地必须从不同的视线看起来显得密集。

而要做到让场景不依赖于摄像机的位置和方向,可以把一些草叶组合起来,表示在一个纹理中,并将多个纹理组合起来,且在结果中单个的多边形不应该引起注意。当观察者四处活动时,通过将草体加入混合操作或者移除混合操作,以在距离范围内增加或删去草体,来保证整个草地的渲染效果具有稳定的视觉质量。

3.草体的准备

    3.1 草的纹理

草的纹理,应该是一些一簇一簇聚集丛生的草,否则,会出现大片的透明区域。需在透明的alpha通道上画实体草茎。在彩色通道中,用深浅不同的绿色和黄色,来较好地区别各个单独的叶片,也应该模拟不同情况的草叶:长得好的和长得差的、老的和嫩的,甚至区别叶片的前面与后面。

下图是一个草地纹理的示例。

    3.2 草体

对于线性排布,如果从垂直于多边形的方向观看场景,就会立刻穿帮,看出草地多边形的结构是线性排布的。另外这种情况下草地会看起来非常稀疏。只有在摄像机自动导航,或者渲染无法到达的远距离草地时,才会考虑这样的排布。为了保证独立于当前视线的良好视觉质量,我们必须交叉地排布草地多边形。已证明,使用星型结构是非常好的。下图给出了“草体”可能的两种变体。

他们由3个相交的方块构成。我们必须禁用背面剔除来渲染多边形,以保证双面都可见。为了得到合适的照明度,应该让所有顶点的法线方向与多边形的垂直边平行。这保证了位于斜坡上的所有草体都可以得到正确的光照,不会因为地形的亮度而出现差异。

如果把这些草地物体彼此相当靠近地设置在一个大的区域里,如下图。在运行期间把它们从后向前进行排序,使用alpha混合,并启用DrawCall中的z-testing/writing,那么就会得到自然而茂密的草地渲染效果。

4.草地的动画

关于草地的动画,基本思想是以三角函数(尤其是正弦和余弦)为基础进行计算,且计算应该考虑到移动的位置和当前时间、风向和强度。我们的每种技术都只移动草体较高的定点。在一个顶点shader中,通过检查纹理坐标,区别较高的顶点和较低的顶点是很容易的。对草纹理而言,所有的上面顶点应该有相同的v坐标。本文首先实现一个顶点shader的框架,在所有的3种动画技术实现方案中都使用该框架,只有纯动画的部分有差别。

顶点shader框架如下:

 

 

动画部分实现起来有几种方法:

1)每草丛草体的动画(Animation per Cluster of Grass Objects)。

对一丛靠近的草体,上面的多边形顶点统一地发生移动。动画的平移矢量由cpu计算,若在cpu上使用更费时的算法,还可以让我们利用非常复杂的风模拟。因为每丛草体由它自己的平移矢量来支持,所以必须针对每丛草体来改变这个常量,因此不得不经常地打断对整个草地的渲染,而且为每丛草体使用独立的绘图调用。

优点:

  • 复杂的动画计算基于cpu算法进行
  • 因为一个多边形上顶点的距离是固定的,所以不发生变形。

缺点:

  • 需要许多的draw call
  • 由于整个草丛的所有顶点同步动画,可能出现聚集成簇的现象。

算法:

  1. 在cpu上计算一个草丛平移矢量
  2. 为顶点shader把平移矢量设置为一个常量
  3. 为该单个草丛执行一个drawcal
  4. 调用顶点shader,把平移矢量加到上面顶点的位置

2)每顶点的动画(Animation per Vertex)

为了减少绘图调用,我们需要把动画计算移进顶点shader内,shader能够相对于它的位置分别的移动每个顶点。如下图所示:

因为对每个顶点的移动是分别计算的,各顶点移动的距离不再是常数,所以可见的变形会出现,但是通常这些失真不易觉察。

 

优点:

  • drawcall很少,甚至仅仅1个
  • 在顶点的shader中改变顶点位置,产生连续的风吹草地引起的波动荡漾
  • 不会看出个别的草丛。

缺点:

  • 出现变形
  • 由于缺少了局部的无序,动画可能显得过于均匀
  • 动画计算的复杂性受到限制

算法:

  1. 为顶点shader设定常量,例如风的基本强度和方向,时间延续性等。
  2. 为完整的草地或大面积的草场执行一次draw call
  3. 调用顶点shader,在shader中计算顶点位置的动画

3)每草体的动画(Animation per Grass Object)

吸取前两个方法的各自优点,我们可以计算动画不是基于每个顶点的位置,而是基于草体的中心位置。因为附近的草体现在有不同的动画,我们能表现那种要求的局部混乱,每个草体内的顶点移动相同,又避免了变形。为了做到这一点,每个顶点必须知道它所在草体的中心位置。因为顶点shader必须读取这个值,所以这个信息所需要的草体位置矢量必须在顶点格式中。

优点:

  • drawcall很少,甚至仅仅1个
  • 没有变形
  • 局部多变,画面更自然

缺点:

  • 因为每个顶点也包含它的草体的中心位置值,所以在顶点格式中需要附加数据
  • 动画计算的复杂性受到限制

算法:

  1. 为顶点shader设定常量,例如风的基本强度和方向,时间延续性等。
  2. 为完整的草地或大面积的草场执行一次draw call
  3. 调用顶点shader,以草体的中心位置为基础在shader中计算顶点位置的动画

 

【核心要点总结】

1)草的纹理,应选取一簇一簇聚集丛生的草。在透明的alpha通道上画实体草茎。在彩色通道中,用深浅不同的绿色和黄色,区别各个单独的叶片。

2)草体的渲染,适合进行交叉排布,从后向前进行排序,使用alpha混合,并启用Draw
Call中的z-testing/writing,便能得到自然而茂密的草地渲染效果。

3)草地的动画,以三角函数(尤其是正弦和余弦)为基础,且应该考虑到移动的位置和当前时间、风向和强度。实现起来有三种方法:

  1. 每草丛草体的动画(Animation per Cluster of Grass Objects)
  2. 每顶点的动画(Animation per Vertex)
  3. 每草体的动画(Animation per Grass Object)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值