2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
# include "platform/platform.h"
# include "materials/processedMaterial.h"
# include "materials/sceneData.h"
# include "materials/materialParameters.h"
# include "materials/matTextureTarget.h"
# include "materials/materialFeatureTypes.h"
# include "materials/materialManager.h"
# include "scene/sceneRenderState.h"
# include "gfx/gfxPrimitiveBuffer.h"
2013-01-30 19:09:22 +00:00
# include "gfx/gfxTextureManager.h"
2012-09-19 15:15:01 +00:00
# include "gfx/sim/cubemapData.h"
RenderPassData : : RenderPassData ( )
{
reset ( ) ;
}
void RenderPassData : : reset ( )
{
for ( U32 i = 0 ; i < Material : : MAX_TEX_PER_PASS ; + + i )
2014-04-17 15:36:29 +00:00
{
2012-09-19 15:15:01 +00:00
destructInPlace ( & mTexSlot [ i ] ) ;
2014-04-17 15:36:29 +00:00
mSamplerNames [ i ] . clear ( ) ;
}
2012-09-19 15:15:01 +00:00
dMemset ( & mTexSlot , 0 , sizeof ( mTexSlot ) ) ;
dMemset ( & mTexType , 0 , sizeof ( mTexType ) ) ;
mCubeMap = NULL ;
mNumTex = mNumTexReg = mStageNum = 0 ;
mGlow = false ;
mBlendOp = Material : : None ;
mFeatureData . clear ( ) ;
for ( U32 i = 0 ; i < STATE_MAX ; i + + )
mRenderStates [ i ] = NULL ;
}
String RenderPassData : : describeSelf ( ) const
{
String desc ;
// Now write all the textures.
String texName ;
for ( U32 i = 0 ; i < Material : : MAX_TEX_PER_PASS ; i + + )
{
if ( mTexType [ i ] = = Material : : TexTarget )
texName = ( mTexSlot [ i ] . texTarget ) ? mTexSlot [ i ] . texTarget - > getName ( ) : " null_texTarget " ;
else if ( mTexType [ i ] = = Material : : Cube & & mCubeMap )
texName = mCubeMap - > getPath ( ) ;
else if ( mTexSlot [ i ] . texObject )
texName = mTexSlot [ i ] . texObject - > getPath ( ) ;
else
continue ;
desc + = String : : ToString ( " TexSlot %d: %d, %s \n " , i , mTexType [ i ] , texName . c_str ( ) ) ;
}
// Write out the first render state which is the
// basis for all the other states and shoud be
// enough to define the pass uniquely.
desc + = mRenderStates [ 0 ] - > getDesc ( ) . describeSelf ( ) ;
return desc ;
}
ProcessedMaterial : : ProcessedMaterial ( )
: mMaterial ( NULL ) ,
mCurrentParams ( NULL ) ,
mHasSetStageData ( false ) ,
mHasGlow ( false ) ,
2014-12-21 20:07:42 +00:00
mHasAccumulation ( false ) ,
2012-09-19 15:15:01 +00:00
mMaxStages ( 0 ) ,
mVertexFormat ( NULL ) ,
mUserObject ( NULL )
{
VECTOR_SET_ASSOCIATION ( mPasses ) ;
}
ProcessedMaterial : : ~ ProcessedMaterial ( )
{
2017-12-19 22:04:46 +00:00
T3D : : for_each ( mPasses . begin ( ) , mPasses . end ( ) , T3D : : delete_pointer ( ) ) ;
2012-09-19 15:15:01 +00:00
}
void ProcessedMaterial : : _setBlendState ( Material : : BlendOp blendOp , GFXStateBlockDesc & desc )
{
switch ( blendOp )
{
case Material : : Add :
{
desc . blendSrc = GFXBlendOne ;
desc . blendDest = GFXBlendOne ;
break ;
}
case Material : : AddAlpha :
{
desc . blendSrc = GFXBlendSrcAlpha ;
desc . blendDest = GFXBlendOne ;
break ;
}
case Material : : Mul :
{
desc . blendSrc = GFXBlendDestColor ;
2018-09-16 01:19:57 +00:00
desc . blendDest = GFXBlendInvSrcAlpha ;
2012-09-19 15:15:01 +00:00
break ;
}
2019-11-22 16:02:01 +00:00
case Material : : PreMul :
{
desc . blendSrc = GFXBlendOne ;
desc . blendDest = GFXBlendInvSrcAlpha ;
break ;
}
2012-09-19 15:15:01 +00:00
case Material : : LerpAlpha :
{
desc . blendSrc = GFXBlendSrcAlpha ;
desc . blendDest = GFXBlendInvSrcAlpha ;
break ;
}
2019-11-19 07:25:24 +00:00
case Material : : Sub :
{
desc . blendOp = GFXBlendOpSubtract ;
desc . blendSrc = GFXBlendOne ;
desc . blendDest = GFXBlendOne ;
break ;
}
2012-09-19 15:15:01 +00:00
default :
{
// default to LerpAlpha
desc . blendSrc = GFXBlendSrcAlpha ;
desc . blendDest = GFXBlendInvSrcAlpha ;
break ;
}
}
}
void ProcessedMaterial : : setBuffers ( GFXVertexBufferHandleBase * vertBuffer , GFXPrimitiveBufferHandle * primBuffer )
{
GFX - > setVertexBuffer ( * vertBuffer ) ;
GFX - > setPrimitiveBuffer ( * primBuffer ) ;
}
bool ProcessedMaterial : : stepInstance ( )
{
AssertFatal ( false , " ProcessedMaterial::stepInstance() - This type of material doesn't support instancing! " ) ;
return false ;
}
String ProcessedMaterial : : _getTexturePath ( const String & filename )
{
// if '/', then path is specified, use it.
if ( filename . find ( ' / ' ) ! = String : : NPos )
{
return filename ;
}
// otherwise, construct path
return mMaterial - > getPath ( ) + filename ;
}
GFXTexHandle ProcessedMaterial : : _createTexture ( const char * filename , GFXTextureProfile * profile )
{
return GFXTexHandle ( _getTexturePath ( filename ) , profile , avar ( " %s() - NA (line %d) " , __FUNCTION__ , __LINE__ ) ) ;
}
2018-09-16 01:19:57 +00:00
GFXTexHandle ProcessedMaterial : : _createCompositeTexture ( const char * filenameR , const char * filenameG , const char * filenameB , const char * filenameA , U32 inputKey [ 4 ] , GFXTextureProfile * profile )
{
return GFXTexHandle ( _getTexturePath ( filenameR ) , _getTexturePath ( filenameG ) , _getTexturePath ( filenameB ) , _getTexturePath ( filenameA ) , inputKey , profile , avar ( " %s() - NA (line %d) " , __FUNCTION__ , __LINE__ ) ) ;
}
2012-09-19 15:15:01 +00:00
void ProcessedMaterial : : addStateBlockDesc ( const GFXStateBlockDesc & sb )
{
mUserDefined = sb ;
}
void ProcessedMaterial : : _initStateBlockTemplates ( GFXStateBlockDesc & stateTranslucent , GFXStateBlockDesc & stateGlow , GFXStateBlockDesc & stateReflect )
{
// Translucency
stateTranslucent . blendDefined = true ;
stateTranslucent . blendEnable = mMaterial - > mTranslucentBlendOp ! = Material : : None ;
_setBlendState ( mMaterial - > mTranslucentBlendOp , stateTranslucent ) ;
stateTranslucent . zDefined = true ;
stateTranslucent . zWriteEnable = mMaterial - > mTranslucentZWrite ;
stateTranslucent . alphaDefined = true ;
stateTranslucent . alphaTestEnable = mMaterial - > mAlphaTest ;
stateTranslucent . alphaTestRef = mMaterial - > mAlphaRef ;
stateTranslucent . alphaTestFunc = GFXCmpGreaterEqual ;
stateTranslucent . samplersDefined = true ;
// Glow
stateGlow . zDefined = true ;
stateGlow . zWriteEnable = false ;
// Reflect
stateReflect . cullDefined = true ;
stateReflect . cullMode = mMaterial - > mDoubleSided ? GFXCullNone : GFXCullCW ;
}
void ProcessedMaterial : : _initRenderPassDataStateBlocks ( )
{
for ( U32 pass = 0 ; pass < mPasses . size ( ) ; pass + + )
_initRenderStateStateBlocks ( mPasses [ pass ] ) ;
}
void ProcessedMaterial : : _initPassStateBlock ( RenderPassData * rpd , GFXStateBlockDesc & result )
{
if ( rpd - > mBlendOp ! = Material : : None )
{
result . blendDefined = true ;
result . blendEnable = true ;
_setBlendState ( rpd - > mBlendOp , result ) ;
}
2013-06-30 15:47:43 +00:00
if ( mMaterial & & mMaterial - > isDoubleSided ( ) )
2012-09-19 15:15:01 +00:00
{
result . cullDefined = true ;
result . cullMode = GFXCullNone ;
}
2013-06-30 15:47:43 +00:00
if ( mMaterial & & mMaterial - > mAlphaTest )
2012-09-19 15:15:01 +00:00
{
result . alphaDefined = true ;
result . alphaTestEnable = mMaterial - > mAlphaTest ;
result . alphaTestRef = mMaterial - > mAlphaRef ;
result . alphaTestFunc = GFXCmpGreaterEqual ;
}
result . samplersDefined = true ;
NamedTexTarget * texTarget ;
U32 maxAnisotropy = 1 ;
2013-06-30 15:47:43 +00:00
if ( mMaterial & & mMaterial - > mUseAnisotropic [ rpd - > mStageNum ] )
2012-09-19 15:15:01 +00:00
maxAnisotropy = MATMGR - > getDefaultAnisotropy ( ) ;
for ( U32 i = 0 ; i < rpd - > mNumTex ; i + + )
{
U32 currTexFlag = rpd - > mTexType [ i ] ;
switch ( currTexFlag )
{
default :
{
result . samplers [ i ] . addressModeU = GFXAddressWrap ;
result . samplers [ i ] . addressModeV = GFXAddressWrap ;
if ( maxAnisotropy > 1 )
{
result . samplers [ i ] . minFilter = GFXTextureFilterAnisotropic ;
result . samplers [ i ] . magFilter = GFXTextureFilterAnisotropic ;
result . samplers [ i ] . maxAnisotropy = maxAnisotropy ;
}
else
{
result . samplers [ i ] . minFilter = GFXTextureFilterLinear ;
result . samplers [ i ] . magFilter = GFXTextureFilterLinear ;
}
break ;
}
case Material : : Cube :
case Material : : SGCube :
case Material : : NormalizeCube :
{
result . samplers [ i ] . addressModeU = GFXAddressClamp ;
result . samplers [ i ] . addressModeV = GFXAddressClamp ;
result . samplers [ i ] . addressModeW = GFXAddressClamp ;
2017-06-23 16:36:20 +00:00
result . samplers [ i ] . minFilter = GFXTextureFilterLinear ;
result . samplers [ i ] . magFilter = GFXTextureFilterLinear ;
2012-09-19 15:15:01 +00:00
break ;
}
case Material : : TexTarget :
{
texTarget = mPasses [ 0 ] - > mTexSlot [ i ] . texTarget ;
if ( texTarget )
texTarget - > setupSamplerState ( & result . samplers [ i ] ) ;
break ;
}
}
}
2017-04-11 05:23:14 +00:00
// The deferred will take care of writing to the
2012-09-19 15:15:01 +00:00
// zbuffer, so we don't have to by default.
2017-04-11 05:23:14 +00:00
if ( MATMGR - > getDeferredEnabled ( ) & &
2012-09-19 15:15:01 +00:00
! mFeatures . hasFeature ( MFT_ForwardShading ) )
result . setZReadWrite ( result . zEnable , false ) ;
result . addDesc ( mUserDefined ) ;
}
/// Creates the default state blocks for a list of render states
void ProcessedMaterial : : _initRenderStateStateBlocks ( RenderPassData * rpd )
{
GFXStateBlockDesc stateTranslucent ;
GFXStateBlockDesc stateGlow ;
GFXStateBlockDesc stateReflect ;
GFXStateBlockDesc statePass ;
_initStateBlockTemplates ( stateTranslucent , stateGlow , stateReflect ) ;
_initPassStateBlock ( rpd , statePass ) ;
// Ok, we've got our templates set up, let's combine them together based on state and
// create our state blocks.
for ( U32 i = 0 ; i < RenderPassData : : STATE_MAX ; i + + )
{
GFXStateBlockDesc stateFinal ;
if ( i & RenderPassData : : STATE_REFLECT )
stateFinal . addDesc ( stateReflect ) ;
if ( i & RenderPassData : : STATE_TRANSLUCENT )
stateFinal . addDesc ( stateTranslucent ) ;
if ( i & RenderPassData : : STATE_GLOW )
stateFinal . addDesc ( stateGlow ) ;
stateFinal . addDesc ( statePass ) ;
if ( i & RenderPassData : : STATE_WIREFRAME )
stateFinal . fillMode = GFXFillWireframe ;
GFXStateBlockRef sb = GFX - > createStateBlock ( stateFinal ) ;
rpd - > mRenderStates [ i ] = sb ;
}
}
U32 ProcessedMaterial : : _getRenderStateIndex ( const SceneRenderState * sceneState ,
const SceneData & sgData )
{
// Based on what the state of the world is, get our render state block
U32 currState = 0 ;
// NOTE: We should only use per-material or per-pass hints to
// change the render state. This is importaint because we
// only change the state blocks between material passes.
//
// For example sgData.visibility would be bad to use
// in here without changing how RenderMeshMgr works.
if ( sgData . binType = = SceneData : : GlowBin )
currState | = RenderPassData : : STATE_GLOW ;
if ( sceneState & & sceneState - > isReflectPass ( ) )
currState | = RenderPassData : : STATE_REFLECT ;
2017-04-11 05:23:14 +00:00
if ( sgData . binType ! = SceneData : : DeferredBin & &
2012-09-19 15:15:01 +00:00
mMaterial - > isTranslucent ( ) )
currState | = RenderPassData : : STATE_TRANSLUCENT ;
if ( sgData . wireframe )
currState | = RenderPassData : : STATE_WIREFRAME ;
return currState ;
}
void ProcessedMaterial : : _setRenderState ( const SceneRenderState * state ,
const SceneData & sgData ,
U32 pass )
{
// Make sure we have the pass
if ( pass > = mPasses . size ( ) )
return ;
U32 currState = _getRenderStateIndex ( state , sgData ) ;
GFX - > setStateBlock ( mPasses [ pass ] - > mRenderStates [ currState ] ) ;
}
void ProcessedMaterial : : _setStageData ( )
{
// Only do this once
2018-09-16 01:19:57 +00:00
if ( mHasSetStageData )
2012-09-19 15:15:01 +00:00
return ;
mHasSetStageData = true ;
U32 i ;
// Load up all the textures for every possible stage
2018-09-16 01:19:57 +00:00
for ( i = 0 ; i < Material : : MAX_STAGES ; i + + )
2012-09-19 15:15:01 +00:00
{
// DiffuseMap
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mDiffuseMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_DiffuseMap , _createTexture ( mMaterial - > mDiffuseMapFilename [ i ] , & GFXStaticTextureSRGBProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_DiffuseMap ) )
2012-09-19 15:15:01 +00:00
{
2016-07-07 05:52:57 +00:00
//If we start with a #, we're probably actually attempting to hit a named target and it may not get a hit on the first pass. So we'll
//pass on the error rather than spamming the console
if ( ! mMaterial - > mDiffuseMapFilename [ i ] . startsWith ( " # " ) )
mMaterial - > logError ( " Failed to load diffuse map %s for stage %i " , _getTexturePath ( mMaterial - > mDiffuseMapFilename [ i ] ) . c_str ( ) , i ) ;
2018-09-16 01:19:57 +00:00
2012-09-19 15:15:01 +00:00
// Load a debug texture to make it clear to the user
// that the texture for this stage was missing.
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_DiffuseMap , _createTexture ( GFXTextureManager : : getMissingTexturePath ( ) . c_str ( ) , & GFXStaticTextureSRGBProfile ) ) ;
2012-09-19 15:15:01 +00:00
}
}
2019-06-03 07:47:30 +00:00
else if ( mMaterial - > mDiffuseMapAsset [ i ] & & ! mMaterial - > mDiffuseMapAsset [ i ] . isNull ( ) )
2019-05-28 22:24:29 +00:00
{
2020-03-19 14:47:38 +00:00
mStages [ i ] . setTex ( MFT_DiffuseMap , mMaterial - > mDiffuseMapAsset [ i ] - > getImage ( GFXStaticTextureSRGBProfile ) ) ;
2019-05-28 22:24:29 +00:00
if ( ! mStages [ i ] . getTex ( MFT_DiffuseMap ) )
{
// Load a debug texture to make it clear to the user
// that the texture for this stage was missing.
mStages [ i ] . setTex ( MFT_DiffuseMap , _createTexture ( GFXTextureManager : : getMissingTexturePath ( ) . c_str ( ) , & GFXStaticTextureSRGBProfile ) ) ;
}
}
2012-09-19 15:15:01 +00:00
// OverlayMap
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mOverlayMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_OverlayMap , _createTexture ( mMaterial - > mOverlayMapFilename [ i ] , & GFXStaticTextureSRGBProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_OverlayMap ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load overlay map %s for stage %i " , _getTexturePath ( mMaterial - > mOverlayMapFilename [ i ] ) . c_str ( ) , i ) ;
}
// LightMap
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mLightMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_LightMap , _createTexture ( mMaterial - > mLightMapFilename [ i ] , & GFXStaticTextureSRGBProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_LightMap ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load light map %s for stage %i " , _getTexturePath ( mMaterial - > mLightMapFilename [ i ] ) . c_str ( ) , i ) ;
}
// ToneMap
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mToneMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_ToneMap , _createTexture ( mMaterial - > mToneMapFilename [ i ] , & GFXStaticTextureProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_ToneMap ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load tone map %s for stage %i " , _getTexturePath ( mMaterial - > mToneMapFilename [ i ] ) . c_str ( ) , i ) ;
}
// DetailMap
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mDetailMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_DetailMap , _createTexture ( mMaterial - > mDetailMapFilename [ i ] , & GFXStaticTextureProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_DetailMap ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load detail map %s for stage %i " , _getTexturePath ( mMaterial - > mDetailMapFilename [ i ] ) . c_str ( ) , i ) ;
}
// NormalMap
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mNormalMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_NormalMap , _createTexture ( mMaterial - > mNormalMapFilename [ i ] , & GFXNormalMapProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_NormalMap ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load normal map %s for stage %i " , _getTexturePath ( mMaterial - > mNormalMapFilename [ i ] ) . c_str ( ) , i ) ;
}
// Detail Normal Map
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mDetailNormalMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2018-09-16 01:19:57 +00:00
mStages [ i ] . setTex ( MFT_DetailNormalMap , _createTexture ( mMaterial - > mDetailNormalMapFilename [ i ] , & GFXNormalMapProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_DetailNormalMap ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load normal map %s for stage %i " , _getTexturePath ( mMaterial - > mDetailNormalMapFilename [ i ] ) . c_str ( ) , i ) ;
}
2018-09-16 01:19:57 +00:00
GFXTextureProfile * profile = & GFXStaticTextureProfile ;
if ( mMaterial - > mIsSRGb [ i ] )
profile = & GFXStaticTextureSRGBProfile ;
2020-09-30 18:51:12 +00:00
// ORMConfig
if ( mMaterial - > mORMConfigMapFilename [ i ] . isNotEmpty ( ) )
2012-09-19 15:15:01 +00:00
{
2020-09-30 18:51:12 +00:00
mStages [ i ] . setTex ( MFT_OrmMap , _createTexture ( mMaterial - > mORMConfigMapFilename [ i ] , profile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_OrmMap ) )
mMaterial - > logError ( " Failed to load PBR Config map %s for stage %i " , _getTexturePath ( mMaterial - > mORMConfigMapFilename [ i ] ) . c_str ( ) , i ) ;
2012-09-19 15:15:01 +00:00
}
2018-09-16 01:19:57 +00:00
else
{
if ( mMaterial - > mRoughMapFilename [ i ] . isNotEmpty ( ) & & mMaterial - > mMetalMapFilename [ i ] . isNotEmpty ( ) )
{
U32 inputKey [ 4 ] ;
2020-09-30 18:51:12 +00:00
inputKey [ 0 ] = mMaterial - > mAOChan [ i ] ;
inputKey [ 1 ] = mMaterial - > mRoughnessChan [ i ] ;
2018-09-16 01:19:57 +00:00
inputKey [ 2 ] = mMaterial - > mMetalChan [ i ] ;
2019-11-02 00:29:31 +00:00
inputKey [ 3 ] = 0 ;
2020-09-30 18:51:12 +00:00
mStages [ i ] . setTex ( MFT_OrmMap , _createCompositeTexture ( mMaterial - > mAOMapFilename [ i ] , mMaterial - > mRoughMapFilename [ i ] ,
2018-09-16 01:19:57 +00:00
mMaterial - > mMetalMapFilename [ i ] , " " ,
inputKey , profile ) ) ;
2020-09-30 18:51:12 +00:00
if ( ! mStages [ i ] . getTex ( MFT_OrmMap ) )
mMaterial - > logError ( " Failed to load PBR Config map %s for stage %i " , _getTexturePath ( mMaterial - > mORMConfigMapFilename [ i ] ) . c_str ( ) , i ) ;
2018-09-16 01:19:57 +00:00
}
}
2019-11-02 00:29:31 +00:00
if ( mMaterial - > mGlowMapFilename [ i ] . isNotEmpty ( ) )
{
mStages [ i ] . setTex ( MFT_GlowMap , _createTexture ( mMaterial - > mGlowMapFilename [ i ] , & GFXStaticTextureProfile ) ) ;
if ( ! mStages [ i ] . getTex ( MFT_GlowMap ) )
mMaterial - > logError ( " Failed to load glow map %s for stage %i " , _getTexturePath ( mMaterial - > mGlowMapFilename [ i ] ) . c_str ( ) , i ) ;
}
2012-09-19 15:15:01 +00:00
}
2018-09-16 01:19:57 +00:00
mMaterial - > mCubemapData = dynamic_cast < CubemapData * > ( Sim : : findObject ( mMaterial - > mCubemapName ) ) ;
if ( ! mMaterial - > mCubemapData )
mMaterial - > mCubemapData = NULL ;
2012-09-19 15:15:01 +00:00
// If we have a cubemap put it on stage 0 (cubemaps only supported on stage 0)
2018-09-16 01:19:57 +00:00
if ( mMaterial - > mCubemapData )
2012-09-19 15:15:01 +00:00
{
mMaterial - > mCubemapData - > createMap ( ) ;
2018-09-16 01:19:57 +00:00
mStages [ 0 ] . setCubemap ( mMaterial - > mCubemapData - > mCubemap ) ;
if ( ! mStages [ 0 ] . getCubemap ( ) )
2012-09-19 15:15:01 +00:00
mMaterial - > logError ( " Failed to load cubemap " ) ;
}
}