From 5f7e6f7b104da9ba53e0061db9970958fef53129 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 21 Aug 2013 16:01:32 +0200 Subject: [PATCH] Fix a material issue, layers per pass wasn't entirely correct --- components/terrain/material.cpp | 98 ++++++++++++++++----------------- components/terrain/material.hpp | 4 -- files/materials/terrain.shader | 4 +- 3 files changed, 51 insertions(+), 55 deletions(-) diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 4a91ad99a..ebf6046ff 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -40,29 +40,6 @@ namespace Terrain } - int MaterialGenerator::getMaxLayersPerPass () - { - // count the texture units free - Ogre::uint8 freeTextureUnits = 16; - - // first layer doesn't need blendmap - --freeTextureUnits; - - if (mSplitShadows) - freeTextureUnits -= 3; - else if (mShadows) - --freeTextureUnits; - - // each layer needs 1.25 units (1xdiffusespec, 0.25xblend) - return static_cast(freeTextureUnits / (1.25f)) + 1; - } - - int MaterialGenerator::getRequiredPasses () - { - int maxLayersPerPass = getMaxLayersPerPass(); - return std::max(1.f, std::ceil(static_cast(mLayerList.size()) / maxLayersPerPass)); - } - Ogre::MaterialPtr MaterialGenerator::generate(Ogre::MaterialPtr mat) { return create(mat, false, false); @@ -201,45 +178,64 @@ namespace Terrain else { - int numPasses = getRequiredPasses(); - assert(numPasses); - int maxLayersInOnePass = getMaxLayersPerPass(); + bool shadows = mShadows && !renderCompositeMap; - for (int pass=0; pass blendTextures; + int remainingTextureUnits = OGRE_MAX_TEXTURE_LAYERS; + if (shadows) + remainingTextureUnits -= (mSplitShadows ? 3 : 1); + while (remainingTextureUnits && layerOffset + numLayersInThisPass < (int)mLayerList.size()) + { + int layerIndex = numLayersInThisPass + layerOffset; + + int neededTextureUnits=0; + int neededBlendTextures=0; + + if (layerIndex != 0) + { + std::string blendTextureName = mBlendmapList[getBlendmapIndexForLayer(layerIndex)]->getName(); + if (std::find(blendTextures.begin(), blendTextures.end(), blendTextureName) == blendTextures.end()) + { + blendTextures.push_back(blendTextureName); + ++neededBlendTextures; + ++neededTextureUnits; // blend texture + } + } + ++neededTextureUnits; // layer texture + if (neededTextureUnits <= remainingTextureUnits) + { + // We can fit another! + remainingTextureUnits -= neededTextureUnits; + numBlendTextures += neededBlendTextures; + ++numLayersInThisPass; + } + else + break; // We're full + } + sh::MaterialInstancePass* p = material->createPass (); p->setProperty ("vertex_program", sh::makeProperty(new sh::StringValue("terrain_vertex"))); p->setProperty ("fragment_program", sh::makeProperty(new sh::StringValue("terrain_fragment"))); - if (pass != 0) + if (layerOffset != 0) { p->setProperty ("scene_blend", sh::makeProperty(new sh::StringValue("alpha_blend"))); // Only write if depth is equal to the depth value written by the previous pass. p->setProperty ("depth_func", sh::makeProperty(new sh::StringValue("equal"))); } - p->mShaderProperties.setProperty ("is_first_pass", sh::makeProperty(new sh::BooleanValue(pass == 0))); p->mShaderProperties.setProperty ("render_composite_map", sh::makeProperty(new sh::BooleanValue(renderCompositeMap))); p->mShaderProperties.setProperty ("display_composite_map", sh::makeProperty(new sh::BooleanValue(displayCompositeMap))); - Ogre::uint numLayersInThisPass = std::min(maxLayersInOnePass, (int)mLayerList.size()-layerOffset); - - // a blend map might be shared between two passes - Ogre::uint numBlendTextures=0; - std::vector blendTextures; - for (unsigned int layer=blendmapOffset; layergetName(); - if (std::find(blendTextures.begin(), blendTextures.end(), blendTextureName) == blendTextures.end()) - { - blendTextures.push_back(blendTextureName); - ++numBlendTextures; - } - } - p->mShaderProperties.setProperty ("num_layers", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numLayersInThisPass)))); p->mShaderProperties.setProperty ("num_blendmaps", sh::makeProperty (new sh::StringValue(Ogre::StringConverter::toString(numBlendTextures)))); @@ -250,7 +246,7 @@ namespace Terrain blendmapStart = 0; else blendmapStart = getBlendmapIndexForLayer(layerOffset+blendmapOffset); - for (Ogre::uint i = 0; i < numBlendTextures; ++i) + for (int i = 0; i < numBlendTextures; ++i) { sh::MaterialInstanceTextureUnit* blendTex = p->createTextureUnit ("blendMap" + Ogre::StringConverter::toString(i)); blendTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue(mBlendmapList[blendmapStart+i]->getName()))); @@ -258,7 +254,7 @@ namespace Terrain } // layer maps - for (Ogre::uint i = 0; i < numLayersInThisPass; ++i) + for (int i = 0; i < numLayersInThisPass; ++i) { sh::MaterialInstanceTextureUnit* diffuseTex = p->createTextureUnit ("diffuseMap" + Ogre::StringConverter::toString(i)); diffuseTex->setProperty ("direct_texture", sh::makeProperty (new sh::StringValue("textures\\"+mLayerList[layerOffset+i]))); @@ -280,7 +276,7 @@ namespace Terrain } // shadow - if (mShadows) + if (shadows) { for (Ogre::uint i = 0; i < (mSplitShadows ? 3 : 1); ++i) { @@ -292,7 +288,9 @@ namespace Terrain Ogre::StringConverter::toString(numBlendTextures + numLayersInThisPass)))); // Make sure the pass index is fed to the permutation handler, because blendmap components may be different - p->mShaderProperties.setProperty ("pass_index", sh::makeProperty(new sh::IntValue(pass))); + p->mShaderProperties.setProperty ("pass_index", sh::makeProperty(new sh::IntValue(layerOffset))); + + layerOffset += numLayersInThisPass; } } } diff --git a/components/terrain/material.hpp b/components/terrain/material.hpp index 2788b79c4..330ed3d14 100644 --- a/components/terrain/material.hpp +++ b/components/terrain/material.hpp @@ -43,10 +43,6 @@ namespace Terrain private: Ogre::MaterialPtr create (Ogre::MaterialPtr mat, bool renderCompositeMap, bool displayCompositeMap); - int getRequiredPasses (); - int getMaxLayersPerPass (); - - int mNumLayers; std::vector mLayerList; std::vector mBlendmapList; std::string mCompositeMap; diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 2bff6d58f..861841a84 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -39,7 +39,6 @@ #if LIGHTING @shAllocatePassthrough(3, lightResult) @shAllocatePassthrough(3, directionalResult) -#endif #if SHADOWS @shAllocatePassthrough(4, lightSpacePos0) @@ -49,6 +48,7 @@ @shAllocatePassthrough(4, lightSpacePos@shIterator) @shEndForeach #endif +#endif #ifdef SH_VERTEX_SHADER @@ -200,6 +200,7 @@ @shPassthroughFragmentInputs +#if LIGHTING #if SHADOWS shSampler2D(shadowMap0) shUniform(float2, invShadowmapSize0) @shAutoConstant(invShadowmapSize0, inverse_texture_size, @shPropertyString(shadowtexture_offset)) @@ -215,6 +216,7 @@ #if SHADOWS || SHADOWS_PSSM shUniform(float4, shadowFar_fadeStart) @shSharedParameter(shadowFar_fadeStart) #endif +#endif #if (UNDERWATER) || (FOG) shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix)