csgo-2018-source/materialobjects/dmeprecompiledtexture.cpp
2021-07-24 21:11:47 -07:00

380 lines
12 KiB
C++

//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "materialobjects/dmeprecompiledtexture.h"
#include "datamodel/dmelementfactoryhelper.h"
#include "materialobjects/dmetexture.h"
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmePrecompiledTexture, CDmePrecompiledTexture );
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
void CDmePrecompiledTexture::OnConstruction()
{
m_ImageFileName.Init( this, "imageFileName" );
m_Processors.Init( this, "processors" );
m_pSourceTexture.Init( this, "sourceTexture" );
m_nStartFrame.InitAndSet( this, "startFrame", -1 );
m_nEndFrame.InitAndSet( this, "endFrame", -1 );
m_nVolumeTextureDepth.InitAndSet( this, "volumeTextureDepth", 1 );
m_nTextureArraySize.InitAndSet( this, "textureArraySize", 1 );
m_nTextureType.Init( this, "textureType" );
m_flBumpScale.InitAndSet( this, "bumpScale", 1.0f );
m_flPFMScale.InitAndSet( this, "pfmScale", 1.0f );
m_nFilterType.Init( this, "filterType" );
m_bClampS.Init( this, "clamps" );
m_bClampT.Init( this, "clampt" );
m_bClampU.Init( this, "clampu" );
m_bLoadMipLevels.Init( this, "loadMipLevels" );
m_bBorder.Init( this, "border" );
m_bNormalMap.Init( this, "normalMap" );
m_bSSBump.Init( this, "ssBump" );
m_bNoMip.Init( this, "noMip" );
m_bAllMips.Init( this, "allMips" );
m_bNoLod.Init( this, "noLod" );
m_bNoDebugOverride.Init( this, "noDebugOverride" );
m_bNoCompression.Init( this, "noCompression" );
m_bHintDxt5Compression.Init( this, "hintDxt5Compression" );
}
void CDmePrecompiledTexture::OnDestruction()
{
}
//-----------------------------------------------------------------------------
// Ensures all settings are internally consistent
//-----------------------------------------------------------------------------
bool CDmePrecompiledTexture::ValidateValues()
{
if ( ( m_nTextureType == DMETEXTURE_TYPE_CUBEMAP ) && ( m_nTextureArraySize != 1 ) )
{
// Cubemaps are packed into a single texture in a cross shape
Warning( "Specified a cubemap with a texture array size != 1!\n" );
return false;
}
if ( ( m_nVolumeTextureDepth > 1 ) && ( m_nTextureArraySize != 1 ) )
{
Warning( "Specified a volume texture with a texture array size != 1!\n" );
return false;
}
if ( m_bLoadMipLevels )
{
char pBaseName[MAX_PATH];
Q_FileBase( GetName(), pBaseName, sizeof( pBaseName ) );
char pRight[16];
V_StrRight( pBaseName, 5, pRight, sizeof( pRight ) );
if ( !Q_stristr( pRight, "_mip0" ) )
{
Warning( "Invalid texture name (\"%s\") for explicitly loading mip levels - the top mip file should end in '_mip0'\n", GetName() );
}
}
return true;
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT( CDmeTextureProcessor );
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
void CDmeTextureProcessor::OnConstruction()
{
}
void CDmeTextureProcessor::OnDestruction()
{
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeTP_ComputeMipmaps, CDmeTP_ComputeMipmaps );
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
void CDmeTP_ComputeMipmaps::OnConstruction()
{
m_bNoNiceFiltering.Init( this, "noNiceFiltering" );
m_bAlphaTestDownsampling.Init( this, "alphaTestDownsampling" );
m_flAlphaTestDownsampleThreshhold.Init( this, "alphaTestDownsampleThreshhold" );
m_flAlphaTestDownsampleHiFreqThreshhold.Init( this, "alphaTestDownsampleHiFreqThreshhold" );
}
void CDmeTP_ComputeMipmaps::OnDestruction()
{
}
void CDmeTP_ComputeMipmaps::ProcessTexture( CDmeTexture *pSrcTexture, CDmeTexture *pDstTexture )
{
int nWidth = pSrcTexture->Width();
int nHeight = pSrcTexture->Height();
int nDepth = pSrcTexture->Depth();
int nTotalMipCount = ImageLoader::GetNumMipMapLevels( nWidth, nHeight, nDepth );
pSrcTexture->CopyAttributesTo( pDstTexture, TD_NONE );
// Copying will copy references to src texture frames. Remove them.
pDstTexture->RemoveAllFrames();
DownsampleInfo_t info;
info.m_flAlphaThreshhold = m_flAlphaTestDownsampleThreshhold;
info.m_flAlphaHiFreqThreshhold = m_flAlphaTestDownsampleHiFreqThreshhold;
info.m_nFlags = 0;
if ( pSrcTexture->m_bClampS )
{
info.m_nFlags |= DOWNSAMPLE_CLAMPS;
}
if ( pSrcTexture->m_bClampT )
{
info.m_nFlags |= DOWNSAMPLE_CLAMPT;
}
if ( pSrcTexture->m_bClampU )
{
info.m_nFlags |= DOWNSAMPLE_CLAMPU;
}
if ( m_bAlphaTestDownsampling )
{
info.m_nFlags |= DOWNSAMPLE_ALPHATEST;
}
int nFrameCount = pSrcTexture->FrameCount();
CDmeImage **ppSrcImages = (CDmeImage**)stackalloc( nTotalMipCount * sizeof(CDmeImage*) );
CDmeImage **ppDstImages = (CDmeImage**)stackalloc( nTotalMipCount * sizeof(CDmeImage*) );
for ( int f = 0; f < nFrameCount; ++f )
{
CDmeTextureFrame *pSrcFrame = pSrcTexture->GetFrame( f );
CDmeTextureFrame *pDstFrame = pDstTexture->AddFrame();
// Add mip level 0 for this frame
CDmeImageArray *pSrcArray = pSrcFrame->GetMipLevel( 0 );
if ( !pSrcArray )
continue;
for ( int m = 0; m < nTotalMipCount; ++m )
{
pDstFrame->AddMipLevel();
}
int nImageCount = pSrcFrame->ImageCount();
for ( int i = 0; i < nImageCount; ++i )
{
pSrcTexture->GetImages( f, i, ppSrcImages, nTotalMipCount );
CDmeImage *pSrcImage = ppSrcImages[0];
if ( !pSrcImage )
continue;
int nMipWidth = nWidth;
int nMipHeight = nHeight;
int nMipDepth = nDepth;
for ( int m = 0; m < nTotalMipCount; ++m )
{
CDmeImageArray *pDstArray = pDstFrame->GetMipLevel( m );
CDmeImage *pSrcImage = ppSrcImages[m];
CDmeImage *pDstImage = pDstArray->AddImage();
ppDstImages[m] = pDstImage;
if ( pSrcImage )
{
Assert( pSrcImage->Width() == nMipWidth );
Assert( pSrcImage->Height() == nMipHeight );
Assert( pSrcImage->Depth() == nMipDepth );
// FIXME: Just assign the src image into the dest texture
// and remove it from the src texture
// For mips where we have data, just copy src -> dest.
pDstImage->CopyFrom( pSrcImage );
}
else
{
// For mips where don't have data, generate a mip from the src data of the previous level
Assert( m != 0 && ppDstImages[m-1] );
if ( m_bNoNiceFiltering )
{
pDstImage->QuarterSize( ppDstImages[m-1] );
}
else
{
int nSrcMip = clamp( m-3, 0, nTotalMipCount );
pDstImage->Init( nMipWidth, nMipHeight, nMipDepth, ppDstImages[nSrcMip]->Format(), ppDstImages[nSrcMip]->Gamma() );
pDstImage->DownsampleNiceFiltered( info, ppDstImages[nSrcMip] );
}
}
nMipWidth >>= 1; nMipHeight >>= 1; nMipDepth >>= 1;
nMipWidth = MAX( 1, nMipWidth ); nMipHeight = MAX( 1, nMipHeight ); nMipDepth = MAX( 1, nMipDepth );
}
}
}
}
//-----------------------------------------------------------------------------
// Expose this class to the scene database
//-----------------------------------------------------------------------------
IMPLEMENT_ELEMENT_FACTORY( DmeTP_ChangeColorChannels, CDmeTP_ChangeColorChannels );
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
void CDmeTP_ChangeColorChannels::OnConstruction()
{
m_nMaxChannels.Init( this, "maxChannels" );
}
void CDmeTP_ChangeColorChannels::OnDestruction()
{
}
static ImageFormat ComputeDestFormat( ImageFormat fmt, int nChannelCount )
{
switch( fmt )
{
case IMAGE_FORMAT_RGBA8888:
case IMAGE_FORMAT_ABGR8888:
case IMAGE_FORMAT_ARGB8888:
case IMAGE_FORMAT_BGRA8888:
Assert( nChannelCount != 2 );
return ( nChannelCount == 3 ) ? IMAGE_FORMAT_RGB888 : IMAGE_FORMAT_I8;
case IMAGE_FORMAT_RGB888:
case IMAGE_FORMAT_BGR888:
case IMAGE_FORMAT_BGRX8888:
case IMAGE_FORMAT_RGBX8888:
Assert( nChannelCount == 1 );
return IMAGE_FORMAT_I8;
case IMAGE_FORMAT_IA88:
Assert( nChannelCount == 1 );
return IMAGE_FORMAT_I8;
case IMAGE_FORMAT_DXT5:
Assert( nChannelCount == 3 );
return IMAGE_FORMAT_DXT1;
case IMAGE_FORMAT_RGBA32323232F:
if ( nChannelCount == 3 )
return IMAGE_FORMAT_RGB323232F;
// fall through
case IMAGE_FORMAT_RGB323232F:
if ( nChannelCount == 2 )
return IMAGE_FORMAT_RG3232F;
// fall through
case IMAGE_FORMAT_RG3232F:
Assert( nChannelCount == 1 );
return IMAGE_FORMAT_R32F;
case IMAGE_FORMAT_RGBA16161616F:
Assert( nChannelCount != 3 );
if ( nChannelCount == 2 )
return IMAGE_FORMAT_RG1616F;
// fall through
case IMAGE_FORMAT_RG1616F:
Assert( nChannelCount == 1 );
return IMAGE_FORMAT_R16F;
default:
Assert( 0 );
break;
}
return fmt;
}
void CDmeTP_ChangeColorChannels::ProcessImage( CDmeImage *pDstImage, CDmeImage *pSrcImage )
{
ImageFormat fmt = pSrcImage->Format();
ImageFormat dstFmt = fmt;
const ImageFormatInfo_t &info = ImageLoader::ImageFormatInfo( fmt );
int nChannelCount = 0;
if ( info.m_nNumRedBits > 0 ) ++nChannelCount;
if ( info.m_nNumGreenBits > 0 ) ++nChannelCount;
if ( info.m_nNumBlueBits > 0 ) ++nChannelCount;
if ( info.m_nNumAlphaBits > 0 ) ++nChannelCount;
if ( nChannelCount > m_nMaxChannels )
{
dstFmt = ComputeDestFormat( fmt, m_nMaxChannels );
}
pDstImage->CopyFrom( pSrcImage, dstFmt );
}
void CDmeTP_ChangeColorChannels::ProcessTexture( CDmeTexture *pSrcTexture, CDmeTexture *pDstTexture )
{
pDstTexture->ProcessTexture( pSrcTexture, this, &CDmeTP_ChangeColorChannels::ProcessImage );
}
/*
class CDmeTP_OneOverMipLevelInAlpha : public CDmeTextureProcessor
{
DEFINE_ELEMENT( CDmeTP_OneOverMipLevelInAlpha, CDmeTextureProcessor );
public:
};
IMPLEMENT_ELEMENT_FACTORY( DmeTP_OneOverMipLevelInAlpha, CDmeTP_OneOverMipLevelInAlpha );
class CDmeTP_PreMultiplyColorByOneOverMipLevel : public CDmeTextureProcessor
{
DEFINE_ELEMENT( CDmeTP_PreMultiplyColorByOneOverMipLevel, CDmeTextureProcessor );
public:
};
IMPLEMENT_ELEMENT_FACTORY( DmeTP_PreMultiplyColorByOneOverMipLevel, CDmeTP_PreMultiplyColorByOneOverMipLevel );
class CDmeTP_NormalToDuDv : public CDmeTextureProcessor
{
DEFINE_ELEMENT( CDmeTP_NormalToDuDv, CDmeTextureProcessor );
public:
};
IMPLEMENT_ELEMENT_FACTORY( DmeTP_NormalToDuDv, CDmeTP_NormalToDuDv );
class CDmeTP_CompressTexture : public CDmeTextureProcessor
{
DEFINE_ELEMENT( CDmeTP_CompressTexture, CDmeTextureProcessor );
public:
CDmaVar< bool > m_bNormalGAMap;
CDmaVar< bool > m_bDXT5; // FIXME: Should nocompress/dxt5 be combined?
CDmaVar< bool > m_bNoCompress;
};
IMPLEMENT_ELEMENT_FACTORY( DmeTP_CompressTexture, CDmeTP_CompressTexture );
class CDmeTP_GenerateMipmaps : public CDmeTextureProcessor
{
DEFINE_ELEMENT( CDmeTP_GenerateMipmaps, CDmeTextureProcessor );
public:
CDmaVar< bool > m_bNoNice;
CDmaVar< bool > m_bAlphaTest;
CDmaVar< float > m_flAlphaThreshhold;
CDmaVar< float > m_flAlphaThreshholdHigh;
};
IMPLEMENT_ELEMENT_FACTORY( DmeTP_GenerateMipmaps, CDmeTP_GenerateMipmaps );
*/