小白也能看懂的Ray March体积云 |
您所在的位置:网站首页 › 噪点产生的原理 › 小白也能看懂的Ray March体积云 |
前言 今天要给大家分享的主题是现在游戏开发中必备的一项游戏效果:游戏中的云渲染 现在大部分的游戏,不管是主机、PC还是手机游戏都在往3A的方向发展,所以现在的游戏在云的渲染上很少会采用传统的渲染方式 体积云是现在很多游戏大作中必备的体积云渲染方式,比如地平线系列、大表哥二,都采用了这样的渲染技术,可以说体积云是主机游戏标配的一项渲染技术 下面先从最早年代的云渲染技术开始,看一下传统的云渲染方式是什么样的,现在的渲染方式又是什么样的 版权声明本文为“优梦创客”原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595或WX:alice17173获取(企业级性能优化/热更新/Shader特效/服务器/商业项目实战/每周直播/一对一指导) 点赞、关注、分享可免费获得配套学习资源 详细内容可参考文末完整视频 云的渲染方式天空盒天空盒方式: 把一个摄像机放在整个场景中间,然后往上、下、左、右、前、后六个方向拍六张图片,来构成一个盒子形状,整个游戏的天空都是被包围在这个盒子里的,这就叫天空盒技术 公告牌云公告板云: 这种方式也比较简单,就是在整个场景上做了一个穹顶(如右图),它可能就是用几个面片把天空罩起来,然后在穹顶上贴一张天空的云层图片 片面穿插云片面穿插云 面片穿插云的特点也是简单,但它比使用前面的这些方式做出来的效果看上去要真实一点 如右图,面片穿插云不再是一个单一平面,而是由多个平面组合成云的形状,在不同的面片上绘制不同的云贴图,由于贴图是半透明的,所以面片穿插云看上去会有一定的立体感 视差云视差云: 云海效果是基于视差贴图的技术来实现的,在视角移动时可以看到云的体积感,因为视差贴图就是用一张图片来表示视差,然后渲染出来,虽然是一个平面,但它能渲染出高低不同的感觉 模型云模型云: 模型云相对要更真实一些,它是把真实的模型放在角色头顶来表示云的形状,它的实现方式有几种: 模型沿着法线外扩,来形成多个云的云层 采用曲面细分技术 优点:云的形状比较简单方便 缺点:由于它本质上并不是真正的带有体积的云,所以不能在云里穿梭 Ray March 体积云Ray March体积云 这是今天课程的主题,也是大家平时不太会接触到,或者比较难理解的一种TA进阶的技术:**Ray March体积云技术,**Ray March的意思是光线步进,它跟光线追踪是比较像的 上图的游戏画面中的云就是使用Ray March体积云实现的,可以清晰地看到云的层次感 体积云的特点体积云的特点: 体积云是有体积的,而不是平面的 议题体积云的噪点图生成 屏幕后处理 光线追踪一个云盒 光线步进云的形状 大气光线散射原理 云的形态控制 最终效果演示 体积云渲染时的七个步骤云的噪点图生成要生成噪点图需要先在图片上随机生成一些小红点(如右图),生成完以后,图片上的每一个像素格子都要判断靠它距离最近的那个小红点是谁,并且通过它们的距离值来代表亮度,距离越近,就把它渲染的越黑 这种随机生成若干个随机点,靠随机点之间的距离来代表这个格子的亮度的算法叫做Worley Noise算法 接下来再把中间是黑的,边缘是白的图做一下亮度值的反转,就会形成左边的中间是白的,越靠近红点越白,越远离红点越黑的图片 在平面上生成噪点图的开销其实是挺大的,它需要一分钟甚至几分钟时间才能生成一张,那有没有办法让它的速度更快一些呢? 可以只生成中间这一小块噪点图,然后再把它重复九次(如右图) 但复制出的平面噪点图是不连续的,缝隙非常明显,可以把这张复制出的图片进行水平和垂直翻转,让平面噪点图变成连续的状态,并把渲染开销降低到原来的1/9 接着再在高度上生成跟平面噪点图分辨率一样的若干个切片就形成了3D噪点图 如何生成Worley Noise噪点图? 随机确定一些中心点 计算每个像素到中心点的距离 但由于随便找一个像素点,然后把这个点与其他中心点的距离全部算一遍的效率太低了,并且中心点越多,它的效率就越低,所以要进行优化 算法层面的优化方法可以参考一下我们的《Untiy小白的TA之路》 如何在Unity中生成这样的噪点图?如何用Worley Noise算法生成噪点图呢?像素数量太多如何优化呢? 优化只要用九宫格算法就可以了,但用九宫格去生成其中一个格子也有不少的时间开销的, 所以为了解决这些问题可以开启Unity Shader的Compute Shader来进行并行运算,Compute Shader可以利用CPU和GPU来高效的调动整个噪点图的生成 具体怎样做才能使效率达到更高,可以参考文末的《Unity小白的TA之路》 上图是我们的噪点图生成器 第一个步骤完成以后就已经能生成云的形状了,那应该如何按照云的噪点来把云渲染出来呢?这里需要使用光线追踪技术来把云渲染到一个盒子范围里 屏幕后处理屏幕后处理就是把整个屏幕看成是一个四边形,然后整个屏幕的内容都已经渲染在一张纹理贴图上面了(左图代码中的_MianTex),然后再传入这张图片的每一个像素点的uv坐标(左图代码中的input.uv),就能够对屏幕四边形进行采样并渲染在场景里 至于为什么要在这里讲解屏幕后处理呢?是因为接下来要做光线追踪 如果想要对场景里的物件实现勾边效果,可以在片元着色器中写右边用黄色圈起来的这段代码,这段代码是把像素点坐标做一个偏移,然后进行采样 光线追踪这一阶段的目标是在执行左边的代码时能渲染出一个盒子(如右上图)这个盒子我们叫它AABB包围盒 算法解析: 在渲染每一个像素点时从摄像机的位置发出一条射线,射线的目标点就是这个像素点的位置,也就是说: 射线的起点是摄像机的原点,方向指向屏幕上的一个像素点,然后通过rayBoxDst(快速求交)算法,算得这个像素点是否与云盒中的云有相交 代码解析: 获取到碰撞信息后,通过返回的X坐标来记录射线到盒子的距离并用变量保存,叫做dstToBox,然后再通过返回的y值记录盒子内部的长度,同样是用变量保存叫做dstInsideBox 下面的if语句是判断如果没有碰到,就把颜色设置为黑色,碰到了就会把显示颜色,这样就能把盒子画出来了 这种技术叫做SDF算法,其实这种算法不仅可以在屏幕四边形上画盒子,还可以画各种各样的形状,大家如果想要了解如何绘制各种SDF形状,可以在文末扫一下爱丽丝老师的二维码,来领取我们的课程资料 现在可以反过来把盒子外面绘制出来,将盒子里面绘制成黑色,方法很简单,就是把上图代码中的if语句中的感叹号去掉 现在假设盒子是隐藏在红色盒子的后面(如右上角图),但黑色盒子并没有被红色盒子遮挡,这又是什么原因呢? 因为在屏幕后处理阶段写的Shader代码不能在平面上区分每一个像素点的前后关系 解决方法: 可以利用Unity URP渲染管线的深度采样功能取得每一个像素点的深度值,然后再通过图形学里的深度重建的技巧来得到每一个像素的深度值 关于深度重建的原理和推导会在系统课程里详细介绍 光线步进并不是盒子范围内全部都要渲染成云,因为前面的噪点图代表云是否生成,而噪点图是一个灰度图,当它的灰度值小于一定的值时,我们就不会把它渲染成云 所以要写一个算法来采样当前位置里的云的浓度 注意点: 由于云在立方体盒子里是立体的,所以这个3D噪点图会有很多层,无法一次步进完,需要进行多次步进(如下图) 这也是为什么这个技术叫做光线步进的原因,每次步进都要进行采样、判断 圈中代码解析: 上图是经过上面一系列步骤之后实现的效果,虽然还不是最终效果,但已经比较接近了 虽然是在屏幕后处理,但我们会使用一个立方体的盒子来承载这个效果,这样可以传入想要渲染的范围,以做到动态控制 大气光线散射实现大气光线散射需要采用LightMarch技术 LightMarch原理: 从摄像机的位置射出一条射线,这条射线会穿越云层,每当它穿越一点,就判断一下它到太阳光方向的浓度值,浓度值越大,说明它产生的散射就越多 云里的每一个点都要判断一下,最后把LightMarch的结果加起来,就得到光线散射的系数值了,然后用这个系数值作为最终渲染云效果的系数,这样就能得到: ”云越靠近光线的地方,就越透明;越远离光线的地方,就能更多的展现它本身的颜色” 云的形态控制体积云最大的好处就是可以控制云的形状,所以我们通过Unity实现了编辑器扩展,可以编辑、调整云生成时的形状,包括实时渲染出的形状 最终效果演示小结体积云的噪点图生成 屏幕后处理简介 Ray Tracing光线追踪一个云盒 Ray Marching光线步进云的形状 大气光线散射的原理 云的形态控制 最终效果演示 思考噪点图生成算法如何进行优化? Compute Shader的原理是什么? 如何有Compute Shader加速运算 Ray-Box快速求交算法 RayMarch性能是否还有优化空间 手游上的RayMarch如何优化 什么是深度重建 如何利用URP环境下的深度缓冲 大气的光线散射如何深入理解并实现 体积雾怎么做 体积光怎么做 如何利用Unity的编辑拓展实现TA工具链 写在最后更多学习资源请加QQ:1517069595或WX:alice17173获取(企业级性能优化/热更新/Shader特效/服务器/商业项目实战/每周直播/一对一指导) 点赞、关注、分享可免费获得配套学习资源 详细内容可参考下方完整视频 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |