adds a built in detail map generator

splitTerrainMaps("data/some/file"); or  makeTerrainMapsFrom("module:anAsset"); to take a detailed albedo map and split it into a _bas(is) file thats an averaghe of the inut and a _det(ail) file to raise and lower different channels from that average.
special note: while used primarily for terrain authoring, these files could also be plugged into a normal material
This commit is contained in:
AzaezelX 2025-02-06 14:46:05 -06:00
parent e77c4b3a18
commit 516df48354
3 changed files with 116 additions and 0 deletions

View file

@ -1632,3 +1632,107 @@ DefineEngineFunction( reloadTextures, void, (),,
TEXMGR->reloadTextures();
PROBEMGR->reloadTextures();
}
void GFXTextureManager::splitTerrainMaps(const Torque::Path& path)
{
bool decompressed = false;
GFXTextureObject* inputTex = createTexture(path, &GFXTexturePersistentSRGBProfile);
if (!inputTex)
{
Con::errorf("GFXTextureManager::splitTerrainMaps - Unable to create texture: %s", path.getFullPath().c_str());
return;
}
GBitmap* inData = inputTex->getBitmap();
if (!inData)
{
DDSFile* tryDDS = inputTex->getDDS();
if (!tryDDS)
{
Con::errorf("GFXTextureManager::splitTerrainMaps - Unable to load texture: %s", path.getFullPath().c_str());
return;
}
decompressed = true;
inData = new GBitmap();
tryDDS->decompressToGBitmap(inData);
}
double average[4] = { 0.0, 0.0, 0.0, 0.0 };
Point2F inputSize = Point2F(inputTex->getBitmapWidth(), inputTex->getBitmapHeight());
U32 count = inputSize.x * inputSize.y;
int u, v;
for (u = 0; u < inputSize.x; u++)
{
for (v = 0; v < inputSize.y; v++)
{
LinearColorF color = inData->sampleTexel(u/ F32(inputSize.x), v / F32(inputSize.y), true);
average[0] += color.red;
average[1] += color.green;
average[2] += color.blue;
average[3] += color.alpha;
}
}
for (U32 i = 0; i < 4; i++)
{
average[i] /= count;
}
LinearColorF averageColor = LinearColorF(F32(average[0]), F32(average[1]), F32(average[2]), F32(average[3]));
Con::printf("Average color: %f %f %f %f", averageColor.red, averageColor.green, averageColor.blue, averageColor.alpha);
GBitmap* outBitmap[2];
outBitmap[0] = new GBitmap();
outBitmap[0]->allocateBitmap(inputSize.x, inputSize.y, false, GFXFormatR8G8B8A8);
for (u = 0; u < inputSize.x; u++)
{
for (v= 0; v < inputSize.y; v++)
{
outBitmap[0]->setColor(u, v, averageColor.toColorI(true));
}
}
Torque::Path difPath = path;
difPath.setFileName(path.getFileName()+String("_bas"));
difPath.setExtension("png");
GFXTextureObject* difRet = _createTexture(outBitmap[0], String(difPath), &GFXTexturePersistentProfile, false, NULL);
difRet->dumpToDisk("png", difPath.getFullPath());
outBitmap[1] = new GBitmap();
outBitmap[1]->allocateBitmap(inputSize.x, inputSize.y, false, GFXFormatR8G8B8A8);
for (u = 0; u < inputSize.x; u++)
{
for (v = 0; v < inputSize.y; v++)
{
LinearColorF color = inData->sampleTexel(u / F32(inputSize.x), v / F32(inputSize.y), true);
color -= averageColor;
color *= 0.5;
color += LinearColorF(0.5,0.5,0.5);
outBitmap[1]->setColor(u, v, color.toColorI(true));
}
}
Torque::Path detPath = path;
detPath.setFileName(path.getFileName() + String("_det"));
detPath.setExtension("png");
GFXTextureObject* detRet = _createTexture(outBitmap[1], String(detPath), &GFXTexturePersistentProfile, false, NULL);
detRet->dumpToDisk("png", detPath.getFullPath());
delete outBitmap[0];
delete outBitmap[1];
if (decompressed)
delete inData;
}
DefineEngineFunction(splitTerrainMaps, void, (const char* path), ,
"Splits a detailed albedo map into separate diffuse and detail textures and saves them to disk.\n"
"@param path The path to the input albedo map.\n"
"@ingroup GFX\n")
{
GFX->getTextureManager()->splitTerrainMaps(path);
}

View file

@ -193,6 +193,7 @@ public:
/// Used to remove a cubemap from the cache.
void releaseCubemap( GFXCubemap *cubemap );
void splitTerrainMaps(const Torque::Path& path);
public:
/// The amount of texture mipmaps to skip when loading a
/// texture that allows downscaling.

View file

@ -782,4 +782,15 @@ function getNumCanCallOnObjectList(%functionName, %objectsList)
}
return %numberWithFunction;
}
function getImageFileName(%id)
{
%assetDef = AssetDatabase.acquireAsset(%id);
return %assetDef.getImagePath();
}
function makeTerrainMapsFrom(%id)
{
splitTerrainMaps(getImageFileName(%id));
}