00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "CaelumPrecompiled.h"
00022 #include "CaelumExceptions.h"
00023 #include "DepthComposer.h"
00024
00025 using namespace Ogre;
00026
00027 namespace Caelum
00028 {
00029 DepthComposer::DepthComposer
00030 (
00031 Ogre::SceneManager *sceneMgr
00032 ):
00033 mSceneMgr (sceneMgr),
00034 mDebugDepthRender (false),
00035 mSkyDomeHazeEnabled (false),
00036 mGroundFogEnabled (false),
00037 mGroundFogDensity (0.1),
00038 mGroundFogBaseLevel (5),
00039 mGroundFogVerticalDecay (0.2),
00040 mGroundFogColour (ColourValue::Black)
00041 {
00042 }
00043
00044 DepthComposer::~DepthComposer()
00045 {
00046 destroyAllViewportInstances();
00047 }
00048
00049 void DepthComposer::setDebugDepthRender (bool value)
00050 {
00051 if (mDebugDepthRender == value) {
00052 return;
00053 }
00054 mDebugDepthRender = value;
00055 onCompositorMaterialChanged ();
00056 }
00057
00058 void DepthComposer::setSkyDomeHazeEnabled (bool value)
00059 {
00060 if (mSkyDomeHazeEnabled == value) {
00061 return;
00062 }
00063 mSkyDomeHazeEnabled = value;
00064 onCompositorMaterialChanged ();
00065 }
00066
00067 void DepthComposer::setGroundFogEnabled (bool value)
00068 {
00069 if (mGroundFogEnabled == value) {
00070 return;
00071 }
00072 mGroundFogEnabled = value;
00073 onCompositorMaterialChanged ();
00074 }
00075
00076 const String& DepthComposer::getCompositorName ()
00077 {
00078
00079 static const Ogre::String CompositorName_DebugDepthRender =
00080 "Caelum/DepthComposer_DebugDepthRender";
00081 static const Ogre::String CompositorName_Dummy =
00082 "Caelum/DepthComposer_Dummy";
00083 static const Ogre::String CompositorName_ExpGroundFog =
00084 "Caelum/DepthComposer_ExpGroundFog";
00085 static const Ogre::String CompositorName_SkyDomeHaze =
00086 "Caelum/DepthComposer_SkyDomeHaze";
00087 static const Ogre::String CompositorName_SkyDomeHaze_ExpGroundFog =
00088 "Caelum/DepthComposer_SkyDomeHaze_ExpGroundFog";
00089
00090
00091 if (mDebugDepthRender) {
00092 return CompositorName_DebugDepthRender;
00093 } else if (mSkyDomeHazeEnabled == false && mGroundFogEnabled == false) {
00094 return CompositorName_Dummy;
00095 } else if (mSkyDomeHazeEnabled == false && mGroundFogEnabled == true) {
00096 return CompositorName_ExpGroundFog;
00097 } else if (mSkyDomeHazeEnabled == true && mGroundFogEnabled == false) {
00098 return CompositorName_SkyDomeHaze;
00099 } else if (mSkyDomeHazeEnabled == true && mGroundFogEnabled == true) {
00100 return CompositorName_SkyDomeHaze_ExpGroundFog;
00101 } else {
00102 assert (0);
00103 return CompositorName_Dummy;
00104 }
00105 }
00106
00107 void DepthComposer::onCompositorMaterialChanged ()
00108 {
00109 ViewportInstanceMap::const_iterator it;
00110 ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin();
00111 ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end();
00112 for (it = begin; it != end; ++it) {
00113 it->second->removeCompositor ();
00114 it->second->addCompositor ();
00115 }
00116 }
00117
00118 void DepthComposer::update ()
00119 {
00120 ViewportInstanceMap::const_iterator it;
00121 ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin();
00122 ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end();
00123 for (it = begin; it != end; ++it) {
00124 assert(it->first == it->second->getViewport());
00125 it->second->_update ();
00126 }
00127 }
00128
00129 DepthComposerInstance::DepthComposerInstance
00130 (
00131 DepthComposer* parent,
00132 Ogre::Viewport* viewport
00133 ):
00134 mParent(parent),
00135 mViewport(viewport),
00136 mCompInst(0)
00137 {
00138 LogManager::getSingleton().logMessage (
00139 "Caelum::DepthComposer: Attaching screen-space fog instance"
00140 " to viewport \'" + StringConverter::toString ((long)getViewport ()) + "\'"
00141 " of render target \'" + getViewport()->getTarget ()->getName () + "\'");
00142
00143 addCompositor ();
00144 mDepthRenderer.reset (new DepthRenderer (getViewport ()));
00145 }
00146
00147 DepthComposerInstance::~DepthComposerInstance()
00148 {
00149 removeCompositor ();
00150 mDepthRenderer.reset ();
00151
00152 LogManager::getSingleton().logMessage (
00153 "Caelum::DepthComposer: Detached screen-space fog instance"
00154 " from viewport \'" + StringConverter::toString ((long)getViewport ()) + "\'"
00155 " of render target \'" + getViewport()->getTarget ()->getName () + "\'");
00156 }
00157
00158 void DepthComposerInstance::addCompositor ()
00159 {
00160 CompositorManager* compMgr = CompositorManager::getSingletonPtr();
00161
00162 const String& compositorName = getParent ()->getCompositorName ();
00163 mCompInst = compMgr->addCompositor(mViewport, compositorName);
00164 if (!mCompInst) {
00165 CAELUM_THROW_UNSUPPORTED_EXCEPTION (
00166 "Can't add \'" + compositorName + "\' compositor.",
00167 "DepthComposer");
00168 }
00169 assert(mCompInst);
00170 mCompInst->setEnabled (true);
00171 mCompInst->addListener (this);
00172 }
00173
00174 void DepthComposerInstance::removeCompositor ()
00175 {
00176 CompositorManager* compMgr = CompositorManager::getSingletonPtr();
00177 compMgr->removeCompositor (mViewport, mCompInst->getCompositor ()->getName ());
00178 mCompInst = 0;
00179 }
00180
00181 void DepthComposerInstance::notifyMaterialSetup(uint pass_id, Ogre::MaterialPtr &mat)
00182 {
00183
00184
00185
00186 Pass* pass = mat->getBestTechnique ()->getPass (0);
00187 GpuProgramParametersSharedPtr fpParams = pass->getFragmentProgramParameters ();
00188
00189 fpParams->setIgnoreMissingParams(true);
00190
00191 TextureUnitState *depthTus = pass->getTextureUnitState(1);
00192 if (depthTus->getTextureName () != mDepthRenderer->getDepthRenderTexture ()->getName()) {
00193 depthTus->setTextureName (mDepthRenderer->getDepthRenderTexture ()->getName ());
00194 LogManager::getSingleton ().logMessage (
00195 "Caelum::DepthComposer: Assigned depth texture in compositor material");
00196 }
00197 }
00198
00199 void DepthComposerInstance::notifyMaterialRender(uint pass_id, Ogre::MaterialPtr &mat)
00200 {
00201 Pass* pass = mat->getBestTechnique ()->getPass (0);
00202 GpuProgramParametersSharedPtr fpParams = pass->getFragmentProgramParameters ();
00203 Camera* camera = getViewport ()->getCamera ();
00204
00205
00206
00207
00208 Matrix4 projMatrix = camera->getProjectionMatrixWithRSDepth();
00209 Matrix4 viewMatrix = camera->getViewMatrix();
00210 fpParams->setNamedConstant("invViewProjMatrix", (projMatrix * viewMatrix).inverse());
00211
00212 fpParams->setNamedConstant("worldCameraPos", camera->getDerivedPosition ());
00213
00214 fpParams->setNamedConstant("groundFogDensity", getParent ()->getGroundFogDensity ());
00215 fpParams->setNamedConstant("groundFogVerticalDecay", getParent ()->getGroundFogVerticalDecay ());
00216 fpParams->setNamedConstant("groundFogBaseLevel", getParent ()->getGroundFogBaseLevel ());
00217 fpParams->setNamedConstant("groundFogColour", getParent ()->getGroundFogColour ());
00218
00219 fpParams->setNamedConstant("sunDirection", getParent ()->getSunDirection ());
00220 fpParams->setNamedConstant("hazeColour", getParent ()->getHazeColour ());
00221
00222 }
00223
00224 void DepthComposerInstance::_update ()
00225 {
00226 mDepthRenderer->update ();
00227 }
00228
00229 DepthComposerInstance* DepthComposer::createViewportInstance(Ogre::Viewport* vp)
00230 {
00231 ViewportInstanceMap::const_iterator it = mViewportInstanceMap.find(vp);
00232 if (it == mViewportInstanceMap.end()) {
00233 std::auto_ptr<DepthComposerInstance> inst(new DepthComposerInstance(this, vp));
00234 mViewportInstanceMap.insert(std::make_pair(vp, inst.get()));
00235
00236 return inst.release();
00237 } else {
00238 return it->second;
00239 }
00240 }
00241
00242 DepthComposerInstance* DepthComposer::getViewportInstance(Ogre::Viewport* vp) {
00243 ViewportInstanceMap::iterator it = mViewportInstanceMap.find(vp);
00244 if (it != mViewportInstanceMap.end()) {
00245 return it->second;
00246 } else {
00247 return 0;
00248 }
00249 }
00250
00251 void DepthComposer::destroyViewportInstance(Viewport* vp)
00252 {
00253 ViewportInstanceMap::iterator it = mViewportInstanceMap.find(vp);
00254 if (it != mViewportInstanceMap.end()) {
00255 DepthComposerInstance* inst = it->second;
00256 delete inst;
00257 mViewportInstanceMap.erase(it);
00258 }
00259 }
00260
00261 void DepthComposer::destroyAllViewportInstances() {
00262 ViewportInstanceMap::const_iterator it;
00263 ViewportInstanceMap::const_iterator begin = mViewportInstanceMap.begin();
00264 ViewportInstanceMap::const_iterator end = mViewportInstanceMap.end();
00265 for (it = begin; it != end; ++it) {
00266 assert(it->first == it->second->getViewport());
00267 delete it->second;
00268 }
00269 mViewportInstanceMap.clear();
00270 }
00271
00272 const String DepthRenderer::DEFAULT_CUSTOM_DEPTH_SCHEME_NAME = "CaelumDepth";
00273
00274 DepthRenderer::DepthRenderer
00275 (
00276 Viewport* masterViewport
00277 ):
00278 mMasterViewport (masterViewport),
00279 mDepthRenderViewport (0),
00280 mDepthRenderingNow (false),
00281 mViewportVisibilityMask (~0),
00282 mUseCustomDepthScheme (true),
00283 mCustomDepthSchemeName (DEFAULT_CUSTOM_DEPTH_SCHEME_NAME)
00284 {
00285 disableRenderGroupRangeFilter ();
00286
00287 Ogre::String uniqueId = Ogre::StringConverter::toString ((size_t)this);
00288
00289
00290 mDepthRenderMaterial = MaterialManager::getSingleton ().getByName ("Caelum/DepthRender");
00291 mDepthRenderMaterial->load();
00292 if (!mDepthRenderMaterial->getBestTechnique ()) {
00293 CAELUM_THROW_UNSUPPORTED_EXCEPTION (
00294 "Can't load depth render material: " +
00295 mDepthRenderMaterial->getUnsupportedTechniquesExplanation(),
00296 "DepthComposer");
00297 }
00298
00299 TextureManager* texMgr = TextureManager::getSingletonPtr();
00300
00301 int width = getMasterViewport ()->getActualWidth ();
00302 int height = getMasterViewport ()->getActualHeight ();
00303 LogManager::getSingleton ().logMessage (
00304 "Caelum::DepthRenderer: Creating depth render texture size " +
00305 StringConverter::toString (width) +
00306 "x" +
00307 StringConverter::toString (height));
00308
00309 PixelFormat desiredFormat = PF_FLOAT32_R;
00310 PixelFormat requestFormat = desiredFormat;
00311 if (texMgr->isFormatSupported (TEX_TYPE_2D, desiredFormat, TU_RENDERTARGET)) {
00312 LogManager::getSingleton ().logMessage (
00313 "Caelum::DepthRenderer: RenderSystem has native support for " +
00314 PixelUtil::getFormatName (desiredFormat));
00315 } else if (texMgr->isEquivalentFormatSupported (TEX_TYPE_2D, desiredFormat, TU_RENDERTARGET)) {
00316 PixelFormat equivFormat = texMgr->getNativeFormat (TEX_TYPE_2D, desiredFormat, TU_RENDERTARGET);
00317 LogManager::getSingleton ().logMessage (
00318 "Caelum::DepthRenderer: RenderSystem supports " +
00319 PixelUtil::getFormatName (equivFormat) +
00320 " instead of " +
00321 PixelUtil::getFormatName (desiredFormat));
00322 requestFormat = equivFormat;
00323 } else {
00324 CAELUM_THROW_UNSUPPORTED_EXCEPTION (
00325 PixelUtil::getFormatName(desiredFormat) + " or equivalent not supported",
00326 "DepthRenderer");
00327 }
00328
00329 if (texMgr->isHardwareFilteringSupported (TEX_TYPE_2D, requestFormat, TU_RENDERTARGET)) {
00330 LogManager::getSingleton ().logMessage (
00331 "Caelum::DepthRenderer: RenderSystem supports hardware filtering for " +
00332 PixelUtil::getFormatName (requestFormat));
00333 } else {
00334 LogManager::getSingleton ().logMessage (
00335 "Caelum::DepthRenderer: RenderSystem does not support hardware filtering for " +
00336 PixelUtil::getFormatName (requestFormat));
00337 }
00338
00339
00340
00341 mDepthRenderTexture = texMgr->createManual(
00342 "Caelum/DepthComposer/" + uniqueId + "/DepthTexture",
00343 Caelum::RESOURCE_GROUP_NAME,
00344 TEX_TYPE_2D,
00345 width, height, 1,
00346 0,
00347 requestFormat,
00348 TU_RENDERTARGET,
00349 0);
00350
00351 assert(getDepthRenderTarget());
00352
00353
00354 LogManager::getSingleton().logMessage (
00355 "Caelum::DepthRenderer: Created depth render texture"
00356 " actual format " + PixelUtil::getFormatName (getDepthRenderTexture()->getFormat ()) +
00357 " desired format " + PixelUtil::getFormatName (getDepthRenderTexture()->getDesiredFormat ()));
00358
00359
00360 getDepthRenderTarget()->setAutoUpdated (false);
00361
00362
00363 mDepthRenderViewport = getDepthRenderTarget()->addViewport(0);
00364 getDepthRenderViewport ()->setShadowsEnabled (false);
00365 getDepthRenderViewport ()->setOverlaysEnabled (false);
00366 getDepthRenderViewport ()->setClearEveryFrame (true);
00367
00368
00369
00370 getDepthRenderViewport ()->setBackgroundColour (Ogre::ColourValue (1, 1, 1, 1));
00371 }
00372
00373 DepthRenderer::~DepthRenderer()
00374 {
00375 TextureManager* texMgr = TextureManager::getSingletonPtr();
00376
00377
00378 if (!mDepthRenderTexture.isNull ()) {
00379 texMgr->remove (mDepthRenderTexture->getHandle ());
00380 mDepthRenderTexture.setNull ();
00381 }
00382 }
00383
00384 void DepthRenderer::update ()
00385 {
00386 Camera* camera = getMasterViewport ()->getCamera ();
00387 Viewport* oldCameraViewport = camera->getViewport ();
00388 SceneManager *sceneManager = camera->getSceneManager ();
00389
00390 assert (oldCameraViewport == getMasterViewport ());
00391 assert (getDepthRenderViewport ()->getActualWidth () == getMasterViewport()->getActualWidth ());
00392 assert (getDepthRenderViewport ()->getActualHeight () == getMasterViewport()->getActualHeight ());
00393
00394 getDepthRenderViewport ()->setVisibilityMask (mViewportVisibilityMask);
00395 getDepthRenderViewport ()->setCamera (camera);
00396 if (this->getUseCustomDepthScheme ()) {
00397 getDepthRenderViewport ()->setMaterialScheme (this->getCustomDepthSchemeName ());
00398 }
00399
00400
00401
00402 RenderQueue::RenderableListener* oldListener = sceneManager->getRenderQueue ()->getRenderableListener();
00403 if (oldListener) {
00404
00405
00406 }
00407 sceneManager->getRenderQueue ()->setRenderableListener (this);
00408
00409 mDepthRenderingNow = true;
00410
00411 getDepthRenderTarget ()->update ();
00412
00413 mDepthRenderingNow = false;
00414
00415 sceneManager->getRenderQueue ()->setRenderableListener (oldListener);
00416 oldListener = 0;
00417
00418
00419 camera->_notifyViewport (oldCameraViewport);
00420 }
00421
00422 #if OGRE_VERSION < 0x00010600
00423 bool DepthRenderer::renderableQueued(
00424 Ogre::Renderable* rend,
00425 Ogre::uint8 groupId,
00426 Ogre::ushort priority,
00427 Ogre::Technique** ppTech)
00428 #else
00429 bool DepthRenderer::renderableQueued(
00430 Ogre::Renderable* rend,
00431 Ogre::uint8 groupId,
00432 Ogre::ushort priority,
00433 Ogre::Technique** ppTech,
00434 Ogre::RenderQueue* pQueue)
00435 #endif // OGRE_VERSION
00436 {
00437 assert (mDepthRenderingNow);
00438
00439
00440
00441
00442
00443
00444
00445 if (groupId < mMinRenderGroupId || groupId > mMaxRenderGroupId) {
00446 return false;
00447 }
00448
00449 if (this->getUseCustomDepthScheme () && (*ppTech)->getSchemeName () == this->getCustomDepthSchemeName ()) {
00450
00451
00452
00453
00454
00455
00456
00457 return true;
00458 }
00459
00460
00461 Material* depthMaterial = getDepthRenderMaterial ();
00462 Technique* tech = depthMaterial->getBestTechnique ();
00463
00464
00465 *ppTech = tech;
00466 return true;
00467 }
00468
00469 void DepthRenderer::setRenderGroupRangeFilter (int minGroup, int maxGroup)
00470 {
00471 mMinRenderGroupId = minGroup;
00472 mMaxRenderGroupId = maxGroup;
00473 }
00474
00475 void DepthRenderer::disableRenderGroupRangeFilter()
00476 {
00477 setRenderGroupRangeFilter(Ogre::RENDER_QUEUE_BACKGROUND, Ogre::RENDER_QUEUE_MAX);
00478 }
00479 }