diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index dadc64f57..52850fd74 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -361,6 +361,11 @@ namespace ESMTerrain std::string Storage::getTextureName(UniqueTextureId id) { + // Goes under used terrain blend transitions + static const std::string baseTexture = "textures\\tx_black_01.dds"; + if (id.first == -1) + return baseTexture; + static const std::string defaultTexture = "textures\\_land_default.dds"; if (id.first == 0) return defaultTexture; // Not sure if the default texture really is hardcoded? @@ -396,11 +401,9 @@ namespace ESMTerrain // Save the used texture indices so we know the total number of textures // and number of required blend maps std::set textureIndices; - // Due to the way the blending works, the base layer will always shine through in between - // blend transitions (eg halfway between two texels, both blend values will be 0.5, so 25% of base layer visible). - // To get a consistent look, we need to make sure to use the same base layer in all cells. - // So we're always adding _land_default.dds as the base layer here, even if it's not referenced in this cell. - textureIndices.insert(std::make_pair(0,0)); + // Due to the way the blending works, the base layer will bleed between texture transitions so we want it to be a black texture + // The subsequent passes are added instead of blended, so this gives the correct result + textureIndices.insert(std::make_pair(-1,0)); // -1 goes to tx_black_01 LandCache cache; @@ -618,15 +621,6 @@ namespace ESMTerrain return info; } - Terrain::LayerInfo Storage::getDefaultLayer() - { - Terrain::LayerInfo info; - info.mDiffuseMap = "textures\\_land_default.dds"; - info.mParallax = false; - info.mSpecular = false; - return info; - } - float Storage::getCellWorldSize() { return static_cast(ESM::Land::REAL_SIZE); diff --git a/components/esmterrain/storage.hpp b/components/esmterrain/storage.hpp index 0bb24a4ab..f3300f748 100644 --- a/components/esmterrain/storage.hpp +++ b/components/esmterrain/storage.hpp @@ -94,8 +94,6 @@ namespace ESMTerrain virtual float getHeightAt (const osg::Vec3f& worldPos); - virtual Terrain::LayerInfo getDefaultLayer(); - /// Get the transformation factor for mapping cell units to world units. virtual float getCellWorldSize(); diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 56ace0e5a..722df9507 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -2,11 +2,13 @@ #include +#include #include #include #include #include #include +#include #include @@ -59,24 +61,52 @@ namespace Terrain } return depth; } + osg::ref_ptr getLequalDepth() + { + static osg::ref_ptr depth; + if (!depth) + { + depth = new osg::Depth; + depth->setFunction(osg::Depth::LEQUAL); + } + return depth; + } std::vector > createPasses(bool useShaders, bool forcePerPixelLighting, bool clampLighting, Shader::ShaderManager* shaderManager, const std::vector &layers, const std::vector > &blendmaps, int blendmapScale, float layerTileSize) { std::vector > passes; - bool firstLayer = true; unsigned int blendmapIndex = 0; unsigned int passIndex = 0; for (std::vector::const_iterator it = layers.begin(); it != layers.end(); ++it) { + bool firstLayer = (it == layers.begin()); + osg::ref_ptr stateset (new osg::StateSet); if (!firstLayer) { + static osg::ref_ptr blendFunc; + if (!blendFunc) + { + blendFunc= new osg::BlendFunc(); + blendFunc->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE); + } stateset->setMode(GL_BLEND, osg::StateAttribute::ON); + stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON); + stateset->setAttributeAndModes(getEqualDepth(), osg::StateAttribute::ON); } + // disable fog if we're the first layer of several - supposed to be completely black + if (firstLayer && blendmaps.size() > 0) + { + osg::ref_ptr fog (new osg::Fog); + fog->setStart(10000000); + fog->setEnd(10000000); + stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE); + stateset->setAttributeAndModes(getLequalDepth(), osg::StateAttribute::ON); + } int texunit = 0; @@ -158,8 +188,6 @@ namespace Terrain stateset->setTextureAttributeAndModes(texunit, getLayerTexMat(layerTileSize), osg::StateAttribute::ON); } - firstLayer = false; - stateset->setRenderBinDetails(passIndex++, "RenderBin"); passes.push_back(stateset); diff --git a/components/terrain/storage.hpp b/components/terrain/storage.hpp index a4a8bc9fd..ebac1148c 100644 --- a/components/terrain/storage.hpp +++ b/components/terrain/storage.hpp @@ -72,8 +72,6 @@ namespace Terrain virtual float getHeightAt (const osg::Vec3f& worldPos) = 0; - virtual LayerInfo getDefaultLayer() = 0; - /// Get the transformation factor for mapping cell units to world units. virtual float getCellWorldSize() = 0;