Ogre 渲染流程

在ogre中,调用renderOneFrame就是渲染一帧的画面, 所以要了解Ogre渲染流程就直接单步调试跟着renderOneFrame走就好了。
本文以调用栈的方式展示ogre渲染流程,由于调用栈是在太深,所以会根据功能分块描述渲染进行到哪一步。

1. renderOneFrame

下面是主要调用堆栈,这部分主要描述了:所谓渲染实际上就是更新视口的画面,而画面则来自与视口绑定的摄像机所看到的场景。

Root::renderOneFrame(void)							//渲染入口
  _updateAllRenderTargets()							//更新所有渲染目标
    mActiveRenderer->_updateAllRenderTargets()		
      forach(RenderTargetPriorityMap)->update()		//遍历所有目标进行更新
        updateImpl()								
          _updateAutoUpdatedViewports()				//更新视口
            foreach(ViewportList)->_updateViewport()//遍历每一个视口
              viewport->update()			  		
			    mCamera->_renderScene()/*通过与视口绑定的摄像机渲染场景,这里在第二节展开*/
    mActiveRenderer->_swapAllRenderTargetBuffers()	//渲染完毕后,交换渲染缓存
    SceneManagerEnumerator->_handleLodEvents()      //通知更新场景事件

2. _renderScene

这部分的主要作用是准备渲染场景所需要的灯光和物体。
流程如下:

  • 初始化场景中的设置
  • 更新控制器、动画等类的参数,从而更新节点的属性(位置、方向等)
  • 更新节点的包围盒,重新计算各个节点的包围盒
  • 更新摄像机状态
  • 遍历灯光,找出会影响摄像机的灯光(计算是否与摄像机视锥相交)
  • 准备阴影纹理(如果有)
  • 遍历物体,找出需要渲染的物体添加进渲染队列(计算是否与摄像机视锥相交)
  • 渲染物体
  • 渲染后操作
mCamera->_renderScene()
	listeners->cameraPreRenderScene()						//摄像机渲染器前处理
	mSceneMgr->_renderScene()
	Root::getSingleton()._pushCurrentSceneManager(this)		//加入场景栈

	mDestRenderSystem->setDrawBuffer()						//设置缓存
	useLights()												//添加附加灯光
		mDestRenderSystem->_useLights()
	initShadowVolumeMaterials()								//初始化阴影材质
	ControllerManager::updateAllControllers()				//更新控制器
		foreach(ControllerList)->update()
	_applySceneAnimations()									//更新动画
	updateDirtyInstanceManagers()							//更新脏实例管理器

	//更新所有场景节点包围盒(AABB)
	_updateSceneGraph(camera)								
		processQueuedUpdates()								
		foreach(Node : msQueuedUpdates)->needUpdate(true)	//重设节点状态
		msQueuedUpdates->clear()
		getRootSceneNode()->_update()						//从根节点开始更新
		_updateFromParent()
		foreach(Node : ChildNodeMap)->_update()				//递归更新子节点
		_updateBounds()										//更新节点包围盒(AABB)
			foreach(mObjects) mWorldAABB.merge(mObjects->getWorldBoundingBox())	//合并包围盒
			foreach(mChildren) mWorldAABB.merge(child->mWorldAABB())			//合并子节点包围盒

	//对于设置了跟踪目标的对象随目标对象更新朝向
	foreach(AutoTrackingSceneNodes)->autoTrack()
		lookAt(mAutoTrackTarget)
	camera->_autoTrack()

	//找出可能影响摄像机(视锥)的灯光
	findLightsAffectingFrustum(camera)					
		lights = getMovableObjectCollection("Light")
		foreach(lights)
			if(camera->isVisible(sphere(light.position, light.range)))	//判断摄像机的范围与灯光范围是否重叠
				mTestLightInfos.push_back(lightInfo);
		stable_sort(mLightsAffectingFrustum)							//对灯光进行排序,以确定用以生成阴影的灯光

	//阴影纹理初始化
	if(isShadowTechniqueInUse() && isShadowTechniqueTextureBased())		//如果启用了纹理阴影
		prepareShadowTextures()
		mShadowRenderer.prepareShadowTextures(cam, vp, lightList)		//渲染阴影纹理
	mDestRenderSystem->setInvertVertexWinding(camera->isReflected())	//是否反转顶点
	setViewport(vp)														//如果之前启用了阴影纹理,这里会换成渲染了阴影纹理的视口

	//设置摄像机、灯光距离、目标对象等渲染参数
	mAutoParamDataSource->setCurrentCamera()
	mAutoParamDataSource->setShadowDirLightExtrusionDistance()
	mAutoParamDataSource->setCurrentRenderTarget()
	mDestRenderSystem->setClipPlanes()

	//准备渲染队列
	prepareRenderQueue()											//初始化渲染队列(清空)
		q = getRenderQueue()
		if(mLastRenderQueueInvocationCustom)						//如果上次启用了自定义渲染,而本次没有,则返回默认设置
			foreach(q->_getQueueGroups)->defaultOrganisationMode()
		updateRenderQueueSplitOptions()								//更新全局渲染设置(阴影纹理相关)

	//查找能被摄像机看到的目标物体 添加进队列
	camVisObjIt = mCamVisibleObjectsMap.find( camera )				//渲染目标队列
	_findVisibleObjects(camera)
		foreach(getRootSceneNode()->_findVisibleObjects())			//从根节点开始,计算所有实体并添加到渲染目标队列
		queue->processVisibleObject(mo, cam, onlyShadowCasters, visibleBounds)
		foreach(mChildren)->_findVisibleObjects()					//递归查找子节点
		queue->addRenderable(getDebugRenderable())					//添加自己到目标队列
		if(mShowBoundingBox)_addBoundingBoxToQueue(queue)			//如果要显示节点边框,也添加进渲染目标队列
	mAutoParamDataSource->setMainCamBoundsInfo(camVisObjIt)			//把渲染目标队列添加进渲染参数
	mSkyRenderer.queueSkiesForRendering(getRenderQueue(), camera)	//把天空盒添加进目标队列

	//渲染队列准备完毕,检查是否保留上次渲染结果(覆盖渲染)
	if(mCurrentViewport->getClearEveryFrame())
		mDestRenderSystem->clearFrameBuffer()			//如果视口要求每帧重绘,则清空帧缓存

	/*渲染所有渲染队列中的物体,此处在第三节中展开*/
	_renderVisibleObjects()

	//渲染结束
	Root::getSingleton()._popCurrentSceneManager(this)	//退出场景栈
	listeners->cameraPostRenderScene()					//摄像机渲染后处理

3. _renderVisibleObjects

这部分的作用是决定启用的渲染序列和阴影纹理(自定义渲染器就是覆盖着部分的内容)。

_renderVisibleObjects() 
	//获取自定义渲染序列
	invocationSequence = mCurrentViewport->_getRenderQueueInvocationSequence() 

	//只有关闭阴影纹理才能使用自定义渲染序列
	if(mIlluminationStage != IRS_RENDER_TO_TEXTURE)		
		renderVisibleObjectsCustomSequence(invocationSequence)	//启用自定义渲染序列(这里不展开)

	//采用默认渲染序列
	else renderVisibleObjectsDefaultSequence()			
		groups = getRenderQueue()->_getQueueGroups()			//获取渲染序列组
		foreach(groups)											//遍历每个渲染序列组
			//渲染前事件,可以根据需要跳过此次渲染
			if(fireRenderQueueStarted())						
				break;			
			_renderQueueGroupObjects(groups[i])

			//使用阴影纹理的渲染(这里不展开)
			if(isShadowTechniqueTextureBased())			
				mShadowRenderer.renderTextureShadowCasterQueueGroupObjects()

			//带阴影传递的渲染(这里不展开)
			else if(doShadows)							
				mShadowRenderer.render()

			//没有阴影传递的渲染(一般渲染)
			else 
				renderBasicQueueGroupObjects()
					pPriorityGrp = groupIt.getNext()
					pPriorityGrp->sort(camera)							//对渲染目标进行排序(按与摄像机的距离)
					foreach(QueueGroupObjects)							//循环每个渲染序列
						/*按类别渲染物体,在下一节展开*/
						renderObjects(pPriorityGrp->getSolidsBasic())	//渲染实体
						renderObjects(getTransparentsUnsorted())		//渲染未分类的透明物体
						renderObjects(getTransparents())				//渲染透明物体
			
			//渲染后事件,可以根据渲染器要求进行重复渲染(跳回渲染前事件那里)
			if(fireRenderQueueEnded()) goto
	//endif

4. renderObjects

这部分是渲染单个物体前的准备工作。

renderObjects()
	objs.acceptVisitor()
		acceptVisitorGrouped(visitor)
			foreach(visitor)->visit()
				targetSceneMgr->validateRenderableForRendering()			//在渲染前判断是否有冲突或者需要跳过

				//渲染单个物体
				targetSceneMgr->renderSingleObject() 
					mAutoParamDataSource->setCurrentRenderable(rend)		//标记当前正在渲染的目标
					setWorldTransform(rend)

					//如果渲染状态被更改,则直接退出渲染
					if(mSuppressRenderStateChanges)							
						mDestRenderSystem->setCurrentPassIterationCount(1)	//重置渲染次数
						resetViewProjMode()									//重置渲染视图
						return

					//更新需要依赖视图矩阵的纹理贴图
					foreach(getTextureUnitStates()) 
						if hasViewRelativeTextureCoordinateGeneration()
							mDestRenderSystem->_setTextureUnitSettings() 

					//排除归一化,如果使用多个着色器,应当自己手动归一化
					mDestRenderSystem->setNormaliseNormals() 

					//设置负缩放剔除模式(负缩放会把模型的反面替换为正面,而有些模型反面是没有贴图的)
					mDestRenderSystem->_setCullingMode(cullMode)

					//设置摄像机渲染模式PM_POINTS、PM_WIREFRAME、PM_SOLID
					mDestRenderSystem->_setPolygonMode(reqMode) 

					//遍历所有灯光,使用每个灯光渲染目标
					foreach(localLightList)
						issueRenderWithLights() /*使用灯光渲染目标,在下一节展开*/
					
					//渲染结束,重置渲染视图
					resetViewProjMode()
			//end for

5. issueRenderWithLights

渲染的核心部分了,光线与每一个物体的作用(即成像),根据摄像机的渲染模式决定是渲染点、线或者实体等等。gl开头的函数都是OpenGL的函数了,至此已不能再往下跟踪了。

issueRenderWithLights()
	useLights()								//启用灯光
	_issueRenderOp()
		updateGpuProgramParameters()		//把前面设置的参数全部设置到GPU中
		rend->getRenderOperation(ro)
		mDestRenderSystem->_render(ro);
			RenderSystem::_render()			//开始渲染顶点
				
				setClipPlanesImpl()			//裁剪平面
				getElements()				//取出所有顶点

				bindVertexElementToGpu()	//绑定顶点到GPU
					glEnableClientState()	//开启渲染flag
				glClientActiveTextureARB()	

				//确定渲染模式(GL_POINTS、GL_LINES、GL_TRIANGLES等)
				primType = switch(op.operationType)

				//渲染所有节点
				do
					glDrawElements() or glDrawArrays()	//渲染顶点
				while(updatePassIterationRenderState())	//渲染下一个顶点

				glDisableClientState()		//结束渲染flag
			rend->postRender()
	resetLightClip() //重置灯光,准备下一次渲染
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值