Ogre의 renderScene 코드
Root::startRendering()
Root::renderOneFrame()
Root::_updateAllRenderTargets()
RenderSystem::_updateAllRenderTargets()
RenderTarget::update()
RenderTarget::updateImpl()
RenderTarget::_updateAutoUpdated()
D3D9RenderWindow::_updateViewport()
RenderTarget::_updateViewport()
Viewport::update()
Camera::_renderScene() -- , listener cameraPreRenderScene() cameraPostRenderScene()
SceneManager::_renderScene()
즉, SceneManager::renderScene()은 전체 장면의 렌더링을 책임집니다.이 방법에서는 다음을 수행합니다.
1、그림자가 켜져 있는지 확인하고, 켜져 있으면 초기화합니다
if (isShadowTechniqueInUse())
{
// Prepare shadow materials
initShadowVolumeMaterials();
}
2、시경체에 영향을 줄 수 있는 램프 테스트
// 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); -- shadow texture?No, ?
// reset the cameras & viewport because of the re-entrant call
mCameraInProgress = camera;
mCurrentViewport = vp;
}
}
3. 그 다음에 대다수 상황에서oct tree의 장면 노드 업데이트를 진행한다. 주로 각 노드의 물체가 세계 좌표와 세계 좌표 아래의 포위함 등을 업데이트한다.
_updateSceneGraph(camera);
//octtree _updateSceneGraph
void SceneManager::_updateSceneGraph(Camera* cam)
{
// Process queued needUpdate calls
Node::processQueuedUpdates();
// Cascade down the graph updating transforms & world bounds
// In this implementation, just update from the root
// Smarter SceneManager subclasses may choose to update only
// certain scene graph branches
getRootSceneNode()->_update(true, false);
}
4、render Queue, PVS 생성 준비
// 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
firePreFindVisibleObjects(vp);
_findVisibleObjects(camera, &(camVisObjIt->second),
mIlluminationStage == IRS_RENDER_TO_TEXTURE? true : false);
firePostFindVisibleObjects(vp);
mAutoParamDataSource->setMainCamBoundsInfo(&(camVisObjIt->second));
}
5. 프레임 업데이트
// Begin the frame
mDestRenderSystem->_beginFrame();
// Set rasterisation mode
mDestRenderSystem->_setPolygonMode(camera->getPolygonMode()); -- polygon
// Set initial camera state
mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrixRS());
// -- project matrix, D3D 。
// -- SetTransform( D3DTS_PROJECTION, &mDxProjMat )
mCachedViewMatrix = mCameraInProgress->getViewMatrix(true);
if (mCameraRelativeRendering)
{
mCachedViewMatrix.setTrans(Vector3::ZERO);
mCameraRelativePosition = mCameraInProgress->getDerivedPosition();
}
mDestRenderSystem->_setTextureProjectionRelativeTo(mCameraRelativeRendering, camera->getDerivedPosition());
setViewMatrix(mCachedViewMatrix);
// -- view matrix
// -- SetTransform( D3DTS_VIEW, &mDxViewMat )
// Render scene content
{
OgreProfileGroup("_renderVisibleObjects", OGREPROF_RENDERING);
_renderVisibleObjects(); -- PVS
}
// End frame
mDestRenderSystem->_endFrame();
만약 장면에 shadow가 필요하지 않으면, 경유하여 모든 노드를 렌더링합니다
void SceneManager::renderBasicQueueGroupObjects(RenderQueueGroup* pGroup,
QueuedRenderableCollection::OrganisationMode om)
{
// Basic render loop
// Iterate through priorities
RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
while (groupIt.hasMoreElements())
{
RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
// Sort the queue first -- geometry
pPriorityGrp->sort(mCameraInProgress);
// Do solids -- 、
renderObjects(pPriorityGrp->getSolidsBasic(), om, true, true);
// Do unsorted transparents -- ,
renderObjects(pPriorityGrp->getTransparentsUnsorted(), om, true, true);
// Do transparents (always descending) --
renderObjects(pPriorityGrp->getTransparents(),
QueuedRenderableCollection::OM_SORT_DESCENDING, true, true);
}// for each priority
}
단일 객체 렌더링:
void SceneManager::renderSingleObject(Renderable* rend, const Pass* pass,
bool lightScissoringClipping, bool doLightIteration,
const LightList* manualLightList)
{
unsigned short numMatrices;
RenderOperation ro;
// Set up rendering operation
// I know, I know, const_cast is nasty but otherwise it requires all internal
// state of the Renderable assigned to the rop to be mutable
const_cast<Renderable*>(rend)->getRenderOperation(ro);
ro.srcRenderable = rend;
GpuProgram* vprog = pass->hasVertexProgram() ? pass->getVertexProgram().get() : 0;
bool passTransformState = true;
if (vprog)
{
passTransformState = vprog->getPassTransformStates();
}
// Set world transformation
numMatrices = rend->getNumWorldTransforms();
if (numMatrices > 0)
{
rend->getWorldTransforms(mTempXform);
if (mCameraRelativeRendering && !rend->getUseIdentityView())
{
for (unsigned short i = 0; i < numMatrices; ++i)
{
mTempXform[i].setTrans(mTempXform[i].getTrans() - mCameraRelativePosition);
}
}
if (passTransformState)
{
// -- SetTransform( D3DTS_WORLD, &mDxWorldMat )
if (numMatrices > 1)
{
mDestRenderSystem->_setWorldMatrices(mTempXform, numMatrices);
}
else
{
mDestRenderSystem->_setWorldMatrix(*mTempXform);
}
}
}
// Issue view / projection changes if any
useRenderableViewProjMode(rend, passTransformState);
// mark per-object params as dirty
mGpuParamsDirty |= (uint16)GPV_PER_OBJECT;
if (!mSuppressRenderStateChanges)
{
bool passSurfaceAndLightParams = true;
if (pass->isProgrammable())
{
// Tell auto params object about the renderable change
mAutoParamDataSource->setCurrentRenderable(rend);
// Tell auto params object about the world matrices, eliminated query from renderable again
mAutoParamDataSource->setWorldMatrices(mTempXform, numMatrices);
if (vprog)
{
passSurfaceAndLightParams = vprog->getPassSurfaceAndLightStates();
}
}
// Reissue any texture gen settings which are dependent on view matrix
Pass::ConstTextureUnitStateIterator texIter = pass->getTextureUnitStateIterator();
size_t unit = 0;
while(texIter.hasMoreElements())
{
TextureUnitState* pTex = texIter.getNext();
if (pTex->hasViewRelativeTextureCoordinateGeneration())
{
mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
}
++unit;
}
// Sort out normalisation
// Assume first world matrix representative - shaders that use multiple
// matrices should control renormalisation themselves
if ((pass->getNormaliseNormals() || mNormaliseNormalsOnScale)
&& mTempXform[0].hasScale())
mDestRenderSystem->setNormaliseNormals(true);
else
mDestRenderSystem->setNormaliseNormals(false);
// Sort out negative scaling
// Assume first world matrix representative
if (mFlipCullingOnNegativeScale)
{
CullingMode cullMode = mPassCullingMode;
if (mTempXform[0].hasNegativeScale())
{
switch(mPassCullingMode)
{
case CULL_CLOCKWISE:
cullMode = CULL_ANTICLOCKWISE;
break;
case CULL_ANTICLOCKWISE:
cullMode = CULL_CLOCKWISE;
break;
case CULL_NONE:
break;
};
}
// this also copes with returning from negative scale in previous render op
// for same pass
if (cullMode != mDestRenderSystem->_getCullingMode())
mDestRenderSystem->_setCullingMode(cullMode);
}
// Set up the solid / wireframe override
// Precedence is Camera, Object, Material
// Camera might not override object if not overrideable
PolygonMode reqMode = pass->getPolygonMode();
if (pass->getPolygonModeOverrideable() && rend->getPolygonModeOverrideable())
{
PolygonMode camPolyMode = mCameraInProgress->getPolygonMode();
// check camera detial only when render detail is overridable
if (reqMode > camPolyMode)
{
// only downgrade detail; if cam says wireframe we don't go up to solid
reqMode = camPolyMode;
}
}
mDestRenderSystem->_setPolygonMode(reqMode);
if (doLightIteration)
{
// Create local light list for faster light iteration setup
static LightList localLightList;
// Here's where we issue the rendering operation to the render system
// Note that we may do this once per light, therefore it's in a loop
// and the light parameters are updated once per traversal through the
// loop
const LightList& rendLightList = rend->getLights();
bool iteratePerLight = pass->getIteratePerLight();
// deliberately unsigned in case start light exceeds number of lights
// in which case this pass would be skipped
int lightsLeft = 1;
if (iteratePerLight)
{
lightsLeft = static_cast<int>(rendLightList.size()) - pass->getStartLight();
// Don't allow total light count for all iterations to exceed max per pass
if (lightsLeft > static_cast<int>(pass->getMaxSimultaneousLights()))
{
lightsLeft = static_cast<int>(pass->getMaxSimultaneousLights());
}
}
const LightList* pLightListToUse;
// Start counting from the start light
size_t lightIndex = pass->getStartLight();
size_t depthInc = 0;
while (lightsLeft > 0)
{
// Determine light list to use
if (iteratePerLight)
{
// Starting shadow texture index.
size_t shadowTexIndex = mShadowTextures.size();
if (mShadowTextureIndexLightList.size() > lightIndex)
shadowTexIndex = mShadowTextureIndexLightList[lightIndex];
localLightList.resize(pass->getLightCountPerIteration());
LightList::iterator destit = localLightList.begin();
unsigned short numShadowTextureLights = 0;
for (; destit != localLightList.end()
&& lightIndex < rendLightList.size();
++lightIndex, --lightsLeft)
{
Light* currLight = rendLightList[lightIndex];
// Check whether we need to filter this one out
if (pass->getRunOnlyForOneLightType() &&
pass->getOnlyLightType() != currLight->getType())
{
// Skip
// Also skip shadow texture(s)
if (isShadowTechniqueTextureBased())
{
shadowTexIndex += mShadowTextureCountPerType[currLight->getType()];
}
continue;
}
*destit++ = currLight;
// potentially need to update content_type shadow texunit
// corresponding to this light
if (isShadowTechniqueTextureBased())
{
size_t textureCountPerLight = mShadowTextureCountPerType[currLight->getType()];
for (size_t j = 0; j < textureCountPerLight && shadowTexIndex < mShadowTextures.size(); ++j)
{
// link the numShadowTextureLights'th shadow texture unit
unsigned short tuindex =
pass->_getTextureUnitWithContentTypeIndex(
TextureUnitState::CONTENT_SHADOW, numShadowTextureLights);
if (tuindex > pass->getNumTextureUnitStates()) break;
// I know, nasty const_cast
TextureUnitState* tu =
const_cast<TextureUnitState*>(
pass->getTextureUnitState(tuindex));
const TexturePtr& shadowTex = mShadowTextures[shadowTexIndex];
tu->_setTexturePtr(shadowTex);
Camera *cam = shadowTex->getBuffer()->getRenderTarget()->getViewport(0)->getCamera();
tu->setProjectiveTexturing(!pass->hasVertexProgram(), cam);
mAutoParamDataSource->setTextureProjector(cam, numShadowTextureLights);
++numShadowTextureLights;
++shadowTexIndex;
// Have to set TU on rendersystem right now, although
// autoparams will be set later
mDestRenderSystem->_setTextureUnitSettings(tuindex, *tu);
}
}
}
// Did we run out of lights before slots? e.g. 5 lights, 2 per iteration
if (destit != localLightList.end())
{
localLightList.erase(destit, localLightList.end());
lightsLeft = 0;
}
pLightListToUse = &localLightList;
// deal with the case where we found no lights
// since this is light iteration, we shouldn't render at all
if (pLightListToUse->empty())
return;
}
else // !iterate per light
{
// Use complete light list potentially adjusted by start light
if (pass->getStartLight() || pass->getMaxSimultaneousLights() != OGRE_MAX_SIMULTANEOUS_LIGHTS)
{
// out of lights?
// skip manual 2nd lighting passes onwards if we run out of lights, but never the first one
if (pass->getStartLight() > 0 &&
pass->getStartLight() >= rendLightList.size())
{
lightsLeft = 0;
break;
}
else
{
localLightList.clear();
LightList::const_iterator copyStart = rendLightList.begin();
std::advance(copyStart, pass->getStartLight());
LightList::const_iterator copyEnd = copyStart;
// Clamp lights to copy to avoid overrunning the end of the list
size_t lightsToCopy = std::min(
static_cast<size_t>(pass->getMaxSimultaneousLights()),
rendLightList.size() - pass->getStartLight());
std::advance(copyEnd, lightsToCopy);
localLightList.insert(localLightList.begin(),
copyStart, copyEnd);
pLightListToUse = &localLightList;
}
}
else
{
pLightListToUse = &rendLightList;
}
lightsLeft = 0;
}
fireRenderSingleObject(rend, pass, mAutoParamDataSource, pLightListToUse, mSuppressRenderStateChanges);
// Do we need to update GPU program parameters?
if (pass->isProgrammable())
{
useLightsGpuProgram(pass, pLightListToUse);
}
// Do we need to update light states?
// Only do this if fixed-function vertex lighting applies
if (pass->getLightingEnabled() && passSurfaceAndLightParams)
{
useLights(*pLightListToUse, pass->getMaxSimultaneousLights());
}
// optional light scissoring & clipping
ClipResult scissored = CLIPPED_NONE;
ClipResult clipped = CLIPPED_NONE;
if (lightScissoringClipping &&
(pass->getLightScissoringEnabled() || pass->getLightClipPlanesEnabled()))
{
// if there's no lights hitting the scene, then we might as
// well stop since clipping cannot include anything
if (pLightListToUse->empty())
continue;
if (pass->getLightScissoringEnabled())
scissored = buildAndSetScissor(*pLightListToUse, mCameraInProgress);
if (pass->getLightClipPlanesEnabled())
clipped = buildAndSetLightClip(*pLightListToUse);
if (scissored == CLIPPED_ALL || clipped == CLIPPED_ALL)
continue;
}
// issue the render op
// nfz: check for gpu_multipass
mDestRenderSystem->setCurrentPassIterationCount(pass->getPassIterationCount());
// We might need to update the depth bias each iteration
if (pass->getIterationDepthBias() != 0.0f)
{
float depthBiasBase = pass->getDepthBiasConstant() +
pass->getIterationDepthBias() * depthInc;
// depthInc deals with light iteration
// Note that we have to set the depth bias here even if the depthInc
// is zero (in which case you would think there is no change from
// what was set in _setPass(). The reason is that if there are
// multiple Renderables with this Pass, we won't go through _setPass
// again at the start of the iteration for the next Renderable
// because of Pass state grouping. So set it always
// Set modified depth bias right away
mDestRenderSystem->_setDepthBias(depthBiasBase, pass->getDepthBiasSlopeScale());
// Set to increment internally too if rendersystem iterates
mDestRenderSystem->setDeriveDepthBias(true,
depthBiasBase, pass->getIterationDepthBias(),
pass->getDepthBiasSlopeScale());
}
else
{
mDestRenderSystem->setDeriveDepthBias(false);
}
depthInc += pass->getPassIterationCount();
// Finalise GPU parameter bindings
updateGpuProgramParameters(pass);
if (rend->preRender(this, mDestRenderSystem))
mDestRenderSystem->_render(ro);
rend->postRender(this, mDestRenderSystem);
if (scissored == CLIPPED_SOME)
resetScissor();
if (clipped == CLIPPED_SOME)
resetLightClip();
} // possibly iterate per light
}
else // no automatic light processing
{
// Even if manually driving lights, check light type passes
bool skipBecauseOfLightType = false;
if (pass->getRunOnlyForOneLightType())
{
if (!manualLightList ||
(manualLightList->size() == 1 &&
manualLightList->at(0)->getType() != pass->getOnlyLightType()))
{
skipBecauseOfLightType = true;
}
}
if (!skipBecauseOfLightType)
{
fireRenderSingleObject(rend, pass, mAutoParamDataSource, manualLightList, mSuppressRenderStateChanges);
// Do we need to update GPU program parameters?
if (pass->isProgrammable())
{
// Do we have a manual light list?
if (manualLightList)
{
useLightsGpuProgram(pass, manualLightList);
}
}
// Use manual lights if present, and not using vertex programs that don't use fixed pipeline
if (manualLightList &&
pass->getLightingEnabled() && passSurfaceAndLightParams)
{
useLights(*manualLightList, pass->getMaxSimultaneousLights());
}
// optional light scissoring
ClipResult scissored = CLIPPED_NONE;
ClipResult clipped = CLIPPED_NONE;
if (lightScissoringClipping && manualLightList && pass->getLightScissoringEnabled())
{
scissored = buildAndSetScissor(*manualLightList, mCameraInProgress);
}
if (lightScissoringClipping && manualLightList && pass->getLightClipPlanesEnabled())
{
clipped = buildAndSetLightClip(*manualLightList);
}
// don't bother rendering if clipped / scissored entirely
if (scissored != CLIPPED_ALL && clipped != CLIPPED_ALL)
{
// issue the render op
// nfz: set up multipass rendering
mDestRenderSystem->setCurrentPassIterationCount(pass->getPassIterationCount());
// Finalise GPU parameter bindings
updateGpuProgramParameters(pass);
if (rend->preRender(this, mDestRenderSystem))
mDestRenderSystem->_render(ro);
rend->postRender(this, mDestRenderSystem);
}
if (scissored == CLIPPED_SOME)
resetScissor();
if (clipped == CLIPPED_SOME)
resetLightClip();
} // !skipBecauseOfLightType
}
}
else // mSuppressRenderStateChanges
{
fireRenderSingleObject(rend, pass, mAutoParamDataSource, NULL, mSuppressRenderStateChanges);
// Just render
mDestRenderSystem->setCurrentPassIterationCount(1);
if (rend->preRender(this, mDestRenderSystem))
mDestRenderSystem->_render(ro);
rend->postRender(this, mDestRenderSystem);
}
// Reset view / projection changes if any
resetViewProjMode(passTransformState);
}
위의 단일 물체에 대해 중점 단계는 다음과 같다.
1. 월드 matrix 설정
2. culling mode 설정
3. polygon mode 설정
4, light 설정 -- SetLight(), EnableLight()
5. DrawPrimitive 등으로 도면 그리기
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
localStorage에 객체를 추가하는 방법은 무엇입니까?이 노트에서는 localStorage에 객체를 삽입하는 방법을 보여드리겠습니다. 경우에 따라 로컬 스토리지 또는 세션 스토리지에 데이터를 개체로 저장해야 할 수 있습니다. 어떻게 이것을 달성할 수 있습니까? 객체가 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.