查看原文
其他

Unity中如何使用Raymarching实现惊艳的图形效果

2017-05-22 Unity官方 Unity官方平台

本文将由David Arppe分享一些在游戏中使用Raymarching技术的建议,以及他已用于实际游戏中的Raymarching代码,看看Raymarching这种古老的渲染技术如何回归游戏,并且使用并行处理和计算技术进行优化!


Raymarching技术实际上已经非常“古老”,在很早之前就被用于一些“古老”而经典的游戏中。例如下面两款经典的“老”游戏:


1.《Tennis for Two》



《Tennis for Two》被广泛认为是最早的视频游戏之一,它是一款使用示波器进行播放的游戏!非常酷并且很有创意!由William Higinbotham在1958年推出。

2. 《Donkey Kong》



《Donkey Kong》是一款诞生于视频游戏黄金年代的街机游戏。游戏主角是Jumperman(也就是现在的马里奥)。它被认为是首批带有故事情节的视频游戏之一,玩家在屏幕上可以像“看电影”一样,惊恐地看着公主一次又一次被绑架。由Nintendo Research and Development 1在1981年推出。


这些比较古老的游戏都非常有创意,他们突破了当时计算机硬件和软件的限制。超前地使用了现在仍未过时的技术。


什么是Raymarching技术


Raymarching是一种计算机图形渲染方式,但它的潜力仍未被完全发掘。Raymarching一般用于渲染体积纹理、高度图以及解析曲面。如今,大多数游戏用OpenGL或Direct3D(DirectX)来使用显卡的硬件加速器绘制多边形,电脑可以以每秒60帧的速度渲染几百万个三角面。虽然Raymarching没有那些图形API那么出名,但它可以仅用两个三角面实现无与伦比的细节

RayMarching是一种数学渲染方式。它是由距离场(点到一个图元的距离)、固定步长(通常用于体积渲染)和根定位(一个数学方法)完成的。


创建上图这样的场景需要借助三维工具(Maya, Blender, 3DsMax),纹理工具(Photoshop, Gimp, MSPaint)。而该场景使用数学方法创建,通过Raymarching技术来渲染,不再受渲染三角面数的限制。不过,Raymarching技术并不是万能的,它速度较慢,我认为其应该与多边形渲染一起使用。


下面的内容所涉及的代码可以给出很好的解释,您可点击【阅读原文】查看具体代码


如何在游戏中添加Raymarching


结合Raymarching与多边形两种渲染方式并不难。不过首先要理解它们之间的区别:

  • Raymarching并非百分百精确。而使用距离场可以趋近于希望渲染的表面,但几乎无法得到真正想要的距离。

  • 渲染多边形(透视模式下)使用了投影矩阵。这是深度,不是距离。


通常两者结合使用时,最简单的方式就是从多边形开始,用Raymarching作为结束。使用距离缓冲区进行深度测试是很难的,并且会局限于固态物体。Raymarching阶段需要在所有渲染结束后进行(就好比固态物体无法在透明物体之前渲染)。您可通过原文中的具体代码,了解如何准备好深度缓冲区,并将其转化为距离缓冲区!


Raymarching的工作原理


在准备工作就绪后,获得深度缓冲区里的距离,就可以处理相交。通过逆投影矩阵计算出正确的射线,来匹配游戏中摄像机的视角。然后定位摄像机即可。


在Unity中的效果如下图,两个黄色球体与一个长方体相交。其中一个(右边的)球体使用多边形渲染。它按照预期与立方体相交。左边的球体则按设置从游戏摄像机中计算的正确FOV,位置和旋转信息。

另外请注意,与右侧多面球体相比,用Raymarching渲染球体相交的立方体表面边缘非常平滑



渲染其他内容


使用Raymarching渲染需要较深的数学功底,下面用球体以外的形状来实现一些特殊物体!

float sdTorus( float3 p, float2 t )

{

  float2 q = float2(length(p.xz)-t.x,p.y);

  return length(q)-t.y;

}


这是一个环面的距离公式。此距离函数返回从点到距离图元最近的点的距离,将用于渲染甜甜圈。在下图中可以看到黑色图形、红圈、蓝点及红线。左下角的蓝点是摄像机,右上角的蓝点是正在观察的点。除了知道与最近平面(底部中心粗短的黑线)的距离以外没有任何信息。因此,使用这个距离来向前移动。不断重复这个过程,直到到达最终想要的平面!最后就可以得到目标平面的距离。


要实现甜甜圈,还需要实现以下功能:

  • 获取射线源(摄像机位置)

  • 获取射线方向(摄像机FOV,长宽比还有旋转角度)

  • 在函数中添加一个距离函数(环形)

  • 将光线投射到图形上

  • 在该光线上获取到图形表面的距离



下面,首先要计算一个点。使用标准的point-along-a-vector方程,沿着所投射的射线移动一定的距离,然后计算到图元的距离。将刚刚计算的数值加上沿射线移动的距离,然后重复该过程。通过FOR循环进行控制,结果如下图。



现在还只渲染出纯黄色。到此已成功创建了一个环形,您也可以尝试一些其它的距离函数,并观察它们的工作工作原理。后面还会使用一些更高级的东西。


获取G-Buffer信息


还需要更多信息来使用光照模型。现在,只有一条射线的距离。要在图形上进行更多操作,需要知道:3D坐标和表面法线。这些属性都非常容易获得!


下图是一个有法线和世界坐标的圆环。



下面来添加光照。这里使用了标准的Phong光照模型为圆环添加光照,看起来效果不错!



投影映射


下面在甜甜圈上撒些东西!可以在此获取所用的纹理。目标是尽可能地让它看起来更像甜甜圈,最终可以达到如下图的效果。



总结


当“古老”的技术与现实碰撞,有的时候能产生很不一样的效果。本文我们教大家Raymarching这种计算机图形渲染方式实现了一个“甜甜圈”,是不是很有意思?您可以点击【阅读原文】查看文中功能实现的源代码。


想要了解更多精彩技术内容,请您访问汇集Unity技术精华的Unity官方中文社区(forum.china.unity3d.com),与其他Unity开发者们一起学习进步。


更多Unity相关技术文章

支持NVIDIA VRWorks的Unity测试版发布

Mac OS上也能使用Unity结合Visual Studio开发游戏了

进阶Unity开发不能错过的Unity完整游戏教学案例

Unity 5 教程 | 低多边形场景的光照与后处理

使用Unity在HoloLens中实现《终结者》视觉HUD


点击“阅读原文”查看文中源代码

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存