OGRE的灯光接口很简单,以Demo_Lighting工程为例:
1.
创建灯光:Light* SceneManager::createLight(const String& name)
此函数再调用“SceneManager::createMovableObject()”,创建一个Light的实例,然后加入到ObjectMap中(保存在SceneManager::mMovableObjectCollectionMap)。
2. 设置灯光属性:调用Light类的接口,设置灯光类型、颜色、衰减、位置、方向。
Light类从MoveableObject派生。目前Ogre支持点光源、方向光、聚光灯三种Light。灯光的其它属性都保存到这个类中。
灯光的渲染时处理在“SceneManager::renderSingleObject()”,参见“Ogre学习笔记(3):Mesh的渲染流程”第11步。这个函数的第一个参数“const Renderable* rend”是需要渲染的对象,Renderble的派生类主要有:Node(SceneNode的父类)、SubEntity。第二个参数“const Pass* pass”。在处理灯光的时候,根据Pass的设置(Pass:: getIteratePerLight),有可能对于Renderable中的每个灯光执行一次渲染,也可能一次渲染所有光照。对于programable pass(Pass:: isProgrammable),调用“mAutoParamDataSource.setCurrentLightList()”设置light list,对于固定渲染管道则调用“RenderSystem:: _useLights()”来设置light list。
可见Ogre的灯光处理是非常灵活的,支持per light-per pass,也支持fixed function pipeline灯光,还可以根据Pass支持的灯光的个数来“喂”给它正确的灯光参数。
下面看一下Renderable的LightList是如何得到的?Renderable::getLights()函数被很多派生类重写,下面分析几个主要的。对于SubEntity,它找到自己属于那个SceneNode,然后调用SceneNode::findLights()==》SceneManager:: _populateLightList(),此函数遍历所有灯光,根据灯光属性,和传进来的位置、半径计算是否影响此物体,然后建立一个LightList,还进行了排序。对于Node类,它只是简单的返回一个空列表。
OGRE这部分处理的过于简单了,没有处理遮挡的问题。例如在屋子里的一个火把,它不应该照亮墙外的一个角色。