现在的位置: 首页 > 综合 > 正文

云彩的渲染(转)

2018年02月06日 ⁄ 综合 ⁄ 共 3843字 ⁄ 字号 评论关闭

原文:

Realistic and Fast Cloud Rendering
NinianeWang
MicrosoftCorporation(nowatGoogleInc.)
niniane@ofb.net
November11,2003

    最近在网上看到很多云渲染的效果图,但很多人吝于向人分享经验知识,我不是很赞同这种想法,本来就是属于别人的知识,自己有幸学习得到就应该拿出来分享。废话不多说了,这篇文章中所述的方法正是微软飞行模拟2004采用的方法,也是CRYSIS中云的实现方法,当然CRYSIS中有更多改进。感谢我前同事提供原论文。

 

                              傍晚的云彩

   云是构成室外场景的重要元素,这篇文章将讲述利用在粒子上赋予纹理的方式来近视各种形态的云彩,而且即使在漫天乌云的情况下也能得到非常理想的运行效率,在光照着色方面我们给予美工最大的控制权,利用美术资源来获取理想的光照效果,而不是传统的利用简单光照模型计算得到,这样对于最终效果可控性会更强.同时我们还将讲述模拟云彩群聚和分散的效果

    真实的云彩能让室外场景精彩万分,特别是在交互写实的应用中尤为重要,好的云彩系统必须能呈现各种形态各种密度并且各方向都真实的云我们的系统必须满足以下几个要求:     1.必须高效,平台应用广泛    2.要能很好的模拟云彩的光照效果    3.云彩需要运动起来才行

 

传统云彩技术
    很多技术用来对云彩进行建模动画和渲染比如最传统的体渲染利用程序生成的噪声对一个椭球体纹理进行干扰而着色计算也是基于真实的大气条件最大的缺点就是不可控无论是噪声生成的形态还是着色效果然后就体渲染本身与多边形3D还是有些差别,2者聚合在一起比较麻烦。

如果对体渲染云彩感兴趣的请参考:http://www.vrvis.at/via/resources/course-volgraphics-2004/
Course notes "Real-Time Volume Graphics", Course #28, Siggraph 2004
如果对纯物理模拟感兴趣的请参考:《Real-Time Cloud Simulation and Rendering》By Mark Jason Harris

我们云彩如何建模?

    我们利用5-400个精灵的ALPHA混合来渲染单朵云彩,渲染时所有精灵都面对相机聚合在一起形成一个具有3D分布的体积然后我们需要依照相机距离来从后向前渲染他们然而如何来建立这些精灵呢我们选择了一个能给与最终效果更好可控性的方式传统的程序生成方式特别是来暴露了许多方程参数的调控让美工痛苦万分而且并不能所见既所得我们写了个3DS-MAX插件它能让美工通过一系列的方盒来近似一个云彩整体形状美工还能指定之后生成的精灵数量这样能控制云的浓淡还能设置生成精灵尺寸范围生成的精灵大部分是正方形的当然也会用一些狭长的矩形来模拟云际见最缥缈的部分通常一个16平方公里的天空会用20-200个盒子来描述云彩外行而每个盒子根据云彩浓淡又会最终生成1-100个精灵导出时插件会首先根据盒子范围云彩密度等参数生成一系列的精灵中心点然后插件会遍历精灵将距离太近的精力合并消除这样能很好的提高效率我们发现这个阀值指定在1/3精灵尺寸时在普通云彩中能得到满意效果而稠密得云彩则使用1/5~1/6尺寸导出时我们需要包含如下信息精灵位置尺寸(长宽)、旋转(增加随机性)、纹理以及着色信息(稍后详述)。

我们使用什么样得纹理呢?

    我们综合使用(不同数量比例,不同渲染参数,旋转扭曲,拉伸)以上16种云彩纹理来模拟各种截然不同得云彩,这个图时32位带ALPHA通道得.比如使用较多得第4种纹理来模拟底部平坦得积雨云,而第一排得其他3种雾一样得纹理多用来模拟蓝灰色调的稀薄层云,最下两排中饱满膨胀的纹理则多用来模拟堆积云,剩下的纹理则在所有类型的云中都又应用.为了使用有限的16种纹理模拟尽可能多的云彩,我们需要做更多的变换,比如随即旋转,一般的云彩我们让它在0~360范围内随机,而雨云平坦的底部一般使用-5~5

在云中飞翔我们需要做些什么

  

    我们的系统将为相机穿梭在云层中提供真实的体验当相机穿过精灵后精灵马上从视野中消失通常这能达到一个完美的效果但如果相机穿过云层的时候正在做变形动画可能就会在视觉上有一些不协调的突变当我们首次实现这个解决方案的时候我们让精灵作为公告板始终面对相机平面这样就不会在相机运动过程中明显感觉到精灵的边界当这样有个很大的缺点就时当相机离精灵很近的时候精灵的旋转会非常明显为了解决这个问题我们决定当相机距离精灵距离小于精灵半径的一半时就不再旋转精灵了这样能很好解决前面提到的精灵旋转问题但又引进了一个新问题就是如果精灵旋转被锁定后如果此时相机旋转观察精灵此时精灵的边界又会比较明显了最终我们决定根据相机观察方向与精灵锁定时的方向之间的夹角来调节精灵的透明度

云彩如何生成为消亡

   云能自然的生成和消亡将会极大的增加真实性这里我们通过控制精灵ALPHA程度来完成云彩的演化过程我们通过精灵在云中的位置来来决定顶点的透明程度当云形成时我们首先只渲染位于云中半径一半范围内的精灵,随着时间流逝慢慢减少他们的透明度当透明度达到一个阀值时我们才开始渲染半径一半外的精灵云彩的消亡过程与此相反当半径一半之外的精灵基本全部透明后开始增加半径一半内精灵的透明度,需要注意的是记得对更外面的精灵使用大一些的透明变化。

云彩如何进行光照着色?
   我们的着色模型中主要又两个控制因子天光和阳光

天光的模拟
  
现实中当光线穿过云层时会被云层的粒子散射和吸收通常在均匀天光条件下云彩会呈现上白下暗的外观为模拟这个效果美工首先定义5个颜色等级每个颜色等级由一个RGBA颜色和高度组成。 

    美工可以使用不同的亮度等级来模拟不同类型的云彩使用方法见原文美工还需要定义一个百分比等级来模拟一天不同时段的天光强度比如中午的天光最强,晚上基本没光了最后计算流程如下首先必须完成公告板的旋转让他们面对相机还有根据精灵与相机的远近程度将精灵锁定到相关角度,对于每个精灵的顶点我们取它的高度分量利用它在高度等级中对天光颜色进行插值再利用当前游戏时间插值得到当前天光百分比等级,将两者相乘就得到了顶点得当前时间得天光颜色

阳光的模拟

   太阳会向天空中的云彩投射方向光特别是再黎明和黄昏变化的阳光能让云彩更加生动我们现在将模拟云彩面向太阳光的部分与被向阳光部分的明暗但我们不模拟云彩之间云彩自身以及云彩与场景中其他物体之间的遮挡与投影效果美工再3DSMAX中会指定着色组通常1~30个精灵为一组每个BOX都有一个用户属性来指定这个BOX产生精灵所属的着色组每个组用来模拟现实云彩中的紧密聚在一起的一簇当我们为一个顶点着色时首先计算其所属着色组中心到这个顶点的向量然后再计算所属着色组中心到太阳的向量将他们正规化后,进行点积得到一个位于[-1, 1]之间得值现在我们要将这个值映射到[Cmin, Cmax]之间,[-1, 0]映射到[Cmin, Cmed], [0, 1]映射到[Cmed, Cmax]。这样单位云簇从明到暗就有一个光滑得过渡Cmin Cmed Cmax均为亮度百分比由美工指定,美工还会指定一天中太阳光变化T0->C0 T1->C1,给定一个时间则顶点得颜色计算为:

C_sun = Func_map(v0*v1) * ( A * C0 + ( 1 – A ) * C1 )        A = (T1 – T) / (T1 – T0)

最终颜色为:

C_vertex = ( C_sky + C_sun ) * C_tex * Alpha_morph 

如何优化性能?
    主要再两个方面,一个时顶点的位置计算和着色计算第二个时GPU象素填充率 。文中提到使用了顶点信息预计算和八角形环代理纹理方式,这里不再详述,请参看原文。

限制 

   我们的云彩系统因为是体积分布的精灵所以非常不适合做平面云如果要做高积云等非常扁平的云可以直接使用纹理平面.因为所有的粒子再渲染前都做了从后向前的排序这样才可以得到正确的渲染效果但当相机移动的时候很可能导致渲染顺序的改变这样再视觉上可能会由一些可以察觉的变化特别是在太阳光分量比较重的黎明和黄昏但这个问题还没有严重到一定需要解决的地步还有一些情况与现实不符比如相机在云彩中间时看到的云比在外面看要更透明因为有一半的精灵位于相机后面了而现实并非如此当相机靠近云层后向下看因为精灵都被垂直的锁定了所以我们将会看到大片无云空白一个建议的解决方案是当相机进入到云彩中心的时候给世界加上一个额外的雾化来增强云的浓度到此为止我们的云没有任何的动画现实中的云一般都会随气流运动变形我们可以通过旋转和移动云中的精灵来模仿被风扰动的效果同样我们可以通过透明掉其中部分精灵来改变云的形状等等因为我们的云没有模拟对光的散射云彩自身不会投影也不会对其他物体产生投影还有利用相对与太阳的夹角来评估光照是错误的应该是根据阳光穿过云层的距离和密度来估算这样我们就不能得到一些现实中得效果比如在云层后面观察太阳能看到云得光边

抱歉!评论已关闭.