1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-02 07:15:34 +00:00

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);
//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
* of the rendered terrain due to light issues (the lighting differs
* so much that it is very noticable
* of the rendered terrain due to not having setup lighting
*/
mTerrainGlobals->setCompositeMapDistance(ESM::Land::REAL_SIZE*4);
@ -38,6 +37,10 @@ namespace MWRender
static_cast<Ogre::TerrainMaterialGeneratorA::SM2Profile*>(activeProfile);
matProfile->setLightmapEnabled(false);
matProfile->setLayerSpecularMappingEnabled(false);
matProfile->setLayerParallaxMappingEnabled(false);
matProfile->setReceiveDynamicShadowsEnabled(false);
//scale the land size if required
@ -85,8 +88,6 @@ namespace MWRender
const int cellX = store->cell->getGridX();
const int cellY = store->cell->getGridY();
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
if ( SPLIT_TERRAIN )
{
@ -97,6 +98,9 @@ namespace MWRender
{
for ( int y = 0; y < 2; y++ )
{
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
const int terrainX = cellX * 2 + x;
const int terrainY = cellY * 2 + y;
@ -138,6 +142,9 @@ namespace MWRender
}
else
{
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
//one cell is one terrain segment
terrainData.inputFloat = OGRE_ALLOC_T(float,
mLandSize*mLandSize,
@ -199,19 +206,17 @@ namespace MWRender
fromY+size <= ESM::Land::LAND_TEXTURE_SIZE &&
"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
terrainData->layerList.resize(1);
terrainData->layerList[0].worldSize = 256;
terrainData->layerList[0].textureNames.push_back("textures\\_land_default.dds");
terrainData->layerList[0].textureNames.push_back("textures\\_land_default.dds");
//there is one texture that we want to use as a base (i.e. it won't have
//a blend map). This holds the ltex index of that base texture so that
//we know not to include it in the output map
int baseTexture = -1;
for ( int y = fromY - 1; y < fromY + size + 1; y++ )
{
for ( int x = fromX - 1; x < fromX + size + 1; x++ )
{
const uint16_t ltexIndex = getLtexIndexAt(store, x, y);
//this is the base texture, so we can ignore this at present
if ( ltexIndex == 0 )
if ( ltexIndex == baseTexture )
{
continue;
}
@ -225,21 +230,35 @@ namespace MWRender
store->landTextures->ltex.size() > (size_t)ltexIndex - 1 &&
"LAND.VTEX must be within the bounds of the LTEX array");
std::string 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";
std::string texture;
if ( ltexIndex == 0 )
{
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();
terrainData->layerList.push_back(Ogre::Terrain::LayerInstance());
Ogre::TexturePtr normDisp = getNormalDisp("textures\\" + texture);
terrainData->layerList[position].worldSize = 256;
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
//the material generator. Another option would be to use a 1x1 blank texture
terrainData->layerList[position].textureNames.push_back("textures\\" + texture);
indexes[ltexIndex] = position;
if ( baseTexture == -1 )
{
baseTexture = ltexIndex;
}
else
{
indexes[ltexIndex] = position;
}
}
}
}
@ -271,9 +290,9 @@ namespace MWRender
std::map<uint16_t, int>::const_iterator iter;
for ( iter = indexes.begin(); iter != indexes.end(); ++iter )
{
float* pBlend = terrain->getLayerBlendMap(iter->second)
->getBlendPointer();
memset(pBlend, 0, sizeof(float) * blendSize * blendSize);
float* pBlend = terrain->getLayerBlendMap(iter->second)
->getBlendPointer();
memset(pBlend, 0, sizeof(float) * blendSize * blendSize);
}
//covert the ltex data into a set of blend maps
@ -288,15 +307,13 @@ namespace MWRender
const int relX = texX - fromX;
const int relY = texY - fromY;
//this is the ground texture, which is currently the base texture
//so don't alter the splatting map
if ( ltexIndex == 0 ){
//check if it is the base texture (which isn't in the map) and
//if it is don't bother altering the blend map for it
if ( indexes.find(ltexIndex) == indexes.end() )
{
continue;
}
assert (indexes.find(ltexIndex) != indexes.end() &&
"Texture layer must exist");
const int layerIndex = indexes.find(ltexIndex)->second;
float* const pBlend = terrain->getLayerBlendMap(layerIndex)
@ -310,7 +327,7 @@ namespace MWRender
const int startY = std::max(0, relY*splatSize - blendDist);
const int endY = std::min(blendSize, (relY+1)*splatSize + blendDist);
for ( int blendX = startX; blendX < endX; blendX++ )
{
for ( int blendY = startY; blendY < endY; blendY++ )
@ -321,34 +338,16 @@ namespace MWRender
assert(blendY >= 0 && blendY < blendSize &&
"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;
pBlend[index] += blendAmount;
pBlend[index] = std::min((float)1, pBlend[index]);
if ( blendX >= relX*splatSize && blendX < (relX+1)*splatSize &&
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];
}
//----------------------------------------------------------------------------------------------
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
* 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
@ -107,6 +107,17 @@ namespace MWRender{
* first splat of the current cell
*/
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);
};