ogre 引擎 框架追踪 第六章 渲染流程
来源:互联网 发布:手机mac地址伪装 编辑:程序博客网 时间:2024/06/05 23:56
ogre 引擎 框架追踪 第五章 资源加载之实加载
ogre的监听模式在渲染流程中得到大量的应用。
自己控制渲染时候可以在mfc的ontimer或者while语句中,直接调用root的renderOneFrame函数。
bool Root::renderOneFrame(void) { if(!_fireFrameStarted())//开始 return false; if (!_updateAllRenderTargets())//更新 return false; return _fireFrameEnded();//结束 }
看代码的三句话,按表面意思就是:帧开始->更新渲染物状态->帧结束。
渲染之帧开始
bool Root::_fireFrameStarted() { FrameEvent evt; populateFrameEvent(FETT_STARTED, evt);//我们没有设置FrameEvent,先设置FrameEvent,得到距上一frame的时间。 return _fireFrameStarted(evt); }
跟进
bool Root::_fireFrameStarted(FrameEvent& evt) { OgreProfileBeginGroup("Frame", OGREPROF_GENERAL); // Remove all marked listeners,从监听者中移除标记为移除的。移除时候是先将listener标记为移除的,在frame开始时候真的移除的 set<FrameListener*>::type::iterator i; for (i = mRemovedFrameListeners.begin(); i != mRemovedFrameListeners.end(); i++) { mFrameListeners.erase(*i); } mRemovedFrameListeners.clear(); // Tell all listeners for (i= mFrameListeners.begin(); i != mFrameListeners.end(); ++i) { if (!(*i)->frameStarted(evt)) return false; } return true; }
先看下mFrameListeners都有啥东西吧。
根据先后顺序
(1)FrameTimeControllerValue(渲染帧时间控制器),在root初始化时由mControllerManager的创建而调用。
(2)自己程序通过Root::addFrameListener添加的监听者。一般自己控制动画时都需要继承自监听者。
第一个是必须的,用以计算最新frame time
所有,帧开始办了三件事(1)真的移除掉标记为移除的帧监听者(2)通知了渲染帧时间控制器计算frame time,(3)调用了其他监听者的帧开始
渲染之更新渲染物
_updateAllRenderTargets
bool Root::_updateAllRenderTargets(void) { // update all targets but don't swap buffers,更新但不替换buffer mActiveRenderer->_updateAllRenderTargets(false); // 用户用的帧刷新 bool ret = _fireFrameRenderingQueued();//触发所有的frameRenderingQueued // block for final swap mActiveRenderer->_swapAllRenderTargetBuffers(mActiveRenderer->getWaitForVerticalBlank()); // This belongs here, as all render targets must be updated before events are // triggered, otherwise targets could be mismatched. This could produce artifacts, // for instance, with shadows. for (SceneManagerEnumerator::SceneManagerIterator it = getSceneManagerIterator(); it.hasMoreElements(); it.moveNext()) it.peekNextValue()->_handleLodEvents(); return ret; }
跟进_updateAllRenderTargets
RenderTargetPriorityMap::iterator itarg, itargend; itargend = mPrioritisedRenderTargets.end(); for( itarg = mPrioritisedRenderTargets.begin(); itarg != itargend; ++itarg ) { if( itarg->second->isActive() && itarg->second->isAutoUpdated())//判断渲染对象是否激活、是否自动跟新。 itarg->second->update(swapBuffers);//更新 }
mPrioritisedRenderTargets变量为renderwindow、movableObject等渲染物的优先级及渲染物指针的map。必有的就是renderwindow
RenderTarget::update->updateImpl
_beginUpdate();//告知监听者要开始更新了,同时设置状态_updateAutoUpdatedViewports(true);//更新自动更新视口_endUpdate();//结束更新,设置状态
_updateAutoUpdatedViewports跟进
void RenderTarget::_updateAutoUpdatedViewports(bool updateStatistics) { // Go through viewports in Z-order,根据z-order来走一遍视口更新 // Tell each to refresh ViewportList::iterator it = mViewportList.begin(); while (it != mViewportList.end()) { Viewport* viewport = (*it).second; if(viewport->isAutoUpdated()) { _updateViewport(viewport,updateStatistics); } ++it; } }
跟进_updateViewport
void RenderTarget::_updateViewport(Viewport* viewport, bool updateStatistics) { assert(viewport->getTarget() == this && "RenderTarget::_updateViewport the requested viewport is " "not bound to the rendertarget!"); fireViewportPreUpdate(viewport);//告诉监听者准备更新视口了 viewport->update();//视口更新 if(updateStatistics)//更新状态 { mStats.triangleCount += viewport->_getNumRenderedFaces(); mStats.batchCount += viewport->_getNumRenderedBatches(); } fireViewportPostUpdate(viewport); }
viewport->update()调用视口绑定的相机来渲染场景mCamera->_renderScene(this, mShowOverlays)
跟进
void Camera::_renderScene(Viewport *vp, bool includeOverlays) { OgreProfileBeginGPUEvent("Camera: " + getName());//调用渲染系统的beginProfileEvent,触发下渲染系统的开始前的准备事件 //update the pixel display ratio,更新像素展示比例 if (mProjType == Ogre::PT_PERSPECTIVE)//透视模式 { mPixelDisplayRatio = (2 * Ogre::Math::Tan(mFOVy * 0.5f)) / vp->getActualHeight(); } else//正交模式 { mPixelDisplayRatio = (mTop - mBottom) / vp->getActualHeight(); } //notify prerender scene ListenerList listenersCopy = mListeners; for (ListenerList::iterator i = listenersCopy.begin(); i != listenersCopy.end(); ++i) { (*i)->cameraPreRenderScene(this);//告知监听者 } //render scene mSceneMgr->_renderScene(this, vp, includeOverlays);//场景管理器去渲染场景 // Listener list may have change listenersCopy = mListeners; //notify postrender scene for (ListenerList::iterator i = listenersCopy.begin(); i != listenersCopy.end(); ++i) { (*i)->cameraPostRenderScene(this); } OgreProfileEndGPUEvent("Camera: " + getName()); }
mSceneMgr->_renderScene继续跟进
OgreProfileGroup("_renderScene", OGREPROF_GENERAL); Root::getSingleton()._pushCurrentSceneManager(this); mActiveQueuedRenderableVisitor->targetSceneMgr = this;//设置队列访问者 mAutoParamDataSource->setCurrentSceneManager(this);//设置当前场景管理器,为多管理器使用 // Also set the internal viewport pointer at this point, for calls that need it // However don't call setViewport just yet (see below) mCurrentViewport = vp; // reset light hash so even if light list is the same, we refresh the content every frame LightList emptyLightList; useLights(emptyLightList, 0); if (isShadowTechniqueInUse()) { // Prepare shadow materials initShadowVolumeMaterials(); } // Perform a quick pre-check to see whether we should override far distance // When using stencil volumes we have to use infinite far distance // to prevent dark caps getting clipped if (isShadowTechniqueStencilBased() && //stencil的阴影策略 camera->getProjectionType() == PT_PERSPECTIVE && camera->getFarClipDistance() != 0 && mDestRenderSystem->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE) && mShadowUseInfiniteFarPlane) { // infinite far distance,设置无限远的远切面 camera->setFarClipDistance(0); } mCameraInProgress = camera; // Update controllers ControllerManager::getSingleton().updateAllControllers(); // Update the scene, only do this once per frame unsigned long thisFrameNumber = Root::getSingleton().getNextFrameNumber(); if (thisFrameNumber != mLastFrameNumber) { // Update animations,更新动画 _applySceneAnimations(); updateDirtyInstanceManagers(); mLastFrameNumber = thisFrameNumber; } { // Lock scene graph mutex, no more changes until we're ready to render,解释的很清楚,锁住场景画面 OGRE_LOCK_MUTEX(sceneGraphMutex) /////////////////////////////////////灯光下的阴影材质设置 if (mIlluminationStage != IRS_RENDER_TO_TEXTURE && mFindVisibleObjects) { // Locate any lights which could be affecting the frustum,在视锥内有用的灯 findLightsAffectingFrustum(camera); // Are we using any shadows at all? if (isShadowTechniqueInUse() && vp->getShadowsEnabled()) { // Prepare shadow textures if texture shadow based shadowing // technique in use if (isShadowTechniqueTextureBased()) { OgreProfileGroup("prepareShadowTextures", OGREPROF_GENERAL); // ******* // WARNING // ******* // This call will result in re-entrant calls to this method // therefore anything which comes before this is NOT // guaranteed persistent. Make sure that anything which // MUST be specific to this camera / target is done // AFTER THIS POINT prepareShadowTextures(camera, vp); // reset the cameras & viewport because of the re-entrant call mCameraInProgress = camera; mCurrentViewport = vp; } } } // Update scene graph for this camera (can happen multiple times per frame),为本相机更新画面,一帧可能走好几次(一般都是好几次,次数决定于rendertarget的数量) { OgreProfileGroup("_updateSceneGraph", OGREPROF_GENERAL); _updateSceneGraph(camera);//真正的刷新场景画面的地方,node更新,包围盒更新 // Auto-track nodes,相机跟随node的设置 AutoTrackingSceneNodes::iterator atsni, atsniend; atsniend = mAutoTrackingSceneNodes.end(); for (atsni = mAutoTrackingSceneNodes.begin(); atsni != atsniend; ++atsni) { (*atsni)->_autoTrack(); } // Auto-track camera if required,如果设置了相机的自动跟踪某个节点,在这儿处理 camera->_autoTrack(); } // Invert vertex winding?,用到这是、反射效果时需要设置 if (camera->isReflected()) { mDestRenderSystem->setInvertVertexWinding(true); } else { mDestRenderSystem->setInvertVertexWinding(false); } //下面的几项设置gpu编程的 默认参数的值。 // Tell params about viewport,视口 mAutoParamDataSource->setCurrentViewport(vp); // Set the viewport - this is deliberately after the shadow texture update setViewport(vp); // Tell params about camera,相机 mAutoParamDataSource->setCurrentCamera(camera, mCameraRelativeRendering); // Set autoparams for finite dir light extrusion,灯 mAutoParamDataSource->setShadowDirLightExtrusionDistance(mShadowDirLightExtrudeDist); // Tell params about current ambient light,环境光 mAutoParamDataSource->setAmbientLightColour(mAmbientLight); // Tell rendersystem mDestRenderSystem->setAmbientLight(mAmbientLight.r, mAmbientLight.g, mAmbientLight.b); // Tell params about render target mAutoParamDataSource->setCurrentRenderTarget(vp->getTarget()); // Set camera window clipping planes (if any),设置相机剪切平面 if (mDestRenderSystem->getCapabilities()->hasCapability(RSC_USER_CLIP_PLANES)) { mDestRenderSystem->resetClipPlanes(); if (camera->isWindowSet()) { mDestRenderSystem->setClipPlanes(camera->getWindowPlanes()); } } // Prepare render queue for receiving new objects,准备渲染队列,以接受新的物体 { OgreProfileGroup("prepareRenderQueue", OGREPROF_GENERAL); prepareRenderQueue();//设置有阴影的物体,设置无阴影的材质,把工作队列分组 } if (mFindVisibleObjects) { OgreProfileGroup("_findVisibleObjects", OGREPROF_CULLING); // Assemble an AAB on the fly which contains the scene elements visible // by the camera. CamVisibleObjectsMap::iterator camVisObjIt = mCamVisibleObjectsMap.find( camera ); assert (camVisObjIt != mCamVisibleObjectsMap.end() && "Should never fail to find a visible object bound for a camera, " "did you override SceneManager::createCamera or something?"); // reset the bounds camVisObjIt->second.reset(); // Parse the scene and tag visibles,找到相机中可见的 object(在设置物体visibleflag时候设置的是否可见) firePreFindVisibleObjects(vp); _findVisibleObjects(camera, &(camVisObjIt->second), mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false); firePostFindVisibleObjects(vp); mAutoParamDataSource->setMainCamBoundsInfo(&(camVisObjIt->second)); } // Add overlays, if viewport deems it,overlay的更新 if (vp->getOverlaysEnabled() && mIlluminationStage != IRS_RENDER_TO_TEXTURE) { OverlayManager::getSingleton()._queueOverlaysForRendering(camera, getRenderQueue(), vp); } // Queue skies, if viewport seems it,天空的更新 if (vp->getSkiesEnabled() && mFindVisibleObjects && mIlluminationStage != IRS_RENDER_TO_TEXTURE) { _queueSkiesForRendering(camera); } } // end lock on scene graph mutex//渲染系统顶点数清零 mDestRenderSystem->_beginGeometryCount(); // Clear the viewport if required,视口清理 if (mCurrentViewport->getClearEveryFrame()) { mDestRenderSystem->clearFrameBuffer( mCurrentViewport->getClearBuffers(), mCurrentViewport->getBackgroundColour(), mCurrentViewport->getDepthClear() );//清理 } // Begin the frame,激活视剪切 mDestRenderSystem->_beginFrame(); // Set rasterisation mode,光栅化模式(点、网格、体) mDestRenderSystem->_setPolygonMode(camera->getPolygonMode()); // Set initial camera state,投影矩阵 mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS()); mCachedViewMatrix = mCameraInProgress->getViewMatrix(true); //更新相机位置,若相机设置为相对坐标的话 if (mCameraRelativeRendering) { mCachedViewMatrix.setTrans(Vector3::ZERO); mCameraRelativePosition = mCameraInProgress->getDerivedPosition(); } mDestRenderSystem->_setTextureProjectionRelativeTo(mCameraRelativeRendering, camera->getDerivedPosition()); //设置投影矩阵 setViewMatrix(mCachedViewMatrix); // Render scene content { OgreProfileGroup("_renderVisibleObjects", OGREPROF_RENDERING); _renderVisibleObjects();//内部调用_renderQueueGroupObjects,不同阴影策略不同的渲染方法,再底层调用renderSingleObject(其中进行shader程序的运行,设置渲染系统的世界矩阵,gpu选择材质pass)->RenderSystem::_render->bindVertexElementToGpu,(glVertexPointer、glTexCoordPointer设置顶点和文字坐标)更新顶点位置、uv等,更新深度偏移->底层调用glDrawElements(若用gl),调用glClientActiveTextureARB, } // End frame mDestRenderSystem->_endFrame(); // Notify camera of vis faces camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount()); // Notify camera of vis batches camera->_notifyRenderedBatches(mDestRenderSystem->_getBatchCount()); Root::getSingleton()._popCurrentSceneManager(this);
SceneManager::_updateSceneGraph跟进
firePreUpdateSceneGraph(cam);//告知监听者Node::processQueuedUpdates();getRootSceneNode()->_update(true, false); firePostUpdateSceneGraph(cam);
渲染物的更新ManualObject::_updateRenderQueue
SceneManager::_renderQueueGroupObjects
SceneManager::renderSingleObject
SceneManager::updateGpuProgramParameters
GLRenderSystem::_render
位置的计算->node->renderable
核心代码的流程:
Root::renderOneFrame->
1、计算evt的两个时间(timeSinceLastEvent、timeSinceLastFrame),用作后面的更新
2、移除掉标记为已删除的监听者
3、告知所有监听者帧开始
4、调用_updateAllRenderTargets的更新所有渲染物(所谓渲染物即渲染对象,可以理解为渲染到哪里)
5、结束
Root::_updateAllRenderTargets->
1、调用RenderSystem::_updateAllRenderTargets更新所有的渲染物(RenderTexture、RenderWindow),更新node、camera、animation、顶点材质等
2、调用用户的帧渲染函数_fireFrameRenderingQueued ,并告知所有监听者
3、替换所有渲染buffer
RenderSystem::_updateAllRenderTargets->
调用RenderTarget::update,更新所有优先级渲染物(如果该渲染物是被激活的并且是自动更新的)
RenderTarget::update->
调用updateImpl更新渲染物
RenderTarget::updateImpl->
1、更新开始,告知监听器,对渲染物状态的两个参数(triangleCount、batchCount)清零
2、调用_updateAutoUpdatedViewports更新所有自动更新的视口
3、结束更新
RenderTarget::_updateAutoUpdatedViewports->
调用所有视口的_updateViewport
RenderTarget::_updateViewport->
1、告知视口时间监听者,视口更新准备函数
2、调用Camera::_renderScene
Camera::_renderScene->
1、根据相机类型(投影、正交)设置像素比例,//直接关系到渲染出来的结果是否真实
2、告知相机事件监听者准备渲染
3、调用SceneManager::_renderScene渲染场景(场景中包含的灯光、阴影、顶点、材质、动画等)
SceneManager::_renderScene->
1、设置当前队列的访问者,设置gpu编程参数场景管理器,设置当前视口,设置当前相机
2、阴影效果用到的材质初始化(只初始化一次)
3、根据情况设置相机远切面是否无限远
4、更新场景中的ogre通用控制器(材质中纹理动画管理器、粒子系统动画管理等)
5、更新帧数,更新动画
6、设置根据场景的视锥中灯的情况,设置阴影材质,可能又会回调到renderscene,因为阴影纹理也是rendertarget
7、更新场景画面,包含节点(node)、包围盒,并在之前和之后告知监听者;同时若相机是有设置了跟踪某个节点,在此时设置相机方位。
8、相机设置了反射、折射后的对渲染系统的特殊设置(gpu编程时候使用)
9、设置gpu编程参数(视口、相机、相机相关、产生阴影的方向灯光照射距离、环境光颜色、渲染物)
10、渲染系统剪切平面设置
11、准备渲染队列
12、遍历,查询到所有该相机视锥内的可见对象(通过八叉树的场景管理方式查询所有时候比较快),包括overlay、天空盒
13、渲染系统在更新前的相关设置:批数目清零、帧缓存清理、帧开始测试、三角模式(网格、顶点或模型)、投影矩阵设置、纹理投影设置、视口矩阵设置
14、调用_renderVisibleObjects,渲染所有可见物体
15、结束一帧
16、告知相机渲染面信息、批信息。弹出当前场景管理器
_renderVisibleObjects->
调用用户自己设置频率的渲染函数或者调用默认的渲染函数renderVisibleObjectsDefaultSequence
renderVisibleObjectsDefaultSequence->
1、告知监听者队列渲染准备
2、告知开始渲染队列
3、调用_renderQueueGroupObjects,渲染队列组中的物体
4、告知队列渲染结束
SceneManager::_renderQueueGroupObjects->
根据不同的阴影策略,调用不同的函数,下面的进入默认情况下 的函数
SceneManager::renderBasicQueueGroupObjects->
1、渲染优先级队列排序
2、调用renderObjects
SceneManager::renderObjects->
1、设置队列访问者
2、调用acceptVisitor
QueuedRenderableCollection::acceptVisitor->
根据组织模式不同,调用不同函数。
以pass分组的进入acceptVisitorGrouped;以相机距离递减的访问acceptVisitorDescending;以相机距离递增的访问acceptVisitorAscending
acceptVisitorGrouped->
调用visit,对所有pass分组下,所有renderable进行访问
SceneMgrQueuedRenderableVisitor::visit->
1、判断是否有效
2、调用renderSingleObject,渲染单个儿object
SceneManager::renderSingleObject->
1、获取renderable,获取pass中 的gpu程序对象
2、设置渲染系统的世界矩阵
3、设置三角模式(pass的)
4、灯列表
5、告知监听者要渲染单个物体
6、渲染系统设置深度偏移
7、更新gpu程序参数,最后一次绑定ogre中的参数与gpu程序的参数
8、调用渲染系统_render渲染
8、重置view的投影模式
GLRenderSystem::_render
1、调用基类_render
2、获取顶点声明信息等相关顶点信息
3、调用bindVertexElementToGpu,将顶点信息同gpu绑定(vertexprogram的顶点、uv信息输入),底层调用的glVertexPointer、glNormalPointer、glColorPointer、glTexCoordPointer等更新顶点及uv信息。
4、顶点索引buffer获取
5、根据顶点信息、索引信息,调用glDrawElements渲染出画面。
6、解绑必要的属性
- ogre 引擎 框架追踪 第六章 渲染流程
- ogre 引擎 框架追踪 第七章 渲染流程之compositor
- ogre 引擎 框架追踪 第二章 初始化
- ogre 引擎 框架追踪 第三章 资源加载之虚加载
- ogre 引擎 框架追踪 第四章 资源加载之资源组初始化
- ogre 引擎 框架追踪 第五章 资源加载之实加载
- ogre 引擎 框架追踪 第一章 root的创建
- OGRE 渲染流程
- Ogre主要渲染流程
- ogre渲染流程
- OGRE - RenderProcess (渲染流程)
- ogre渲染流程
- OGRE 内部渲染流程
- Ogre渲染流程
- ogre渲染流程
- Ogre 渲染流程 RenderProcess
- ogre 渲染流程
- ogre的主要渲染流程
- mac 上安装redis
- 关于jQuery中isNumeric 方法判断数字的深刻理解
- Gallery + ViewPager实现图片浏览器
- android面试题
- volatile与synchronized
- ogre 引擎 框架追踪 第六章 渲染流程
- opencv环境搭建(linux)
- [leetcode] 421. Maximum XOR of Two Numbers in an Array 解题报告
- Android开发人员不得不收集的代码
- 第4章 Spring MVC基础
- web安全————XSS(预防篇)
- 四元数初学
- mysql查询出现ambiguous的问题
- kafka的解析