在Irrlicth中的整个主循环框架为:
while(device->run())
{
device->beginScene();
sceneManager->drawAll();
guiEnvironment->drawAll();
device->endScene();
}
说明:
device->run() : 事件处理部分
sceneManager->drawAll() : 渲染场景部分
guiEnvironment->drawAll() : 渲染UI部分
sceneManager->drawAll() : 在这个过程里面:
1: Game 时间驱动部分,这一步对于所有物体都是必须进行的操作。
// do animations and other stuff.
// Drive all the objects in the scene no matter the object is visible.
OnAnimate(os::Timer::getTime());
OnAnimate中依次Animate这个Node包含的每一个Animator。然后对每一个子节点调用OnAnimate.
2: 计算出View Frustrum,用于在后面对场景中的物体进行cull 操作
/*!
First Scene Node for prerendering should be the active camera
consistent Camera is needed for culling
*/
camWorldPos.set(0,0,0);
// Compute the camera attribute
if ( ActiveCamera )
{
// Setup the view and project matrix to the driver and recalculate the view frustrum.
ActiveCamera->render();
camWorldPos = ActiveCamera->getAbsolutePosition();
}
但是注意的是ActiveCamera->render();这个操作会将该Camera中的View Matrix和Project Matrix设定到Video Driver中去,也就是设定到DX 中的Device中。但这不是这处代码的作用,这里主要还是为了后面的场景管理部分作准备。
3: 对整个SceneManager中的所有Scene Nodes进行cull,对于没有cull的Node添加到对应的渲染的列表中。而cull掉得,舍弃掉。
// let all nodes register themselves
OnRegisterSceneNode();
OnRegisterSceneNode会将迭代的调用每一个子节点的OnRegisterSceneNode,并一直下去。
OnRegisterSceneNode中的建议方式为:
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
而registerNodeForRendering用来将会检查该Node相对于当前的Camera来进行View Frustrum的可见性判断(在Irrlicht中采用的是AABB模型进行判定)。如果没有被cull,则添加到对应的list中去。
比如:
case ESNRP_SOLID:
if (!isCulled(node)) // visibility detection
{
SolidNodeList.push_back(node);
taken = 1;
}
break;
所以OnRegisterSceneNode应该完成对整个Scene剪裁逻辑。构建对应Pass中的渲染列表。
4: 渲染每一个Rendering Pass。不同的列表在不同的Rendering Pass中进行渲染。
比如:
他的Rendering Pass 的顺序为:
1: Camera Pass, 这里主要是计算Camera的View和Project Matrix,并设定到Fixed Function Pipeline中去。
2: Light Pass
3: Sky-Box
4: Solid Pass
5: Shadow
6: Transparent
7: Transparent_effect.
这里的每一个对应一个列表,在每一次渲染完过后,这些列表会被清空,所以这些列表是Per-Frame constructed。
阅读(762) | 评论(0) | 转发(0) |