您好,欢迎访问三七文档
1.需求概述1.1.天气效果整个天气效果,除了雨雪之外,还应该包含大气、天空、雾所有这些效果组合起来,才能形成一个接近实际的仿真效果。雾功能标识功能名称雾优先级功能描述创建过程点击创建雾按钮,可以在场景中增加一个雾对象,模拟起雾的效果。雾对象类型从雾范围来看,雾对象分为两种:一种为全局雾,一种为局部雾。全局雾:在任何地方都有雾效果。局部雾:绘制一个多边形,设置一个雾高度,那么,雾范围被限定在以这个多边形为边界,沿地面到雾高度所形成的柱体里面。雾对象参数雾对象可设置的参数包括:1雾浓度可理解为雾的密度2雾的颜色雾颜色应该是从近到远有一个渐变的过程。输入点击按钮处理输出雾效果显示补充说明2.实现原理2.1.基础知识现实世界对于雾的定义,雾是指在接近地球表面的大气中悬浮的由小水滴或冰晶组成的水汽凝结物,是一种常见的天气现象,雾能影响能见度。在虚拟现实中一般雾的效果实现是比较简单的,所谓雾效,就是在远离我们视角的方向上,物体看起来像被蒙上了某种颜色(通常是灰色)。这种技术的实现实际上非常简单,就是根据物体距离摄像机的远近,来混合雾的颜色和物体本身的颜色即可。在传统的固定管线的中,已经内置了雾的效果,模拟雾的浓度计算有三种算法:线性雾Linear,指数雾Exponential,二阶指数雾Exp2。Linear:,其中Dmax和Dmin分别表示受雾影响的距离起点和终点。Exponential:,其中d表示雾的浓度。Exp2:,其中d表示雾的浓度。1原始场景2线性雾效果3指数雾效果4二阶指数雾效果UGlobe3.0版本中采用的就是固定管线方式实现的雾,由于固定管线方式实现的雾可定制性不好,因此在UGlobe3.0中雾的效果存在一些比较问题:1、Globe的可视域和可视范围远远超过普通的场景,并且雾的最大浓度不可控制,雾效开启后很容易出现场景的全部都是雾颜色。2、开启雾效后,远距离查看地球,应该一定程度的关闭雾效,3.0版本控制效果不太好。3、体积雾(VolumnFog)、深度雾等效果,固定管线方式无法实现。对于目前我们的应用,因为大部分都是使用可编程脚本渲染,所以继续采用固定管线方式的雾方案不可行。为了能够更好的进行大范围和局部范围的雾效果模拟,我们才结合传统距离雾和深度雾的方式进行模拟。2.2.体积雾效果及原理为了表现我们将来的实现效果,下图是采用Unity的GlobeFog的实现的效果。5体积雾(VolumetricFog)6传统基于距离的雾效果7深度雾+距离雾混合效果8近距离深度雾(现实中经常见到的情况,雾只出现在距离地表一段距离内)在现实世界中,云雾效果9云雾效果(Volumetricclouds)10云雾效果体积雾的实现原理:1、假定在距离水平面高H的处,构建一个虚拟平面FogPlane(其中F为平面的法线,P点世界空间内的一点,H为雾的高度)。平面下的部分会存在雾的效果,平面上的部分不存在雾。2、渲染场景对象(主要地形、模型)到深度纹理(DepthTexture),注意如果天空不需要雾效果是不用渲染到深度纹理(而且我们一般不不会渲染天空到深度纹理中)。3、渲染所有场景对象到颜色纹理(ColorTexture)。在Ogre中可以使用Composite进行控制颜色纹理和深度纹理的渲染流程。4、使用cg进行雾效果合成。//计算目标点的雾效因子floatComputeHalfSpace(float3wsDir){float3wpos=_CameraWS+wsDir;floatFH=_HeightParams.x;float3C=_CameraWS;float3V=wsDir;float3P=wpos;float3aV=_HeightParams.w*V;floatFdotC=_HeightParams.y;floatk=_HeightParams.z;floatFdotP=P.y-FH;floatFdotV=wsDir.y;floatc1=k*(FdotP+FdotC);floatc2=(1-2*k)*FdotP;floatg=min(c2,0.0);g=-length(aV)*(c1-g*g/abs(FdotV+1.0e-5f));returng;}//从深度纹理计算像素点距离相机的深度值floatrawDepth=SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);floatdpth=Linear01Depth(rawDepth);float4wsDir=dpth*i.interpolatedRay;float4wsPos=_CameraWS+wsDir;g+=ComputeHalfSpace(wsDir);//ComputefogamounthalffogFac=ComputeFogFactor(max(0.0,g));returnlerp(unity_FogColor,sceneColor,fogFac);深度雾参考资料:实现步骤深度雾和全局雾可在大多数平台中使用延迟渲染(DeferredShading),其实也可以使用传统渲染(ForwardShading)。使用传统渲染流程比较简单方便,因此我们推荐使用ForwardShading。下面介绍一下简单流程:1、将场景渲染一遍,让需要渲染深度的物体,将深度值渲染到深度纹理zDepthTexture。(注:这一步需要调整目前UGlobe的渲染流程,需要对目前的渲染流程做一些调整)2、进行正常渲染流程。对于有些希望不受雾效影响的对象,可以放在第4步执行。3、构建一个全屏四边形Quad(使用屏幕坐标),材质使用深度纹理。使用原理中介绍的体积雾cg进行渲染。4、渲染不希望受雾效影像的对象。(比如矢量线,矢量面,注记等)5、整个流程结束。2.4.如何实现局部雾局部雾的实现,局部雾范围由绘制多边形调整为沿中心点一个圆形范围内。如果场景中只存在局部雾,需要传入局部雾的基于视点的坐标。然后在cg中进行处理:float4wsPos=_CameraWS+wsDir;floatlen=length(wPos-fogPos);ff(lenr){g+=ComputeHalfSpace(wsDir);//ComputefogamounthalffogFac=ComputeFogFactor(max(0.0,g));returnlerp(unity_FogColor,sceneColor,fogFac);}一般情况下,在当前视野范围不会存在过多的局部雾,否则这也不合理。因此局部雾在传入cg中会设置一个上限数量,并且在实际处理过程中,会过滤掉那些不在视野范围内的局部雾。3.对象设计由于需要实现局部雾的效果,采用要素机制实现。要素如果存在局部雾或者全局雾,那么忽略局部雾的效果,全部采用全局雾的效果设置。3.1.FogElementRender类雾效要素FogElement主要作用是将雾效的参数传入FogElementRender中渲染,然后由FogElementRender进行处理和渲染。关键成员变量名字含义boolmIsInited是否初始化ListFogElementmFogElementList雾要素对象集合MaterialmFogMaterial渲染雾合成材质Ogre::Renderable*mScreenQuad覆盖屏幕空间的渲染对象,用来计算屏幕空间内的像素的雾效果VectorFogElementmShadingFogElement对当前渲染范围有影响的雾要素FloatmMaxFogDistance最大雾效果距离关键成员函数名字含义Ogre::Renderable*CreateScreenQuadRenderable()覆盖屏幕空间的渲染对象VoidUpdateFogParams()计算所有的局部雾和全局雾的结果参数3.2.FogElement深度雾要素类关键成员变量名字含义boolmIsGlobeFog是否是全局雾(默认为false)Vector3mFogCenterPosition深度雾的中心位置floatmFogRadius深度雾半径floatmFogHeight深度雾的厚度,雾效开始退化的世界空间高度intmFogMode雾的类型,基于距离、高度或两者皆有。mFogMode=0表示两者都有,mFogMode=1表示基于距离;mFogMode=2表示基于深度floatmStartDistance距离雾的开始退化距离。floatmDistanceDensity在一定距离雾气积累的程度。floatmHeightScale雾浓度随高度减少的程度(当使用基于高度的雾效时开启)。floatmFogColor雾的颜色关键成员函数名字含义
本文标题:雾效果设计文档
链接地址:https://www.777doc.com/doc-7071385 .html