斜视角图形引擎的设计

精灵的影子处理(实时篇)

[上篇:精灵影子处理][下篇:内存消耗]

  上篇谈到U.Studio郭兄曾提到精灵的影子可以实时计算出来, 开始我很不以为然, 因为影子是 3D 世界的东西, 在 2D 下计算影子必然有相当的失真. 但是经过一番思考后, 又得到了一些可能性. 最近, 读到一篇 2D Engine 中动态光源的实现的文章, 其算法最大的缺陷在于无法生成影子, 这使我重新重视影子的实时运算问题. 本文将在此方便做些探讨, 把我曾经考虑过的问题记录下, 希望对朋友们和我自己以后的Engine 设计有所帮助.

  2D 下, 生成影子最大的困难是, 所有的物体都是平面的, 有如一张纸片, 这是计算真实的影子的最大障碍. 设想下阳光照射到一张纸片上和一个立体模型上在地面投射下 的影子有多大的区别吧. 所以, 对于阳光照射角度能够变化的 2D Engine 中, 大多数物体的影子是必须 由美工人员做好的. 但唯一有可能例外的是精灵(这里是狭义的精灵, 专指游戏中运动的小人等, 具体描述见第2篇)

正确的影子(1884字节)  先来看看什么时候, 平面的图象也能运算出真实的影子. 对, 是当光线平行于精灵图象平面的法平面时(如图). 这个时候, 精灵的 厚度完全不影响影子的形状, 我们可以得到真实的影子. 而斜视角引擎中, 所有的精灵都有 8 个方向的图, 所以我们可以得到 8 个方向的真实形状的影子, 这可以满足大多数情况的需要. (2D 游戏中不需要精确 的 3D 效果, 不是吗?)

  下面来看看影子是怎么(近似)运算出来的, 下图是一个精灵站立时的 8 个方向的图象.(特别感谢 devil网友友情制作精灵的图案)
0号精灵 (2032字节) 1号精灵 (1901字节) 2号精灵 (1709字节) 3号精灵 (1873字节) 4号精灵 (1911字节) 5号精灵 (1898字节) 6号精灵 (1740字节) 7号精灵 (2014字节)
0号 1号 2号 3号 4号 5号 6号 7号
然后将所有的图倒过来, 将成了光线于精灵平面的法平面平行时的影子:
0号精灵的影子 (1135字节) 1号精灵的影子 (1107字节) 2号精灵的影子 (1138字节) 3号精灵的影子 (1168字节) 4号精灵的影子 (1203字节) 5号精灵的影子 (1153字节) 6号精灵的影子 (1112字节) 7号精灵的影子 (1125字节)
现在把它们合起来看像这样:
可以注意到, 影子的衔接不太好, 这个还是由于图象是 2D 的原因, 简单的处理方法是将影子的脚部砍去, 贴的时候也对按精灵的底面投影对齐(大概在精灵的脚踝),这个砍去的高度和贴影子时的上移高度是一样的. 而且真正使用的时候, 光线的高度角决定了影子的长度, 大多数情况我们是使用压缩的影子. 诸如倒置, 压缩的运算都是可以实时完成的. 以 1 号图为例, 最后的效果如左图.

接下来如果光线从左上方照射过来呢? 实际上它就等于 2 号图的直射情况, 所以我们可以拿出 2 号图的倒影 压缩旋转来获得. (见下图示)

光线非直射的影子生成(4587字节)

  同理, 这 8 个方向的精灵分别 8 个方向的影子都可以近似的得到(和实际的还是有区别), 这里都没有考虑运算量, 而运算的速度关键应该是集中在旋转上面. 但是, 随着计算机运算速度的提高, 实时计算影子应该不会成为 Engine 的速度瓶颈, 但是这个方法最大的弊病出在精灵本身的不规则上面, 这里多谢沐枫网友的 email 来讨论这个, 比如本文中用到的精灵, 手中的长棍就是最糟糕的地方, 应该棍子本身和精灵的身体完全不在一个平面而且几乎垂直, 这样影子经过旋转后, 某些情况将和实际大相径庭, Sigh, 看来 2D 下运算出影子还是非常困难的, 如果您有好的方法, 请来 Email 讨论 ^_^