Ogre、Shadow Map、和其他
Ogre的影子分为两类:模版阴影和基于纹理的阴影。
(1)模版阴影 SHADOWTYPE_STENCIL 分MODULATIVE,ADDITIVE两种。 不过模版阴影我不太care,没有太仔细看。大致基于闭合多边形的影子,我猜可能类似于Shadow Volume的实现(d3d sdk的那个例子我就没看懂过,干), 但是奇怪的是, Ogre的这种模版阴影的效率居然还相当高。
目测市面上一些Ogre引擎的网游,都采用过这种影子。缺点是边缘比较尖锐,也无法做模糊。
(2)纹理阴影 SHADOWTYPE_TEXTURE 也分MODULATIVE, ADDITIVE两种, Ogre本身的所谓Texture Shadow, 大概是project Shaodw的做法,按光照方向把物体渲染到texture上, 然后把这张图project到接收影子的物体上。 所谓的modulative, additive, 应该只是最后如何贴上影子texture的方法。 但似乎并不仅限于此,中间还有其他的工作。我无法从Ogre的文档中得到足够的信息。而且因为代码封装的缘故,从source上也很难看出所以然。project shadow可以只用固定管线的来实现; 当然更流行的方法还是用shader写入影子的像素。
这些在Ogre中都得到了体现。这种方法很传统,如果改进的足够好,缺点很少。 除了不支持自投影。
(3)纹理阴影可以完全改造成shadow map, 抛弃project map的做法。这个应该是当前的主流。如果要做shadow map, 阴影的cast和receive就只能用shader来做了,而且显卡要支持32F。早年因为不支持浮点精度,需要做一些解码的花哨工作,现在应该可以忽略这些trick了吧。
Ogre的shadow map的做法,和所有的SM做法都大同小异。 同样是Z buffer的比较, 同样要面临Depgth buffer精度不足、Size不够大、锯齿怎么办、Z Fighting如何处理、如何模糊、如何PCF的问题。 当然, 更麻烦的可能是如何改善perspective projection等等诸如此类让影子投出来更加好看的若干方法, 几何和数学公式在这里设置了屏障,我只好跟在不知所谓的Paper后面茫然无助。
(4)
测试用例一: 带有骨骼动画、法线贴图、深度贴图;需要投射阴影, 使用自己改造后的ogre shadow map。
这个用例很奇怪的就在程序写完之后就跑起来了。 影子很正常,连它的锯齿都很正常。 这时候我发现一件奇怪的事, 我的shader完全是按静态模型的parallax map写的, 甚至生成depth map那一段也没有经过skin matrix变换,但是ogre却依然让模型动了起来。 我日,还有这等好事。 我翻看了一些文档, 大概好像是Ogre引擎能自动识别带有skin动画的模型,并且如果发现材质通道没有提供vertex skin步骤的话,
会自动做soft blend。就是说, 传到显卡管线里的顶点,已经是软件skin好的。 而且, ogre引擎自称它会灰常高效的做这个操作。 说实话,我想不出它如何能高速的填充vertex buffer。 看起来,ogre的软件skin效率真的还不错。
通常的做法: 带有骨骼动画的模型要写depth buffer, 一般通过hardwareSkinningWeight的VS计算出顶点位置,然后写入深度信息即可。能够用硬件做应该会快一些。 我没有真的去写这个hardware skin shadow map的用例去比较,想当然会快一些。
测试用例二: 换了一个场景, 还是带骨骼动画的模型,和地面
问题来了: 不知道为什么,投射影子只有一个方块。 大概推测是light cameramatrix 有点问题, 不过我无法推测问题在哪里。 用了LiSPSM, 问题就解决了。 不过很遗憾, LiSPSM这个东西, 在Ogre本身就封装好了,所做的事情,只要创建一个对象设置到场景里去就行。我翻看了LiSPSM的Paper, 很揪心的发现,好像不认识的公式很多。 短时间内看不懂。
(5)
所谓shadow, 从来都是图形的话题。 Shadow map是更新更难缠的话题。 如果在跟Ogre搞在一起, 就更加说不清了。
Ogre的封装初衷, 是为了更加方便程序员使用。 这些确实让很多非图形程序员欣喜若狂,不需要啃3D API就能摆弄引擎,确实令很多怀着开发3D游戏梦想的人夜不能寐。 确实,有一群足够聪明的人在开发Ogre, 他们的设计让很多人快速搭建出了游戏或者Demo,几乎不需要掌握任何d3d Api。 但是,我认为,过度臃肿的封住, 也让后期的Ogre使用变得困难。 这种困难,在我做影子的尝试中,表现成各种束缚和难受,以及ogre本身的bug,或者是我无法明白的现象。
Ogre已经做的足够好, 但是它还是不像看起来的那么好。 过度的封装,越来越庞大的代码、无法解释的现象,让后期很多东西真的很难处理,让引擎本身成为束缚, 可能会陷入死角。更致命的是,会让研究Ogre这件事变得没有乐趣。
最后的结果可能是:要么抛弃它,要么完全搞明白。
需要有很多志同道合的朋友来讨论这些,解答问题。