OGRE 阴影详解

来源:互联网 发布:爸爸网络词的意思 编辑:程序博客网 时间:2024/06/03 14:07

OGRE 中可以使用三种形式的阴影技术 (ShadowTechnique) ,这个在引擎评估专栏的《 OGRE (10) -- 投影》一节中已经有过简要的说明,这里进一步研究三种阴影技术的一些具体差异和细节控制。

示例代码中除了阴影技术的演示之外还包括了键盘输入的处理,按主键盘上的 [1] 、 [2] 、 [3] 、 [4] 可以在各种阴影技术之间切换:
[1] SHADOWTYPE_NONE
[2] SHADOWTYPE_STENCIL_MODULATIVE
[3] SHADOWTYPE_STENCIL_ADDITIVE
[4] SHADOWTYPE_TEXTURE_MODULATIVE
键盘输入的处理留到下一节再具体讲解,这一章专讲阴影技术。
Ogre:: ShadowTechnique 本身是一个枚举类型,在头文件 OgreCommon.h 中定义:

      enum ShadowTechnique      
 {         
    SHADOWTYPE_NONE,                        // 无阴影          
    SHADOWTYPE_STENCIL_MODULATIVE,          // 模版调制阴影       
     SHADOWTYPE_STENCIL_ADDITIVE,            // 模版叠加阴影     
      SHADOWTYPE_TEXTURE_MODULATIVE,          // 纹理调制阴影    
   };

下面我们通过截图比较一下后面三种阴影技术各自的不同,包括阴影的细节表现和场景的运行速度。
场景中存在着两盏方向光,一盏是蓝色,一盏是黄色。
你可以对源代码中的各个参数做一些修改,然后观察三个阴影技术彼此之间的具体不同。
Ogre:: SceneManager 类中有一群阴影相关的方法,下面逐一列举并简单说明:
设置/获取阴影技术
virtual void setShadowTechnique (ShadowTechnique technique)
virtual ShadowTechnique getShadowTechnique (void) const
设置/获取调试阴影显示状态
至于什么是调试阴影 (Debug Shadows) ,你把它打开看看就知道了
virtual void setShowDebugShadows (bool debug)
virtual bool getShowDebugShadows (void) const
设置/获取阴影颜色
virtual void setShadowColour (const ColourValue &colour)
virtual const ColourValue & getShadowColour (void) const
设置/获取方向光阴影影响距离
物体距灯光超过这个距离,就不再计算它的阴影以节省场景运算。
virtual void setShadowDirectionalLightExtrusionDistance (Real dist)
virtual Real getShadowDirectionalLightExtrusionDistance (void) const
设置/获取阴影最大可见距离
阴影距镜头超过这个距离,就不再在视野中显示。注意这个跟上面的方向光阴影影响距离不同,上面那个是指物体距灯光的最大距离,这个是指阴影本身距镜头的最大距离。
virtual void setShadowFarDistance (Real distance)
virtual Real getShadowFarDistance (void) const
设置/获取阴影索引缓存大小
为了计算物体的阴影, OGRE 在 GPU 中设置了一个缓存区用于保存物体的顶点索引,默认是 51,200 个,大约占用 100KB GPU ,足够渲染大约 17,000 个三角形。你可以修改这个索引缓存的大小,使之适合场景中物体的顶点总数,顶点总数大约等于三角形总数的 3 倍。
virtual void setShadowIndexBufferSize (size_t size)
virtual size_t getShadowIndexBufferSize (void) const
设置/获取阴影纹理尺寸
当你使用纹理调制阴影技术( SHADOWTYPE_TEXTURE_MODULATIVE )的时候, OGRE 需要先把物体的阴影渲染到一张纹理贴图上,然后再与地板或墙壁做调制运算。这张纹理贴图的尺寸越大,阴影看上去就越清晰;尺寸越小,阴影看上去就越粗糙。
但是要注意,如果你使用 OpenGL 渲染系统,纹理贴图的边长不能超过 OGRE 渲染窗口的尺寸,一般设置为不大于 512 。
virtual void setShadowTextureSize (unsigned short size)
unsigned short getShadowTextureSize (void) const
设置/获取阴影纹理数目
当你使用纹理调制阴影技术( SHADOWTYPE_TEXTURE_MODULATIVE )的时候,每张阴影纹理贴图只能渲染一盏灯光所产生的阴影,所以如果场景中存在多盏灯光,你可能需要把阴影纹理数目相应调大以使每盏灯光都可以投射阴影。
virtual void setShadowTextureCount (unsigned short count)
unsigned short getShadowTextureCount (void) const
设置阴影纹理设定
这个方法是上面两个方法的结合版,同时设置阴影纹理的尺寸和个数。
virtual void setShadowTextureSettings (unsigned short size, unsigned short count)
设置方向光阴影纹理偏移
当你使用纹理调制阴影技术( SHADOWTYPE_TEXTURE_MODULATIVE )的时候, OGRE 首先对每盏方向光产生一张阴影纹理,具体做法就是,把这盏灯光作为一个镜头,把这个镜头中看到的投影物体渲染下来,不是真实的渲染,只是用单色渲染出来一个“影子”,影子的边缘之外都是透明的,然后把这张阴影纹理蒙到物体所投射到的表面。
而这个方向光阴影纹理偏移,是控制在渲染这张阴影纹理的时候,纹理距离作为“镜头”的光源的远近。纹理距离“镜头”太近,会导致纹理贴图的大部分边缘区域超出了“镜头”的视野之外,所以我们使用这个纹理偏移,使这张纹理图远离作为“镜头”的光源中心,以最大限度地利用纹理贴图的空间。当场景很大的时候,这个纹理偏移很有用。
打个比方,手电筒发射光束,打在远处的墙上形成一个大光圈,我们拿着一张报纸截断这束光,距离手电筒越近,光打在报纸上的光圈就越小,报纸上就有更多的边缘区域是黑暗的,对于阴影纹理来说,就是有更多的边缘区域没有被利用,浪费了。
这个偏移值是一个从 0 到 1 的比率:从光源位置到 ShadowFarDistance * 2 。
virtual void setShadowDirLightTextureOffset (Real offset)
设置阴影纹理淡出起始距离/结束距离
这两个距离也是从 0 到 1 的比率:占 setShadowFarDistance 所指定的阴影最大可见距离的比率。它指定当阴影上的一点距离镜头超过起始距离之后,这一点上的阴影就开始变淡,直到达到结束距离就完全看不见了。效果可以参看下面的截图,可以看到近处的阴影颜色比远处的深一些。
virtual void setShadowTextureFadeStart (Real fadeStart)
virtual void setShadowTextureFadeEnd (Real fadeEnd)

 

设置是否使用阴影无限远截面
当阴影的投射距离超出镜头的远视距离之后,阴影的计算就会出毛病,导致场景变花。为了解决这个问题,我们对阴影使用一个无限远的投射平面,可以一定程度上防止阴影计算错误。
virtual void setShadowUseInfiniteFarPlane (bool enable)
具体的细节差异,修改一下源代码的各项参数观察一下。
设置了阴影技术之后,还不算完,还需要打开各个物体的阴影属性包括光源的阴影属性,使用 setCastShadows 方法:
void Ogre::MovableObject:: setCastShadows ( bool enabled ) [inline, inherited]
在本节的例子中,关闭了地面模型的阴影属性,如果打开,投影计算会有问题,也没必要。
最后要注意,纹理阴影相关的很多方法都只对方向光起作用,不支持点光源或锥形光。

0 0
原创粉丝点击