1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 11:49:56 +00:00

Merge branch 'terrain' of https://github.com/Yacoby/openmw into terrain_next

Conflicts:
	apps/openmw/mwrender/terrain.cpp
This commit is contained in:
scrawl 2012-02-29 19:38:34 +01:00
commit bac7f23604
3 changed files with 128 additions and 64 deletions

View file

@ -17,9 +17,6 @@ namespace MWRender
{
mTerrainGlobals = OGRE_NEW Ogre::TerrainGlobalOptions();
mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals->setLayerBlendMapSize(SPLIT_TERRAIN ? 256 : 1024);
Ogre::TerrainMaterialGeneratorPtr matGen;
TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
matGen.bind(matGenP);
@ -31,11 +28,26 @@ namespace MWRender
TerrainMaterialGeneratorB::SM2Profile* matProfile =
static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
mTerrainGlobals->setMaxPixelError(8);
//mTerrainGlobals->setLayerBlendMapSize(SPLIT_TERRAIN ? 256 : 1024);
//mTerrainGlobals->setLightMapSize(SPLIT_TERRAIN ? 256 : 1024);
//mTerrainGlobals->setCompositeMapSize(SPLIT_TERRAIN ? 256 : 1024);
//mTerrainGlobals->setDefaultGlobalColourMapSize(256);
//10 (default) didn't seem to be quite enough
mTerrainGlobals->setSkirtSize(128);
/*
* Here we are pushing the composite map distance beyond the edge
* of the rendered terrain due to not having setup lighting
*/
//mTerrainGlobals->setCompositeMapDistance(ESM::Land::REAL_SIZE*4);
matProfile->setLightmapEnabled(false);
matProfile->setReceiveDynamicShadowsEnabled(false);
matProfile->setLayerSpecularMappingEnabled(false);
matProfile->setLayerNormalMappingEnabled(false);
matProfile->setLayerParallaxMappingEnabled(false);
matProfile->setLayerSpecularMappingEnabled(false);
matProfile->setReceiveDynamicShadowsEnabled(false);
mLandSize = ESM::Land::LAND_SIZE;
mRealSize = ESM::Land::REAL_SIZE;
@ -95,8 +107,6 @@ namespace MWRender
const int cellX = store->cell->getGridX();
const int cellY = store->cell->getGridY();
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
if ( SPLIT_TERRAIN )
{
@ -107,6 +117,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;
@ -133,6 +146,8 @@ namespace MWRender
x * numTextures, y * numTextures,
numTextures, indexes);
assert( mTerrainGroup->getTerrain(cellX, cellY) == NULL &&
"The terrain for this cell already existed" );
mTerrainGroup->defineTerrain(terrainX, terrainY, &terrainData);
mTerrainGroup->loadTerrain(terrainX, terrainY, true);
@ -146,6 +161,9 @@ namespace MWRender
}
else
{
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
//one cell is one terrain segment
terrainData.inputFloat = OGRE_ALLOC_T(float,
mLandSize*mLandSize,
@ -167,6 +185,7 @@ namespace MWRender
ESM::Land::LAND_TEXTURE_SIZE, indexes);
}
mTerrainGroup->freeTemporaryResources();
}
//----------------------------------------------------------------------------------------------
@ -179,14 +198,14 @@ namespace MWRender
{
for ( int y = 0; y < 2; y++ )
{
mTerrainGroup->removeTerrain(store->cell->getGridX() * 2 + x,
mTerrainGroup->unloadTerrain(store->cell->getGridX() * 2 + x,
store->cell->getGridY() * 2 + y);
}
}
}
else
{
mTerrainGroup->removeTerrain(store->cell->getGridX(),
mTerrainGroup->unloadTerrain(store->cell->getGridX(),
store->cell->getGridY());
}
}
@ -206,19 +225,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"); // diffuseSpec
//terrainData->layerList[0].textureNames.push_back("textures\\_land_default.dds"); // normalHeight
//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;
}
@ -232,25 +249,42 @@ 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;
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());
terrainData->layerList[position].worldSize = 256;
Ogre::TexturePtr normDisp = getNormalDisp("textures\\" + texture);
//terrainData->layerList[position].worldSize = 256;
terrainData->layerList[position].textureNames.push_back("textures\\" + texture);
//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);
//terrainData->layerList[position].textureNames.push_back(normDisp->getName());
if ( baseTexture == -1 )
{
baseTexture = ltexIndex;
}
else
{
indexes[ltexIndex] = position;
}
}
}
}
}
//----------------------------------------------------------------------------------------------
@ -295,15 +329,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)
@ -328,34 +360,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);
}
}
}
@ -420,4 +434,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

@ -65,7 +65,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
@ -111,6 +111,17 @@ namespace MWRender{
*/
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);
};
}

View file

@ -544,7 +544,7 @@ namespace Ogre
params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
params->setNamedAutoConstant("lightPosObjSpace", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, 0);
params->setNamedAutoConstant("lightDiffuseColour", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0);
params->setNamedAutoConstant("lightSpecularColour", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
//params->setNamedAutoConstant("lightSpecularColour", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
@ -948,7 +948,7 @@ namespace Ogre
"uniform float3 ambient,\n"
"uniform float4 lightPosObjSpace,\n"
"uniform float3 lightDiffuseColour,\n"
"uniform float3 lightSpecularColour,\n"
//"uniform float3 lightSpecularColour,\n"
"uniform float3 eyePosObjSpace,\n"
// pack scale, bias and specular
"uniform float4 scaleBiasSpecular,\n";
@ -1274,7 +1274,7 @@ namespace Ogre
else
{
// Apply specular
outStream << " outputCol.rgb += litRes.z * lightSpecularColour * specular * shadow;\n";
//outStream << " outputCol.rgb += litRes.z * lightSpecularColour * specular * shadow;\n";
if (prof->getParent()->getDebugLevel())
{