Skip to content

Commit

Permalink
HydraX: fixed crash when going underwater (bad compositor cleanup)
Browse files Browse the repository at this point in the history
Fixes the following scenario:
1. start game and select HydraX in settings
2. load terrain with water, like Auriga Proving Grounds
3. In top menubar/settings, change water type to HydraX to trigger reloading water.
4. put camera under water -> crash due to compositor not existing. Cause: creating it failed because the previous one wasnt cleaned up properly.

The fix is in file 'MaterialManager.cpp', func `void MaterialManager::_destroyUnderwaterCompositor()` - the rest is a cleanup of HydraX compositor handling code.
  • Loading branch information
ohlidalp committed Sep 18, 2024
1 parent f42b3fa commit 32f0e91
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 93 deletions.
24 changes: 5 additions & 19 deletions source/main/gfx/hydrax/Hydrax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ namespace Hydrax

mMesh->remove();
mDecalsManager->removeAll();
mMaterialManager->removeMaterials();
mMaterialManager->removeMaterialsAndCompositor();
mRttManager->removeAll();
mGodRaysManager->remove();
mModule->remove();
Expand Down Expand Up @@ -217,7 +217,7 @@ namespace Hydrax
mMesh->getSceneNode()->setVisible(false);

// Stop compositor (MaterialManager::setCompositorEnable(...) checks if underwater compositor exists)
mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false);
mMaterialManager->setUnderwaterCompositorEnabled(false);
}
else
{
Expand Down Expand Up @@ -519,7 +519,7 @@ namespace Hydrax

if (mCurrentFrameUnderwater)
{
mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true);
mMaterialManager->setUnderwaterCompositorEnabled(true);
}
}

Expand Down Expand Up @@ -671,7 +671,7 @@ namespace Hydrax

mMaterialManager->reload(MaterialManager::MAT_UNDERWATER);

mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true);
mMaterialManager->setUnderwaterCompositorEnabled(true);

mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_UNDERWATER)->getName());
}
Expand Down Expand Up @@ -708,7 +708,7 @@ namespace Hydrax
mRttManager->remove(RttManager::RTT_DEPTH_REFLECTION);
}

mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false);
mMaterialManager->setUnderwaterCompositorEnabled(false);

mMesh->setMaterialName(mMaterialManager->getMaterial(MaterialManager::MAT_WATER)->getName());
}
Expand Down Expand Up @@ -848,20 +848,6 @@ namespace Hydrax
mMaterialManager->setGpuProgramParameter(
MaterialManager::GPUP_FRAGMENT, MaterialManager::MAT_UNDERWATER,
"uWaterColor", WaterColor);

//mMaterialManager->getCompositor(MaterialManager::COMP_UNDERWATER)->
// getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(WC);

/* Active creation/destruction
if (getHeigth(mCamera->getDerivedPosition()) > mCamera->getDerivedPosition().y-1.25f)
{
if (mMaterialManager->isCompositorEnable(MaterialManager::COMP_UNDERWATER))
{
mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, false);
mMaterialManager->setCompositorEnable(MaterialManager::COMP_UNDERWATER, true);
}
}
*/
}
}

Expand Down
53 changes: 24 additions & 29 deletions source/main/gfx/hydrax/MaterialManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,15 @@ namespace Hydrax
mMaterials[k].setNull();
}

for (int k = 0; k < 1; k++)
{
mCompositorsEnable[k] = false;
mCompositorsNeedToBeReloaded[k] = false;
}

mUnderwaterCompositorListener.mMaterialManager = this;
}

MaterialManager::~MaterialManager()
{
removeMaterials();
removeMaterialsAndCompositor();
}

void MaterialManager::removeMaterials()
void MaterialManager::removeMaterialsAndCompositor()
{
if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Water_Material_Name))
{
Expand Down Expand Up @@ -139,16 +133,24 @@ namespace Hydrax
}
}

removeCompositor();
_destroyUnderwaterCompositor();

mCreated = false;
}

void MaterialManager::removeCompositor()
void MaterialManager::_destroyUnderwaterCompositor()
{
if (Ogre::MaterialManager::getSingleton().resourceExists(_def_Underwater_Compositor_Material_Name))
{
setCompositorEnable(COMP_UNDERWATER, false);
setUnderwaterCompositorEnabled(false);

if (!mUnderwaterCompositor.isNull())
{
Ogre::CompositorManager::getSingleton().removeCompositor(
mHydrax->getViewport(), mUnderwaterCompositor->getName());
mUnderwaterCompositor.setNull();
}

Ogre::CompositorManager::getSingleton().remove(_def_Underwater_Compositor_Name);

Ogre::MaterialManager::getSingleton().remove(_def_Underwater_Compositor_Material_Name);
Expand All @@ -162,7 +164,7 @@ namespace Hydrax

bool MaterialManager::createMaterials(const HydraxComponent &Components, const Options &Options)
{
removeMaterials();
removeMaterialsAndCompositor();

HydraxLOG("Creating water material...");
if (!_createWaterMaterial(Components, Options))
Expand Down Expand Up @@ -3074,11 +3076,9 @@ namespace Hydrax
UnderwaterCompositorMaterial->setReceiveShadows(false);
UnderwaterCompositorMaterial->load();

Ogre::CompositorPtr &UnderwaterCompositor = getCompositor(COMP_UNDERWATER);
UnderwaterCompositor = Ogre::CompositorManager::getSingleton().
mUnderwaterCompositor = Ogre::CompositorManager::getSingleton().
create(_def_Underwater_Compositor_Name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

Ogre::CompositionTechnique* UnderWaterComp_Technique = UnderwaterCompositor->createTechnique();
Ogre::CompositionTechnique* UnderWaterComp_Technique = mUnderwaterCompositor->createTechnique();

// Create the texture definition to render the original scene
Ogre::CompositionTechnique::TextureDefinition* TDef = UnderWaterComp_Technique->createTextureDefinition("OriginalScene");
Expand Down Expand Up @@ -3353,7 +3353,7 @@ namespace Hydrax

case MAT_UNDERWATER_COMPOSITOR:
{
mCompositorsNeedToBeReloaded[COMP_UNDERWATER] = true;
mUnderwaterCompositorNeedsReloading = true;
}
break;

Expand Down Expand Up @@ -3509,19 +3509,15 @@ namespace Hydrax
}
}

void MaterialManager::setCompositorEnable(const CompositorType &Compositor, const bool &Enable)
void MaterialManager::setUnderwaterCompositorEnabled(bool Enable)
{
Ogre::CompositorPtr &Comp = mCompositors[static_cast<int>(Compositor)];

if (Comp.isNull())
if (mUnderwaterCompositor.isNull())
{
return;
}

Ogre::CompositorManager::getSingleton().
setCompositorEnabled(mHydrax->getViewport(), Comp->getName(), Enable);

mCompositorsEnable[static_cast<int>(Compositor)] = Enable;
Ogre::CompositorManager::getSingleton().setCompositorEnabled(
mHydrax->getViewport(), mUnderwaterCompositor->getName(), Enable);
}

bool MaterialManager::_isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const
Expand Down Expand Up @@ -3730,8 +3726,7 @@ namespace Hydrax
void MaterialManager::UnderwaterCompositorListener::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr &mat)
{
const Ogre::Vector3& WC = mMaterialManager->mHydrax->getWaterColor();
Ogre::CompositorPtr &UnderwaterCompositor = mMaterialManager->getCompositor(COMP_UNDERWATER);
UnderwaterCompositor->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(Ogre::ColourValue(WC.x, WC.y, WC.z));
mMaterialManager->getUnderwaterCompositor()->getTechnique(0)->getTargetPass(0)->getPass(0)->setClearColour(Ogre::ColourValue(WC.x, WC.y, WC.z));

Ogre::GpuProgramParametersSharedPtr FP_Parameters = mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters();

Expand Down Expand Up @@ -3780,15 +3775,15 @@ namespace Hydrax
}
*/

if (mMaterialManager->mCompositorsNeedToBeReloaded[COMP_UNDERWATER])
if (mMaterialManager->mUnderwaterCompositorNeedsReloading)
{
if (mMaterialManager->_isComponent(mMaterialManager->mComponents, HYDRAX_COMPONENT_DEPTH))
{
Ogre::Pass* DM_Technique0_Pass0 = mat->getTechnique(0)->getPass(0);
DM_Technique0_Pass0->getTextureUnitState(2)->setTextureName("HydraxDepthMap");
}

mMaterialManager->mCompositorsNeedToBeReloaded[COMP_UNDERWATER] = false;
mMaterialManager->mUnderwaterCompositorNeedsReloading = false;
}
}
}
59 changes: 14 additions & 45 deletions source/main/gfx/hydrax/MaterialManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,6 @@ namespace Hydrax
MAT_SIMPLE_BLACK = 5
};

/** Compositor type enum
@remarks Use in getCompositor(CompositorType)
*/
enum CompositorType
{
// Underwater compositor
COMP_UNDERWATER = 0
};

/** Gpu program enum
@remarks Use in setGpuProgramParameter()
*/
Expand Down Expand Up @@ -166,14 +157,7 @@ namespace Hydrax
*/
bool createMaterials(const HydraxComponent &Components, const Options &Options);

/** Remove materials
@remarks removeCompositor() is called too.
*/
void removeMaterials();

/** Remove compositor
*/
void removeCompositor();
void removeMaterialsAndCompositor();

/** Reload material
@param Material Material to reload
Expand Down Expand Up @@ -223,29 +207,12 @@ namespace Hydrax
return mMaterials[static_cast<int>(Material)];
}

/** Get compositor
@param Compositor to get
@return Compositor to get
*/
inline Ogre::CompositorPtr &getCompositor(const CompositorType &Compositor)
{
return mCompositors[static_cast<int>(Compositor)];
}

/** Is the compositor enable?
@param Compositor compositor to check
@return true if it's enabled
*/
inline const bool& isCompositorEnable(const CompositorType &Compositor) const
inline Ogre::CompositorPtr &getUnderwaterCompositor()
{
return mCompositorsEnable[static_cast<int>(Compositor)];
return mUnderwaterCompositor;
}

/** Set a compositor enable/disable
@param Compositor compositor to change
@param Enable true to enable, false to disable
*/
void setCompositorEnable(const CompositorType &Compositor, const bool &Enable);
void setUnderwaterCompositorEnabled(bool Enable);

/** Get the last MaterialManager::Options used in a material generation
@return Last MaterialManager::Options used in a material generation
Expand Down Expand Up @@ -355,28 +322,30 @@ namespace Hydrax
*/
bool _createUnderwaterCompositor(const HydraxComponent &Components, const Options &Options);

void _destroyUnderwaterCompositor();

bool _createSimpleColorMaterial(const Ogre::ColourValue& MaterialColor, const MaterialType& MT, const Ogre::String& MaterialName, const bool& DepthCheck = true, const bool& DepthWrite = true);

/// Is createMaterials() already called?
bool mCreated;
/// Hydrax materials vector
Ogre::MaterialPtr mMaterials[6];
/// Hydrax compositors vector
Ogre::CompositorPtr mCompositors[1];
/// Hydrax compositors boolean: Need to be reloaded?
bool mCompositorsNeedToBeReloaded[1];
/// Hydrax compostor enable vector
bool mCompositorsEnable[1];
/// Technique vector for addDepthTechnique(...)
std::vector<Ogre::Technique*> mDepthTechniques;
/// Actual material components
HydraxComponent mComponents;
/// Actual material options
Options mOptions;
/// Underwater compositor listener
UnderwaterCompositorListener mUnderwaterCompositorListener;

/// Hydrax main pointer
Hydrax *mHydrax;

/// @name Underwater compositor
/// @{
Ogre::CompositorPtr mUnderwaterCompositor;
UnderwaterCompositorListener mUnderwaterCompositorListener;
bool mUnderwaterCompositorNeedsReloading = false;
/// @}
};
};

Expand Down
2 changes: 2 additions & 0 deletions source/main/gfx/hydrax/RttManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ namespace Hydrax

RttManager::~RttManager()
{
//mHydrax->getSceneManager()->removeRenderQueueListener(&mReflectionListener.mCReflectionQueueListener);

removeAll();
}

Expand Down

0 comments on commit 32f0e91

Please sign in to comment.