阴影体是一种动态阴影技术。
仔细一看,这玩意儿其实很简单。
利用的模拟缓冲的功能,把阴影体画进模板缓冲即可。
这要求计算出物体对着光线的轮廓。
本来觉得,怎么样高效地求出这个轮廓,发现irricht实现得非常简单,同时也意味着不够优化(笔者看的irricht版本是1.7的,可能最新的版本优化了)
irricht直接取面对光线的那些多边形,然后利用这些多边形构造阴影体。(可以想像,阴影体是背对光线延伸至无穷远,irricht的"无穷远"是1000)
irricht的阴影体定义成一个对象CShadowVolumeSceneNode
这个对象会做为CAnimatedMeshSceneNode的子节点,进入场影管理,
并在OnRegister时,进入场影的shadow list
CShadowVolumeSceneNode 会去取CAnimatedMeshSceneNode当前帧对应的mesh,并计算阴影体
irricht首先渲染所有的物体,例如CAnimatedMeshSceneNode
然后才渲染阴影体。
把阴影体画进模板,然后再画一个矩形,把整个渲染遮住,在画这个矩形时,会做模板测试,
只有模板缓存中的阴影体会被渲染,在视觉就形成了阴影。
这样就可以了?
这里还需要做一个简单的处理。
接下来的东西说起来拗口,但一画图就非常简单了。
图中的矩形是物体,因为光源而产生的阴影,物体1和物体3处于阴影中,而物体2显然不处于阴影当中。
如果不做处理,根据模板缓存里画出的阴影体直接渲染,则会错误地把物体2也画成处于阴影的状态。
irricht的处理如下:
这个函数中有这么一段代码
glStencilOp(GL_KEEP, incr, GL_KEEP);
glCullFace(GL_FRONT);
glDrawArrays(GL_TRIANGLES,0,count);
glStencilOp(GL_KEEP, decr, GL_KEEP);
glCullFace(GL_BACK);
glDrawArrays(GL_TRIANGLES,0,count);
会画两次,多边形可以认为有两个面(front back),
打开深度缓存,做比较,类似出栈入栈,在物体之后的阴影体多边的,遇到背面+1, 遇到正面-1,
最终,如果为0,表示该点不同阴影体之内,如果不为0,就需要加入阴影效果。
这样就可以正确把阴影效果表现出来。
相关的理论,有更详细的文章,请参考
http://blog.youkuaiyun.com/kongbu0622/article/details/1838317
求得阴影体后往模板里画就可以了?
这里还需要做一个简单的处理。