Unity中如何使用Raymarching实现惊艳的图形效果
本文将由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相关技术文章
点击“阅读原文”查看文中源代码!