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
}