很久以前,我想根据我在YouTube上看到的一个想法实现2D闪电算法。该视频是实时的,但它在CPU上运行并且分辨率很低。我很好奇是否有人知道如何在GPU上执行此操作。

该算法的工作方式如下:


我们有明亮的数据图,它们保持材料的颜色(例如,红色玻璃的色度为0xFF0000)以及该像素的透明度。
用光源计算出以圆圈为单位的每个像素的光值。换句话说,首先计算紧挨着光(8个像素)的值,然后计算这些像素的邻居,依此类推。像素的颜色是其在闪电数据图中的值,其alpha值等于:(最接近光源的像素附近的alpha值-自己的alpha值)。因此,这是一种射线投射算法,可以计算每个像素的值,并且可以处理有色玻璃和雾/烟雾。

因此,CPU实现非常简单。我的问题是我想在手机游戏中使用它,但是我不知道如何将其用作着色器。
如何在GPU上实现它(可以在移动设备上运行,因此使用OpenGL) ES 2.0 / 3.0,也许使用Metal-如果无法实现,则使用OpenCL / CUDA)?

注意:我不是在寻找完整的实现,只是想法/着色器伪代码如何实现。

#1 楼

如果您的墙几何形状是矢量图形,则可以简单地将线段拉伸远离灯光位置。这意味着每个绘制调用2个三角形,所有的拉伸偏移都可以在顶点着色器中进行处理。

图像1:为每个墙生成阴影体积拉伸。

阴影卷的快速且极其肮脏的示例实现在这里:



http://webglplayground.net/saved/AeN6yoNGih(请不要保存您自己的版本,而不是fork)

现在,由于您的着色器可以根据需要对三角形进行着色,因此您可以在着色的三角形上应用着色器。就像渲染透明表面一样。为此,您可能需要屏幕外的缓冲区以获取正确的颜色累积模式。



图像2:根据与光的距离为体积着色。 >
当然,着色算法可能是您喜欢的任何一种。例如,您离挤出边缘越近,颜色可能越暗。

很快就完成了非常脏的彩色阴影体积实况示例:



http://webglplayground.net/saved/9xgxDbtY7f(请不要保存您自己的版本,请使用fork代替),在运行时(以及在我的手机上)执行的代码风格很差。

这只是希望其他人能仔细研究的一种方法。您也可以使用与3d完全相同的方法。对于不均匀的雾,您可以使用raymarcher。

评论


$ \ begingroup $
感谢您的回答!但是我不是在寻找简单的2D阴影算法(网络上有很多),而是在寻找能够处理体积雾和彩色透明表面的阴影/光算法(如YouTube视频所示)。
$ \ endgroup $
– sydd
16年1月10日在17:57



$ \ begingroup $
@sydd只是阴影体积上的着色器。易于扩展。
$ \ endgroup $
– joojaa
16年1月10日在18:17

$ \ begingroup $
@sydd添加了彩色示例
$ \ endgroup $
– joojaa
16年1月11日在17:43

$ \ begingroup $
谢谢,看起来不错!但是,当我写这篇文章的时候,是关于将我描述的算法移植到GPU上的。实际上,有人在stackoverflow.com/questions/34708021/…上提供了关于SO的答案。这个答案是我正在寻找的,但是它很慢,因此我认为该算法对于真实游戏不可行。
$ \ endgroup $
– sydd
16年1月12日在17:23

$ \ begingroup $
通过将数据预先计算为更好的数据结构,可以加快@sydd射线广播的速度。
$ \ endgroup $
– joojaa
16年1月12日在18:19