forked from mirror/openmw-tes3mp
Crash fix, material fix
This commit is contained in:
parent
13afcc9324
commit
8c8653160d
11 changed files with 123 additions and 25 deletions
|
@ -244,16 +244,6 @@ void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
|
||||||
mObjects.buildStaticGeometry (*store);
|
mObjects.buildStaticGeometry (*store);
|
||||||
sh::Factory::getInstance().unloadUnreferencedMaterials();
|
sh::Factory::getInstance().unloadUnreferencedMaterials();
|
||||||
mDebugging->cellAdded(store);
|
mDebugging->cellAdded(store);
|
||||||
if (store->isExterior())
|
|
||||||
{
|
|
||||||
if (!mTerrain)
|
|
||||||
{
|
|
||||||
mTerrain = new Terrain::Terrain(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
|
||||||
Settings::Manager::getBool("distant land", "Terrain"),
|
|
||||||
Settings::Manager::getBool("shader", "Terrain"));
|
|
||||||
mTerrain->update(mRendering.getCamera()->getRealPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
waterAdded(store);
|
waterAdded(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,7 +838,12 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
|
||||||
mWater->processChangedSettings(settings);
|
mWater->processChangedSettings(settings);
|
||||||
|
|
||||||
if (rebuild)
|
if (rebuild)
|
||||||
|
{
|
||||||
mObjects.rebuildStaticGeometry();
|
mObjects.rebuildStaticGeometry();
|
||||||
|
if (mTerrain)
|
||||||
|
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
|
||||||
|
Settings::Manager::getBool("split", "Shadows"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::setMenuTransparency(float val)
|
void RenderingManager::setMenuTransparency(float val)
|
||||||
|
@ -994,7 +989,7 @@ void RenderingManager::updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, con
|
||||||
|
|
||||||
void RenderingManager::frameStarted(float dt, bool paused)
|
void RenderingManager::frameStarted(float dt, bool paused)
|
||||||
{
|
{
|
||||||
if (mTerrain)
|
if (mTerrain && mTerrain->getVisible())
|
||||||
mTerrain->update(mRendering.getCamera()->getRealPosition());
|
mTerrain->update(mRendering.getCamera()->getRealPosition());
|
||||||
|
|
||||||
if (!paused)
|
if (!paused)
|
||||||
|
@ -1012,4 +1007,24 @@ float RenderingManager::getTerrainHeightAt(Ogre::Vector3 worldPos)
|
||||||
return mTerrain->getHeightAt(worldPos);
|
return mTerrain->getHeightAt(worldPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::enableTerrain(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
if (!mTerrain)
|
||||||
|
{
|
||||||
|
mTerrain = new Terrain::Terrain(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
|
||||||
|
Settings::Manager::getBool("distant land", "Terrain"),
|
||||||
|
Settings::Manager::getBool("shader", "Terrain"));
|
||||||
|
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
|
||||||
|
Settings::Manager::getBool("split", "Shadows"));
|
||||||
|
mTerrain->update(mRendering.getCamera()->getRealPosition());
|
||||||
|
}
|
||||||
|
mTerrain->setVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (mTerrain)
|
||||||
|
mTerrain->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -110,6 +110,8 @@ public:
|
||||||
void cellAdded (MWWorld::CellStore *store);
|
void cellAdded (MWWorld::CellStore *store);
|
||||||
void waterAdded(MWWorld::CellStore *store);
|
void waterAdded(MWWorld::CellStore *store);
|
||||||
|
|
||||||
|
void enableTerrain(bool enable);
|
||||||
|
|
||||||
void removeWater();
|
void removeWater();
|
||||||
|
|
||||||
void preCellChange (MWWorld::CellStore* store);
|
void preCellChange (MWWorld::CellStore* store);
|
||||||
|
|
|
@ -362,6 +362,8 @@ namespace MWWorld
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
mRendering.enableTerrain(false);
|
||||||
|
|
||||||
std::string loadingInteriorText;
|
std::string loadingInteriorText;
|
||||||
loadingInteriorText = gmst.find ("sLoadingMessage2")->getString();
|
loadingInteriorText = gmst.find ("sLoadingMessage2")->getString();
|
||||||
|
|
||||||
|
@ -440,6 +442,8 @@ namespace MWWorld
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->positionToIndex (position.pos[0], position.pos[1], x, y);
|
MWBase::Environment::get().getWorld()->positionToIndex (position.pos[0], position.pos[1], x, y);
|
||||||
|
|
||||||
|
mRendering.enableTerrain(true);
|
||||||
|
|
||||||
changeCell (x, y, position, true);
|
changeCell (x, y, position, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace Terrain
|
||||||
|
|
||||||
MaterialGenerator::MaterialGenerator(bool shaders)
|
MaterialGenerator::MaterialGenerator(bool shaders)
|
||||||
: mShaders(shaders)
|
: mShaders(shaders)
|
||||||
|
, mShadows(false)
|
||||||
|
, mSplitShadows(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,6 +48,11 @@ namespace Terrain
|
||||||
// first layer doesn't need blendmap
|
// first layer doesn't need blendmap
|
||||||
--freeTextureUnits;
|
--freeTextureUnits;
|
||||||
|
|
||||||
|
if (mSplitShadows)
|
||||||
|
freeTextureUnits -= 3;
|
||||||
|
else if (mShadows)
|
||||||
|
--freeTextureUnits;
|
||||||
|
|
||||||
// each layer needs 1.25 units (1xdiffusespec, 0.25xblend)
|
// each layer needs 1.25 units (1xdiffusespec, 0.25xblend)
|
||||||
return static_cast<Ogre::uint8>(freeTextureUnits / (1.25f)) + 1;
|
return static_cast<Ogre::uint8>(freeTextureUnits / (1.25f)) + 1;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +165,6 @@ namespace Terrain
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
sh::MaterialInstance* material = sh::Factory::getInstance().createMaterialInstance (name.str());
|
sh::MaterialInstance* material = sh::Factory::getInstance().createMaterialInstance (name.str());
|
||||||
material->setProperty ("allow_fixed_function", sh::makeProperty<sh::BooleanValue>(new sh::BooleanValue(false)));
|
material->setProperty ("allow_fixed_function", sh::makeProperty<sh::BooleanValue>(new sh::BooleanValue(false)));
|
||||||
|
|
||||||
|
@ -179,12 +185,14 @@ namespace Terrain
|
||||||
tex->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp")));
|
tex->setProperty ("tex_address_mode", sh::makeProperty (new sh::StringValue("clamp")));
|
||||||
|
|
||||||
// shadow. TODO: repeated, put in function
|
// shadow. TODO: repeated, put in function
|
||||||
for (Ogre::uint i = 0; i < 3; ++i)
|
if (mShadows)
|
||||||
|
{
|
||||||
|
for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i)
|
||||||
{
|
{
|
||||||
sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i));
|
sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i));
|
||||||
shadowTex->setProperty ("content_type", sh::makeProperty<sh::StringValue> (new sh::StringValue("shadow")));
|
shadowTex->setProperty ("content_type", sh::makeProperty<sh::StringValue> (new sh::StringValue("shadow")));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty (new sh::StringValue(
|
p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty (new sh::StringValue(
|
||||||
Ogre::StringConverter::toString(1))));
|
Ogre::StringConverter::toString(1))));
|
||||||
|
|
||||||
|
@ -272,12 +280,14 @@ namespace Terrain
|
||||||
}
|
}
|
||||||
|
|
||||||
// shadow
|
// shadow
|
||||||
for (Ogre::uint i = 0; i < 3; ++i)
|
if (mShadows)
|
||||||
|
{
|
||||||
|
for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i)
|
||||||
{
|
{
|
||||||
sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i));
|
sh::MaterialInstanceTextureUnit* shadowTex = p->createTextureUnit ("shadowMap" + Ogre::StringConverter::toString(i));
|
||||||
shadowTex->setProperty ("content_type", sh::makeProperty<sh::StringValue> (new sh::StringValue("shadow")));
|
shadowTex->setProperty ("content_type", sh::makeProperty<sh::StringValue> (new sh::StringValue("shadow")));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty (new sh::StringValue(
|
p->mShaderProperties.setProperty ("shadowtexture_offset", sh::makeProperty (new sh::StringValue(
|
||||||
Ogre::StringConverter::toString(numBlendTextures + numLayersInThisPass))));
|
Ogre::StringConverter::toString(numBlendTextures + numLayersInThisPass))));
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ namespace Terrain
|
||||||
const std::vector<Ogre::TexturePtr>& getBlendmapList() { return mBlendmapList; }
|
const std::vector<Ogre::TexturePtr>& getBlendmapList() { return mBlendmapList; }
|
||||||
void setCompositeMap (const std::string& name) { mCompositeMap = name; }
|
void setCompositeMap (const std::string& name) { mCompositeMap = name; }
|
||||||
|
|
||||||
|
void enableShadows(bool shadows) { mShadows = shadows; }
|
||||||
|
void enableSplitShadows(bool splitShadows) { mSplitShadows = splitShadows; }
|
||||||
|
|
||||||
/// Creates a material suitable for displaying a chunk of terrain using alpha-blending.
|
/// Creates a material suitable for displaying a chunk of terrain using alpha-blending.
|
||||||
/// @param mat Material that will be replaced by the generated material. May be empty as well, in which case
|
/// @param mat Material that will be replaced by the generated material. May be empty as well, in which case
|
||||||
/// a new material is created.
|
/// a new material is created.
|
||||||
|
@ -48,6 +51,8 @@ namespace Terrain
|
||||||
std::vector<Ogre::TexturePtr> mBlendmapList;
|
std::vector<Ogre::TexturePtr> mBlendmapList;
|
||||||
std::string mCompositeMap;
|
std::string mCompositeMap;
|
||||||
bool mShaders;
|
bool mShaders;
|
||||||
|
bool mShadows;
|
||||||
|
bool mSplitShadows;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,10 @@ void QuadTreeNode::update(const Ogre::Vector3 &cameraPos)
|
||||||
mChunk->setVisibilityFlags(mTerrain->getVisiblityFlags());
|
mChunk->setVisibilityFlags(mTerrain->getVisiblityFlags());
|
||||||
mChunk->setCastShadows(true);
|
mChunk->setCastShadows(true);
|
||||||
mSceneNode->attachObject(mChunk);
|
mSceneNode->attachObject(mChunk);
|
||||||
|
|
||||||
|
mMaterialGenerator->enableShadows(mTerrain->getShadowsEnabled());
|
||||||
|
mMaterialGenerator->enableSplitShadows(mTerrain->getSplitShadowsEnabled());
|
||||||
|
|
||||||
if (mSize == 1)
|
if (mSize == 1)
|
||||||
{
|
{
|
||||||
ensureLayerInfo();
|
ensureLayerInfo();
|
||||||
|
@ -338,9 +342,12 @@ void QuadTreeNode::destroyChunks()
|
||||||
mMaterialGenerator->setCompositeMap("");
|
mMaterialGenerator->setCompositeMap("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mCompositeMap.isNull())
|
||||||
|
{
|
||||||
Ogre::TextureManager::getSingleton().remove(mCompositeMap->getName());
|
Ogre::TextureManager::getSingleton().remove(mCompositeMap->getName());
|
||||||
mCompositeMap.setNull();
|
mCompositeMap.setNull();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (hasChildren())
|
else if (hasChildren())
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mChildren[i]->destroyChunks();
|
mChildren[i]->destroyChunks();
|
||||||
|
@ -444,3 +451,29 @@ void QuadTreeNode::ensureCompositeMap()
|
||||||
mTerrain->clearCompositeMapSceneManager();
|
mTerrain->clearCompositeMapSceneManager();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuadTreeNode::applyMaterials()
|
||||||
|
{
|
||||||
|
if (mChunk)
|
||||||
|
{
|
||||||
|
mMaterialGenerator->enableShadows(mTerrain->getShadowsEnabled());
|
||||||
|
mMaterialGenerator->enableSplitShadows(mTerrain->getSplitShadowsEnabled());
|
||||||
|
if (mSize <= 1)
|
||||||
|
mChunk->setMaterial(mMaterialGenerator->generate(Ogre::MaterialPtr()));
|
||||||
|
else
|
||||||
|
mChunk->setMaterial(mMaterialGenerator->generateForCompositeMap(Ogre::MaterialPtr()));
|
||||||
|
}
|
||||||
|
if (hasChildren())
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
mChildren[i]->applyMaterials();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuadTreeNode::setVisible(bool visible)
|
||||||
|
{
|
||||||
|
if (!visible && mChunk)
|
||||||
|
mChunk->setVisible(false);
|
||||||
|
|
||||||
|
if (hasChildren())
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
mChildren[i]->setVisible(visible);
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,11 @@ namespace Terrain
|
||||||
QuadTreeNode (Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2& center, QuadTreeNode* parent);
|
QuadTreeNode (Terrain* terrain, ChildDirection dir, float size, const Ogre::Vector2& center, QuadTreeNode* parent);
|
||||||
~QuadTreeNode();
|
~QuadTreeNode();
|
||||||
|
|
||||||
|
void setVisible(bool visible);
|
||||||
|
|
||||||
|
/// Rebuild all materials
|
||||||
|
void applyMaterials();
|
||||||
|
|
||||||
/// Initialize neighbours - do this after the quadtree is built
|
/// Initialize neighbours - do this after the quadtree is built
|
||||||
void initNeighbours();
|
void initNeighbours();
|
||||||
/// Initialize bounding boxes of non-leafs by merging children bounding boxes.
|
/// Initialize bounding boxes of non-leafs by merging children bounding boxes.
|
||||||
|
|
|
@ -425,7 +425,7 @@ namespace Terrain
|
||||||
0---1 0---1
|
0---1 0---1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Build all 4 positions in terrain space, using point-sampled height
|
// Build all 4 positions in normalized cell space, using point-sampled height
|
||||||
Ogre::Vector3 v0 (startXTS, startYTS, getVertexHeight(land, startX, startY) / 8192.f);
|
Ogre::Vector3 v0 (startXTS, startYTS, getVertexHeight(land, startX, startY) / 8192.f);
|
||||||
Ogre::Vector3 v1 (endXTS, startYTS, getVertexHeight(land, endX, startY) / 8192.f);
|
Ogre::Vector3 v1 (endXTS, startYTS, getVertexHeight(land, endX, startY) / 8192.f);
|
||||||
Ogre::Vector3 v2 (endXTS, endYTS, getVertexHeight(land, endX, endY) / 8192.f);
|
Ogre::Vector3 v2 (endXTS, endYTS, getVertexHeight(land, endX, endY) / 8192.f);
|
||||||
|
|
|
@ -370,5 +370,23 @@ namespace Terrain
|
||||||
return mStorage->getHeightAt(worldPos);
|
return mStorage->getHeightAt(worldPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Terrain::applyMaterials(bool shadows, bool splitShadows)
|
||||||
|
{
|
||||||
|
mShadows = shadows;
|
||||||
|
mSplitShadows = splitShadows;
|
||||||
|
mRootNode->applyMaterials();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terrain::setVisible(bool visible)
|
||||||
|
{
|
||||||
|
mVisible = visible;
|
||||||
|
mRootNode->setVisible(visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Terrain::getVisible()
|
||||||
|
{
|
||||||
|
return mVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace Terrain
|
||||||
|
|
||||||
bool getDistantLandEnabled() { return mDistantLand; }
|
bool getDistantLandEnabled() { return mDistantLand; }
|
||||||
bool getShadersEnabled() { return mShaders; }
|
bool getShadersEnabled() { return mShaders; }
|
||||||
|
bool getShadowsEnabled() { return mShadows; }
|
||||||
|
bool getSplitShadowsEnabled() { return mSplitShadows; }
|
||||||
|
|
||||||
float getHeightAt (const Ogre::Vector3& worldPos);
|
float getHeightAt (const Ogre::Vector3& worldPos);
|
||||||
|
|
||||||
|
@ -56,14 +58,16 @@ namespace Terrain
|
||||||
Storage* getStorage() { return mStorage; }
|
Storage* getStorage() { return mStorage; }
|
||||||
|
|
||||||
/// Show or hide the whole terrain
|
/// Show or hide the whole terrain
|
||||||
|
/// @note this setting will be invalidated once you call Terrain::update, so do not call it while the terrain should be hidden
|
||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
|
bool getVisible();
|
||||||
|
|
||||||
/// Recreate materials used by terrain chunks. This should be called whenever settings of
|
/// Recreate materials used by terrain chunks. This should be called whenever settings of
|
||||||
/// the material factory are changed. (Relying on the factory to update those materials is not
|
/// the material factory are changed. (Relying on the factory to update those materials is not
|
||||||
/// enough, since turning a feature on/off can change the number of texture units available for layer/blend
|
/// enough, since turning a feature on/off can change the number of texture units available for layer/blend
|
||||||
/// textures, and to properly respond to this we may need to change the structure of the material, such as
|
/// textures, and to properly respond to this we may need to change the structure of the material, such as
|
||||||
/// adding or removing passes. This can only be achieved by a full rebuild.)
|
/// adding or removing passes. This can only be achieved by a full rebuild.)
|
||||||
void applyMaterials();
|
void applyMaterials(bool shadows, bool splitShadows);
|
||||||
|
|
||||||
int getVisiblityFlags() { return mVisibilityFlags; }
|
int getVisiblityFlags() { return mVisibilityFlags; }
|
||||||
|
|
||||||
|
@ -74,6 +78,9 @@ namespace Terrain
|
||||||
private:
|
private:
|
||||||
bool mDistantLand;
|
bool mDistantLand;
|
||||||
bool mShaders;
|
bool mShaders;
|
||||||
|
bool mShadows;
|
||||||
|
bool mSplitShadows;
|
||||||
|
bool mVisible;
|
||||||
|
|
||||||
QuadTreeNode* mRootNode;
|
QuadTreeNode* mRootNode;
|
||||||
Storage* mStorage;
|
Storage* mStorage;
|
||||||
|
|
|
@ -348,7 +348,6 @@ float2 blendUV = (UV - 0.5) * (16.0 / (16.0+1.0)) + 0.5;
|
||||||
#else
|
#else
|
||||||
shOutputColour(0).a = 1.f-previousAlpha;
|
shOutputColour(0).a = 1.f-previousAlpha;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue