Removed the flawed shading, updated textures, removed the need for a unused base texture

This commit is contained in:
Jacob Essex 2012-02-11 20:54:29 +00:00
parent 9cc3af34e5
commit 286701e3a5
2 changed files with 107 additions and 58 deletions

View file

@ -22,12 +22,11 @@ namespace MWRender
mTerrainGlobals->setDefaultGlobalColourMapSize(256); mTerrainGlobals->setDefaultGlobalColourMapSize(256);
//10 (default) didn't seem to be quite enough //10 (default) didn't seem to be quite enough
mTerrainGlobals->setSkirtSize(32); mTerrainGlobals->setSkirtSize(128);
/* /*
* Here we are pushing the composite map distance beyond the edge * Here we are pushing the composite map distance beyond the edge
* of the rendered terrain due to light issues (the lighting differs * of the rendered terrain due to not having setup lighting
* so much that it is very noticable
*/ */
mTerrainGlobals->setCompositeMapDistance(ESM::Land::REAL_SIZE*4); mTerrainGlobals->setCompositeMapDistance(ESM::Land::REAL_SIZE*4);
@ -38,6 +37,10 @@ namespace MWRender
static_cast<Ogre::TerrainMaterialGeneratorA::SM2Profile*>(activeProfile); static_cast<Ogre::TerrainMaterialGeneratorA::SM2Profile*>(activeProfile);
matProfile->setLightmapEnabled(false); matProfile->setLightmapEnabled(false);
matProfile->setLayerSpecularMappingEnabled(false);
matProfile->setLayerParallaxMappingEnabled(false);
matProfile->setReceiveDynamicShadowsEnabled(false); matProfile->setReceiveDynamicShadowsEnabled(false);
//scale the land size if required //scale the land size if required
@ -85,8 +88,6 @@ namespace MWRender
const int cellX = store->cell->getGridX(); const int cellX = store->cell->getGridX();
const int cellY = store->cell->getGridY(); const int cellY = store->cell->getGridY();
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
if ( SPLIT_TERRAIN ) if ( SPLIT_TERRAIN )
{ {
@ -97,6 +98,9 @@ namespace MWRender
{ {
for ( int y = 0; y < 2; y++ ) for ( int y = 0; y < 2; y++ )
{ {
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
const int terrainX = cellX * 2 + x; const int terrainX = cellX * 2 + x;
const int terrainY = cellY * 2 + y; const int terrainY = cellY * 2 + y;
@ -138,6 +142,9 @@ namespace MWRender
} }
else else
{ {
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
//one cell is one terrain segment //one cell is one terrain segment
terrainData.inputFloat = OGRE_ALLOC_T(float, terrainData.inputFloat = OGRE_ALLOC_T(float,
mLandSize*mLandSize, mLandSize*mLandSize,
@ -199,19 +206,17 @@ namespace MWRender
fromY+size <= ESM::Land::LAND_TEXTURE_SIZE && fromY+size <= ESM::Land::LAND_TEXTURE_SIZE &&
"Can't get a terrain texture on terrain outside the current cell"); "Can't get a terrain texture on terrain outside the current cell");
//have a base texture for now, but this is probably not needed on most cells //there is one texture that we want to use as a base (i.e. it won't have
terrainData->layerList.resize(1); //a blend map). This holds the ltex index of that base texture so that
terrainData->layerList[0].worldSize = 256; //we know not to include it in the output map
terrainData->layerList[0].textureNames.push_back("textures\\_land_default.dds"); int baseTexture = -1;
terrainData->layerList[0].textureNames.push_back("textures\\_land_default.dds");
for ( int y = fromY - 1; y < fromY + size + 1; y++ ) for ( int y = fromY - 1; y < fromY + size + 1; y++ )
{ {
for ( int x = fromX - 1; x < fromX + size + 1; x++ ) for ( int x = fromX - 1; x < fromX + size + 1; x++ )
{ {
const uint16_t ltexIndex = getLtexIndexAt(store, x, y); const uint16_t ltexIndex = getLtexIndexAt(store, x, y);
//this is the base texture, so we can ignore this at present //this is the base texture, so we can ignore this at present
if ( ltexIndex == 0 ) if ( ltexIndex == baseTexture )
{ {
continue; continue;
} }
@ -225,21 +230,35 @@ namespace MWRender
store->landTextures->ltex.size() > (size_t)ltexIndex - 1 && store->landTextures->ltex.size() > (size_t)ltexIndex - 1 &&
"LAND.VTEX must be within the bounds of the LTEX array"); "LAND.VTEX must be within the bounds of the LTEX array");
std::string texture = store->landTextures->ltex[ltexIndex-1].texture; std::string texture;
//TODO this is needed due to MWs messed up texture handling if ( ltexIndex == 0 )
texture = texture.substr(0, texture.rfind(".")) + ".dds"; {
texture = "_land_default.dds";
}
else
{
texture = store->landTextures->ltex[ltexIndex-1].texture;
//TODO this is needed due to MWs messed up texture handling
texture = texture.substr(0, texture.rfind(".")) + ".dds";
}
const size_t position = terrainData->layerList.size(); const size_t position = terrainData->layerList.size();
terrainData->layerList.push_back(Ogre::Terrain::LayerInstance()); terrainData->layerList.push_back(Ogre::Terrain::LayerInstance());
Ogre::TexturePtr normDisp = getNormalDisp("textures\\" + texture);
terrainData->layerList[position].worldSize = 256; terrainData->layerList[position].worldSize = 256;
terrainData->layerList[position].textureNames.push_back("textures\\" + texture); terrainData->layerList[position].textureNames.push_back("textures\\" + texture);
terrainData->layerList[position].textureNames.push_back(normDisp->getName());
//Normal map. This should be removed but it would require alterations to if ( baseTexture == -1 )
//the material generator. Another option would be to use a 1x1 blank texture {
terrainData->layerList[position].textureNames.push_back("textures\\" + texture); baseTexture = ltexIndex;
}
indexes[ltexIndex] = position; else
{
indexes[ltexIndex] = position;
}
} }
} }
} }
@ -271,9 +290,9 @@ namespace MWRender
std::map<uint16_t, int>::const_iterator iter; std::map<uint16_t, int>::const_iterator iter;
for ( iter = indexes.begin(); iter != indexes.end(); ++iter ) for ( iter = indexes.begin(); iter != indexes.end(); ++iter )
{ {
float* pBlend = terrain->getLayerBlendMap(iter->second) float* pBlend = terrain->getLayerBlendMap(iter->second)
->getBlendPointer(); ->getBlendPointer();
memset(pBlend, 0, sizeof(float) * blendSize * blendSize); memset(pBlend, 0, sizeof(float) * blendSize * blendSize);
} }
//covert the ltex data into a set of blend maps //covert the ltex data into a set of blend maps
@ -288,15 +307,13 @@ namespace MWRender
const int relX = texX - fromX; const int relX = texX - fromX;
const int relY = texY - fromY; const int relY = texY - fromY;
//this is the ground texture, which is currently the base texture //check if it is the base texture (which isn't in the map) and
//so don't alter the splatting map //if it is don't bother altering the blend map for it
if ( ltexIndex == 0 ){ if ( indexes.find(ltexIndex) == indexes.end() )
{
continue; continue;
} }
assert (indexes.find(ltexIndex) != indexes.end() &&
"Texture layer must exist");
const int layerIndex = indexes.find(ltexIndex)->second; const int layerIndex = indexes.find(ltexIndex)->second;
float* const pBlend = terrain->getLayerBlendMap(layerIndex) float* const pBlend = terrain->getLayerBlendMap(layerIndex)
@ -310,7 +327,7 @@ namespace MWRender
const int startY = std::max(0, relY*splatSize - blendDist); const int startY = std::max(0, relY*splatSize - blendDist);
const int endY = std::min(blendSize, (relY+1)*splatSize + blendDist); const int endY = std::min(blendSize, (relY+1)*splatSize + blendDist);
for ( int blendX = startX; blendX < endX; blendX++ ) for ( int blendX = startX; blendX < endX; blendX++ )
{ {
for ( int blendY = startY; blendY < endY; blendY++ ) for ( int blendY = startY; blendY < endY; blendY++ )
@ -321,34 +338,16 @@ namespace MWRender
assert(blendY >= 0 && blendY < blendSize && assert(blendY >= 0 && blendY < blendSize &&
"index must be within texture bounds"); "index must be within texture bounds");
//calculate the distance from the edge of the square
// to the point we are shading
int distX = relX*splatSize - blendX;
if ( distX < 0 )
{
distX = std::max(0, blendX - (relX+1)*splatSize);
}
int distY = relY*splatSize - blendY;
if ( distY < 0 )
{
distY = std::max(0, blendY - (relY+1)*splatSize);
}
float blendAmount = blendDist - std::sqrt((float)distX*distX + distY*distY);
blendAmount /= blendDist;
//this is required as blendDist < sqrt(blendDist*blendDist + blendDist*blendDist)
//this means that the corners are slightly the "wrong" shape but totaly smooth
//shading for the edges
blendAmount = std::max( (float) 0.0, blendAmount);
assert(blendAmount >= 0 && "Blend should never be negative");
//flips the y
const int index = blendSize*(blendSize - 1 - blendY) + blendX; const int index = blendSize*(blendSize - 1 - blendY) + blendX;
pBlend[index] += blendAmount; if ( blendX >= relX*splatSize && blendX < (relX+1)*splatSize &&
pBlend[index] = std::min((float)1, pBlend[index]); blendY >= relY*splatSize && blendY < (relY+1)*splatSize )
{
pBlend[index] = 1;
}
else
{
pBlend[index] = std::max((float)pBlend[index], 0.5f);
}
} }
} }
@ -413,4 +412,43 @@ namespace MWRender
->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x]; ->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
} }
//----------------------------------------------------------------------------------------------
Ogre::TexturePtr TerrainManager::getNormalDisp(const std::string& fileName)
{
Ogre::TextureManager* const texMgr = Ogre::TextureManager::getSingletonPtr();
const std::string normalTextureName = fileName.substr(0, fileName.rfind("."))
+ "_n.dds";
if ( !texMgr->getByName(normalTextureName).isNull() )
{
return texMgr->getByName(normalTextureName);
}
const std::string textureName = "default_terrain_normal";
if ( !texMgr->getByName(textureName).isNull() )
{
return texMgr->getByName(textureName);
}
Ogre::TexturePtr tex = texMgr->createManual(
textureName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, 1, 1, 0, Ogre::PF_BYTE_BGRA);
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = tex->getBuffer();
pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
*pDest++ = 128; // B
*pDest++ = 128; // G
*pDest++ = 128; // R
*pDest++ = 0; // A
pixelBuffer->unlock();
return tex;
}
} }

View file

@ -62,7 +62,7 @@ namespace MWRender{
* The distance that the current cell should be shaded into the neighbouring * The distance that the current cell should be shaded into the neighbouring
* texture. The distance is in terms of the splat size of a texture * texture. The distance is in terms of the splat size of a texture
*/ */
static const float TERRAIN_SHADE_DISTANCE = 0.5; static const float TERRAIN_SHADE_DISTANCE = 0.25f;
/** /**
* Setups up the list of textures for part of a cell, using indexes as * Setups up the list of textures for part of a cell, using indexes as
@ -107,6 +107,17 @@ namespace MWRender{
* first splat of the current cell * first splat of the current cell
*/ */
int getLtexIndexAt(MWWorld::Ptr::CellStore* store, int x, int y); int getLtexIndexAt(MWWorld::Ptr::CellStore* store, int x, int y);
/**
* Retrives the texture that is the normal and parallax map for the
* terrain. If it doesn't exist a blank texture is used
*
* The file name of the texture should be the same as the file name of
* the base diffuse texture, but with _n appended before the extension
*
* @param fileName the name of the *diffuse* texture
*/
Ogre::TexturePtr getNormalDisp(const std::string& fileName);
}; };