6. RenderTarget
RenderTarget用来接收渲染操作的结果,它可以是屏幕上的窗口、离屏面(如texture)等。FPS信息的统计也是由RenderTarget完成的。在RenderTarget每次更新完成后,将会更新统计信息(封装于FrameStats中)。除了负责统计帧的信息外,RenderTarget还负责创建维护Viewport(视口):
typedef std::map<int, Viewport*, std::less<int> > ViewportList;
ViewportList mViewportList;
Viewport* RenderTarget::addViewport(Camera* cam, int ZOrder, float left, float top ,
float width , float height)
{
ViewportList::iterator it = mViewportList.find(ZOrder);
if (it != mViewportList.end())
{
…
}
Viewport* vp = new Viewport(cam, this, left, top, width, height, ZOrder);
mViewportList.insert(ViewportList::value_type(ZOrder, vp));
fireViewportAdded(vp);
return vp;
}
由上面的代码可以看出,每个Viewport都对应一个Camera和一个RenderTarget。当创建一个Viewport后,它会自动建立与Camera的联系。可以把Camera看作是图像的来源,而RenderTarget是图像渲染的目的地。一个Viewport只能对应一个Camera和一个RenderTarget,而一个Camera也只能对应一个Viewport,但RenderTarget却可以拥有几个Viewport。
7. 渲染过程
OGRE通过WinMain或main调用go再通过Root调用startRendering进行消息循环,然后调用renderOneFrame,通过RenderSystem的_updateAllRenderTargets方法,更新所有的RenderTarget。RenderTarget通过update方法更新与之关联的Viewport并产生FPS统计信息。而Viewport则调用与之关联的Camera的_renderScene方法进行渲染,Camera此时把“球”踢给SceneManager。进入SceneManager的renderScene成员函数中后,在经过计算后,把需要渲染的场景送给RenderSystem去做真正的渲染,此时我们可以看到熟悉的_breginFrame和_endFrame。一直下去经过RenderQueue、RenderQueueGroup、RenderPriorityGroup、QueuedRenderableCollection再通过访问者到达QueuedRenderableVisitor的子类SceneMgrQueuedRenderableVisitor,最终又回到SceneManager,由SceneManager再到RenderSystem完成整个渲染过程。过程伪码如下所示:
int WinMain or main(int argc, char **argv)
{
app.go();
}
virtual void go(void)
{
Root->startRendering();
}
void Root::startRendering(void)
{
renderOneFrame();
}
bool Root::renderOneFrame(void)
{
_updateAllRenderTargets();
}
void Root::_updateAllRenderTargets(void)
{
RenderSystem->_updateAllRenderTargets();
}
void RenderSystem::_updateAllRenderTargets(void)
{
RenderTarget->update();
}
void RenderTarget::update(void)
{
Viewport->update();
}
void Viewport::update(void)
{
Camera->_renderScene(this, mShowOverlays);
}
void Camera::_renderScene(Viewport *vp, bool includeOverlays)
{
SceneManager->_renderScene(this, vp, includeOverlays);
}
void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
{
RenderSystem->_beginFrame();
_renderVisibleObjects();
RenderSystem->_endFrame();
}
void SceneManager::_renderVisibleObjects(void)
{
//如果有阴影
renderVisibleObjectsCustomSequence();
//否则
renderVisibleObjectsDefaultSequence();
}
void SceneManager::renderVisibleObjectsDefaultSequence(void)
{
fireRenderQueueStarted(qId,mIlluminationStage)
_renderQueueGroupObjects(pGroup, QueuedRenderableCollection::OM_PASS_GROUP);
fireRenderQueueEnded(qId, mIlluminationStage)
}
void SceneManager::_renderQueueGroupObjects(RenderQueueGroup* pGroup, OrganisationMode om)
{
renderBasicQueueGroupObjects(pGroup, om);
}
void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup, OrganisationMode om)
{
renderObjects(pPriorityGrp->getSolidsBasic(), om, true);
}
void SceneManager::renderObjects(const QueuedRenderableCollection& objs, …)
{
objs.acceptVisitor(mActiveQueuedRenderableVisitor, om);
}
void QueuedRenderableCollection::acceptVisitor(QueuedRenderableVisitor* visitor…)
{
switch(om){
case OM_PASS_GROUP:
acceptVisitorGrouped(visitor);
…
}
}
void QueuedRenderableCollection::acceptVisitorGrouped(QueuedRenderableVisitor* visitor)
{
QueuedRenderableVisitor->visit(Renderable);
}
void SceneManager::SceneMgrQueuedRenderableVisitor::visit(const Renderable* r)
{
SceneManager->renderSingleObject(r, mUsedPass, autoLights, manualLightList);
}
void SceneManager::renderSingleObject(const Renderable* rend, const Pass* pass…)
{
RenderSystem->_render(RenderOperation);
}
最终进入的RenderSystem的子类D3D9RenderSystem or GLRenderSystem。
void D3D9RenderSystem::_render(const RenderOperation& op)
{
mpD3DDevice->DrawIndexedPrimitive or mpD3DDevice->DrawPrimitive
}
void GLRenderSystem::_render(const RenderOperation& op)
{
glDrawElements or glDrawArrays
}