我发现了Unity3D的2D Light Renderer, 随后就把它抄了过来

原帖传送门_博客园

.  前几个月,偶然在群里看到有人讨论Unity3D光照,于是我又萌生了一个新的目标————把它抄过来!

.  众所周知,3D渲染的整个流水线都跟光照密不可分,相关的技术更是数不甚数,而2D游戏的光照通常被人忽略,因为2D游戏大多数都是贴图叠加,要什么效果,美术直接画出来就完事了,所以大多数2D游戏引擎就不过是个贴图引擎,干着渲染的工作却没有一点渲染的技术含量。

.  即使是2D游戏,运用好光源也可以把品质提升一个档次,但就如前面所说,做2D引擎的不提供这个功能,用2D引擎的不知道这个技术,以至于大部分有动态光效的2D游戏都是外国货。


.  进入正题,记录一下我花了2个周末实现的2D光源编辑。

效果图

成品

大体思路

先生成光照面积,在后期阶段通过面积全屏采样输出即可,其难点就在于生成光照面积。

光照面积又分内面积和外面积,内面积就是发光的部分,光线不会衰减,外面积则是辐射范围,光线会逐渐衰减,在这个前提下,光照面积还分圆形面积和多边形面积。

圆形面积生成:

通过圆形和半径生成内面积,再通过给定的辐射度生成外面积,这个形状看起来像是一个环,之后再用三角形填充内面积以及环,最终生成的样子是这样的。

圆形_线段

多边形面积生成:

通过给定的顶点生成内面积,再通过给定的辐射度生成外面积,思路跟圆形是一样的,但多边形有两个略为棘手的问题。其一是多边形的形状是不可控的,如果是凹多边形,则光照面积会叠加,这会导致叠加的部分被多次光照。其二是多边形并非像圆形一样均匀的形状,想象一下,同一个光源散发出来的光在相同距离的情况下衰减程度应该是一样的,拿圆形光源来说,光从内面积边缘发出,最终抵达外面积边缘,当光线刚发出时(在内面积边缘时)其衰减值为1(最大值),当光线抵达终点后(在外面积边缘时)其衰减值为0(最小值),而圆形是一个均匀的形状,因此它任何角度都满足这一条件,而多边形则需要通过一点点的计算代价来做到这一点。

解决第一点:求得最大凸包即可。

解决第二点,计算外面积的时候,用圆角来代替多边形的锐角。

最终生成的样子是这样的。

多边形_线段
多边形_线段_填充
多边形_填充

最终效果

有线段绘制

演示图_有线段

无线段绘制

演示图_无线段

Github传送门

推荐阅读更多精彩内容