Engine directory for ticket #1

This commit is contained in:
DavidWyand-GG 2012-09-19 11:15:01 -04:00
parent 352279af7a
commit 7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions

View file

@ -0,0 +1,80 @@
//-----------------------------------------------------------------------------
// 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/baseMatInstance.h"
#include "core/util/safeDelete.h"
BaseMatInstance::~BaseMatInstance()
{
deleteAllHooks();
}
void BaseMatInstance::addHook( MatInstanceHook *hook )
{
AssertFatal( hook, "BaseMatInstance::addHook() - Got null hook!" );
const MatInstanceHookType &type = hook->getType();
while ( mHooks.size() <= type )
mHooks.push_back( NULL );
delete mHooks[type];
mHooks[type] = hook;
}
MatInstanceHook* BaseMatInstance::getHook( const MatInstanceHookType &type ) const
{
if ( type >= mHooks.size() )
return NULL;
return mHooks[ type ];
}
void BaseMatInstance::deleteHook( const MatInstanceHookType &type )
{
if ( type >= mHooks.size() )
return;
delete mHooks[ type ];
mHooks[ type ] = NULL;
}
U32 BaseMatInstance::deleteAllHooks()
{
U32 deleteCount = 0;
Vector<MatInstanceHook*>::iterator iter = mHooks.begin();
for ( ; iter != mHooks.end(); iter++ )
{
if ( *iter )
{
delete (*iter);
(*iter) = NULL;
++deleteCount;
}
}
return deleteCount;
}

View file

@ -0,0 +1,254 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _BASEMATINSTANCE_H_
#define _BASEMATINSTANCE_H_
#ifndef _TSIGNAL_H_
#include "core/util/tSignal.h"
#endif
#ifndef _BASEMATERIALDEFINITION_H_
#include "materials/baseMaterialDefinition.h"
#endif
#ifndef _MATERIALPARAMETERS_H_
#include "materials/materialParameters.h"
#endif
#ifndef _MMATRIX_H_
#include "math/mMatrix.h"
#endif
#ifndef _GFXENUMS_H_
#include "gfx/gfxEnums.h"
#endif
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
#ifndef _MATERIALFEATUREDATA_H_
#include "materials/materialFeatureData.h"
#endif
#ifndef _MATINSTANCEHOOK_H_
#include "materials/matInstanceHook.h"
#endif
#ifndef _MATSTATEHINT_H_
#include "materials/matStateHint.h"
#endif
struct RenderPassData;
class GFXVertexBufferHandleBase;
class GFXPrimitiveBufferHandle;
struct SceneData;
class SceneRenderState;
struct GFXStateBlockDesc;
class GFXVertexFormat;
class MatrixSet;
class ProcessedMaterial;
///
class BaseMatInstance
{
protected:
/// The array of active material hooks indexed
/// by a MatInstanceHookType.
Vector<MatInstanceHook*> mHooks;
///
MatFeaturesDelegate mFeaturesDelegate;
/// Should be true if init has been called and it succeeded.
/// It is up to the derived class to set this variable appropriately.
bool mIsValid;
/// This is set by initialization and used by the prepass.
bool mHasNormalMaps;
public:
virtual ~BaseMatInstance();
/// @param features The features you want to allow for this material.
///
/// @param vertexFormat The vertex format on which this material will be rendered.
///
/// @see GFXVertexFormat
/// @see FeatureSet
virtual bool init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat ) = 0;
/// Reinitializes the material using the previous
/// initialization parameters.
/// @see init
virtual bool reInit() = 0;
/// Returns true if init has been successfully called.
/// It is up to the derived class to set this value properly.
bool isValid() { return mIsValid; }
/// Adds this stateblock to the base state block
/// used during initialization.
/// @see init
virtual void addStateBlockDesc(const GFXStateBlockDesc& desc) = 0;
/// Updates the state blocks for this material.
virtual void updateStateBlocks() = 0;
/// Adds a shader macro which will be passed to the shader
/// during initialization.
/// @see init
virtual void addShaderMacro( const String &name, const String &value ) = 0;
/// Get a MaterialParameters block for this BaseMatInstance,
/// caller is responsible for freeing it.
virtual MaterialParameters* allocMaterialParameters() = 0;
/// Set the current parameters for this BaseMatInstance
virtual void setMaterialParameters(MaterialParameters* param) = 0;
/// Get the current parameters for this BaseMatInstance (BaseMatInstances are created with a default active
/// MaterialParameters which is managed by BaseMatInstance.
virtual MaterialParameters* getMaterialParameters() = 0;
/// Returns a MaterialParameterHandle for name.
virtual MaterialParameterHandle* getMaterialParameterHandle(const String& name) = 0;
/// Sets up the next rendering pass for this material. It is
/// typically called like so...
///
///@code
/// while( mat->setupPass( state, sgData ) )
/// {
/// mat->setTransforms(...);
/// mat->setSceneInfo(...);
/// ...
/// GFX->drawPrimitive();
/// }
///@endcode
///
virtual bool setupPass( SceneRenderState *state, const SceneData &sgData ) = 0;
/// This initializes the material transforms and should be
/// called after setupPass() within the pass loop.
/// @see setupPass
virtual void setTransforms( const MatrixSet &matrixSet, SceneRenderState *state ) = 0;
/// This initializes various material scene state settings and
/// should be called after setupPass() within the pass loop.
/// @see setupPass
virtual void setSceneInfo( SceneRenderState *state, const SceneData &sgData ) = 0;
/// This is normally called from within setupPass() automatically, so its
/// unnecessary to do so manually unless a texture stage has changed. If
/// so it should be called after setupPass() within the pass loop.
/// @see setupPass
virtual void setTextureStages(SceneRenderState *, const SceneData &sgData ) = 0;
/// Sets the vertex and primitive buffers as well as the instancing
/// stream buffer for the current material if the material is instanced.
virtual void setBuffers( GFXVertexBufferHandleBase *vertBuffer, GFXPrimitiveBufferHandle *primBuffer ) = 0;
/// Returns true if this material is instanced.
virtual bool isInstanced() const = 0;
/// Used to increment the instance buffer for this material.
virtual bool stepInstance() = 0;
/// Returns true if the material is forward lit and requires
/// a list of lights which affect it when rendering.
virtual bool isForwardLit() const = 0;
/// Sets a SimObject which will passed into ShaderFeature::createConstHandles.
/// Normal features do not make use of this, it is for special class specific
/// or user designed features.
virtual void setUserObject( SimObject *userObject ) = 0;
virtual SimObject* getUserObject() const = 0;
/// Returns the material this instance is based on.
virtual BaseMaterialDefinition* getMaterial() = 0;
// BTRTODO: This stuff below should probably not be in BaseMatInstance
virtual bool hasGlow() = 0;
virtual U32 getCurPass() = 0;
virtual U32 getCurStageNum() = 0;
virtual RenderPassData *getPass(U32 pass) = 0;
/// Returns the state hint which can be used for
/// sorting and fast comparisions of the equality
/// of a material instance.
virtual const MatStateHint& getStateHint() const = 0;
/// Returns the active features in use by this material.
/// @see getRequestedFeatures
virtual const FeatureSet& getFeatures() const = 0;
/// Returns the features that were requested at material
/// creation time which may differ from the active features.
/// @see getFeatures
virtual const FeatureSet& getRequestedFeatures() const = 0;
virtual const GFXVertexFormat* getVertexFormat() const = 0;
virtual void dumpShaderInfo() const = 0;
/// Fast test for use of normal maps in this material.
bool hasNormalMap() const { return mHasNormalMaps; }
///
MatFeaturesDelegate& getFeaturesDelegate() { return mFeaturesDelegate; }
/// Returns true if this MatInstance is built from a CustomMaterial.
virtual bool isCustomMaterial() const = 0;
/// @name Material Hook functions
/// @{
///
void addHook( MatInstanceHook *hook );
/// Helper function for getting a hook.
/// @see getHook
template <class HOOK>
inline HOOK* getHook() { return (HOOK*)getHook( HOOK::Type ); }
///
MatInstanceHook* getHook( const MatInstanceHookType &type ) const;
///
void deleteHook( const MatInstanceHookType &type );
///
U32 deleteAllHooks();
/// @}
virtual const GFXStateBlockDesc &getUserStateBlock() const = 0;
};
#endif /// _BASEMATINSTANCE_H_

View file

@ -0,0 +1,42 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _BASEMATERIALDEFINITION_H_
#define _BASEMATERIALDEFINITION_H_
#ifndef _SIMOBJECT_H_
#include "console/simObject.h"
#endif
class BaseMatInstance;
class BaseMaterialDefinition : public SimObject
{
typedef SimObject Parent;
public:
virtual BaseMatInstance* createMatInstance() = 0;
virtual bool isTranslucent() const = 0;
virtual bool isDoubleSided() const = 0;
virtual bool isLightmapped() const = 0;
virtual bool castsShadows() const = 0;
};
#endif // _BASEMATERIALDEFINITION_H_

View file

@ -0,0 +1,179 @@
//-----------------------------------------------------------------------------
// 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/customMaterialDefinition.h"
#include "materials/materialManager.h"
#include "console/consoleTypes.h"
#include "materials/shaderData.h"
#include "gfx/sim/cubemapData.h"
#include "gfx/gfxCubemap.h"
#include "gfx/sim/gfxStateBlockData.h"
//****************************************************************************
// Custom Material
//****************************************************************************
IMPLEMENT_CONOBJECT(CustomMaterial);
ConsoleDocClass( CustomMaterial,
"@brief Material object which provides more control over surface properties.\n\n"
"CustomMaterials allow the user to specify their own shaders via the ShaderData datablock. "
"Because CustomMaterials are derived from Materials, they can hold a lot of the same properties. "
"It is up to the user to code how these properties are used.\n\n"
"@tsexample\n"
"singleton CustomMaterial( WaterBasicMat )\n"
"{\n"
" sampler[\"reflectMap\"] = \"$reflectbuff\";\n"
" sampler[\"refractBuff\"] = \"$backbuff\";\n\n"
" cubemap = NewLevelSkyCubemap;\n"
" shader = WaterBasicShader;\n"
" stateBlock = WaterBasicStateBlock;\n"
" version = 2.0;\n"
"};\n"
"@endtsexample\n\n"
"@see Material, GFXStateBlockData, ShaderData\n\n"
"@ingroup Materials\n"
);
//----------------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------------
CustomMaterial::CustomMaterial()
{
mFallback = NULL;
mMaxTex = 0;
mVersion = 1.1f;
mTranslucent = false;
dMemset( mFlags, 0, sizeof( mFlags ) );
mShaderData = NULL;
mRefract = false;
mStateBlockData = NULL;
mForwardLit = false;
}
//--------------------------------------------------------------------------
// Init fields
//--------------------------------------------------------------------------
void CustomMaterial::initPersistFields()
{
addField("version", TypeF32, Offset(mVersion, CustomMaterial),
"@brief Specifies pixel shader version for hardware.\n\n"
"Valid pixel shader versions include 2.0, 3.0, etc. "
"@note All features aren't compatible with all pixel shader versions.");
addField("fallback", TYPEID< Material >(), Offset(mFallback, CustomMaterial),
"@brief Alternate material for targeting lower end hardware.\n\n"
"If the CustomMaterial requires a higher pixel shader version than the one "
"it's using, it's fallback Material will be processed instead. "
"If the fallback material wasn't defined, Torque 3D will assert and attempt to use a very "
"basic material in it's place.\n\n");
addField("shader", TypeRealString, Offset(mShaderDataName, CustomMaterial),
"@brief Name of the ShaderData to use for this effect.\n\n");
addField("stateBlock", TYPEID< GFXStateBlockData >(), Offset(mStateBlockData, CustomMaterial),
"@brief Name of a GFXStateBlockData for this effect.\n\n");
addField("target", TypeRealString, Offset(mOutputTarget, CustomMaterial),
"@brief String identifier of this material's target texture.");
addField("forwardLit", TypeBool, Offset(mForwardLit, CustomMaterial),
"@brief Determines if the material should recieve lights in Basic Lighting. "
"Has no effect in Advanced Lighting.\n\n");
Parent::initPersistFields();
}
//--------------------------------------------------------------------------
// On add - verify data settings
//--------------------------------------------------------------------------
bool CustomMaterial::onAdd()
{
if (Parent::onAdd() == false)
return false;
mShaderData = dynamic_cast<ShaderData*>(Sim::findObject( mShaderDataName ) );
if(mShaderDataName.isNotEmpty() && mShaderData == NULL)
{
logError("Failed to find ShaderData %s", mShaderDataName.c_str());
return false;
}
const char* samplerDecl = "sampler";
S32 i = 0;
for (SimFieldDictionaryIterator itr(getFieldDictionary()); *itr; ++itr)
{
SimFieldDictionary::Entry* entry = *itr;
if (dStrStartsWith(entry->slotName, samplerDecl))
{
if (i >= MAX_TEX_PER_PASS)
{
logError("Too many sampler declarations, you may only have %i", MAX_TEX_PER_PASS);
return false;
}
if (dStrlen(entry->slotName) == dStrlen(samplerDecl))
{
logError("sampler declarations must have a sampler name, e.g. sampler[\"diffuseMap\"]");
return false;
}
mSamplerNames[i] = entry->slotName + dStrlen(samplerDecl);
mSamplerNames[i].insert(0, '$');
mTexFilename[i] = entry->value;
++i;
}
}
return true;
}
//--------------------------------------------------------------------------
// On remove
//--------------------------------------------------------------------------
void CustomMaterial::onRemove()
{
Parent::onRemove();
}
//--------------------------------------------------------------------------
// Map this material to the texture specified in the "mapTo" data variable
//--------------------------------------------------------------------------
void CustomMaterial::_mapMaterial()
{
if( String(getName()).isEmpty() )
{
Con::warnf( "Unnamed Material! Could not map to: %s", mMapTo.c_str() );
return;
}
if( mMapTo.isEmpty() )
return;
MATMGR->mapMaterial(mMapTo, getName());
}
const GFXStateBlockData* CustomMaterial::getStateBlockData() const
{
return mStateBlockData;
}

View file

@ -0,0 +1,78 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _CUSTOMMATERIALDEFINITION_H_
#define _CUSTOMMATERIALDEFINITION_H_
#ifndef _MATERIALDEFINITION_H_
#include "materials/materialDefinition.h"
#endif
class ShaderData;
class GFXStateBlockData;
//**************************************************************************
// Custom Material
//**************************************************************************
class CustomMaterial : public Material
{
typedef Material Parent;
public:
enum CustomConsts
{
MAX_PASSES = 8,
NUM_FALLBACK_VERSIONS = 2,
};
FileName mTexFilename[MAX_TEX_PER_PASS];
String mSamplerNames[MAX_TEX_PER_PASS];
String mOutputTarget;
Material* mFallback;
bool mForwardLit;
F32 mVersion; // 0 = legacy, 1 = DX 8.1, 2 = DX 9.0
bool mRefract;
ShaderData* mShaderData;
CustomMaterial();
const GFXStateBlockData* getStateBlockData() const;
//
// SimObject interface
//
virtual bool onAdd();
virtual void onRemove();
//
// ConsoleObject interface
//
static void initPersistFields();
DECLARE_CONOBJECT(CustomMaterial);
protected:
U32 mMaxTex;
String mShaderDataName;
U32 mFlags[MAX_TEX_PER_PASS];
GFXStateBlockData* mStateBlockData;
virtual void _mapMaterial();
};
#endif

View file

@ -0,0 +1,561 @@
//-----------------------------------------------------------------------------
// 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/matInstance.h"
#include "materials/materialManager.h"
#include "materials/customMaterialDefinition.h"
#include "materials/processedMaterial.h"
#include "materials/processedFFMaterial.h"
#include "materials/processedShaderMaterial.h"
#include "materials/processedCustomMaterial.h"
#include "materials/materialFeatureTypes.h"
#include "shaderGen/featureMgr.h"
#include "gfx/gfxDevice.h"
#include "gfx/sim/cubemapData.h"
#include "gfx/gfxCubemap.h"
#include "core/util/safeDelete.h"
class MatInstParameters;
class MatInstanceParameterHandle : public MaterialParameterHandle
{
public:
virtual ~MatInstanceParameterHandle() {}
MatInstanceParameterHandle(const String& name);
void loadHandle(ProcessedMaterial* pmat);
// MaterialParameterHandle interface
const String& getName() const { return mName; }
virtual bool isValid() const;
virtual S32 getSamplerRegister( U32 pass ) const;
private:
friend class MatInstParameters;
String mName;
MaterialParameterHandle* mProcessedHandle;
};
MatInstanceParameterHandle::MatInstanceParameterHandle(const String& name)
{
mName = name;
mProcessedHandle = NULL;
}
bool MatInstanceParameterHandle::isValid() const
{
return mProcessedHandle && mProcessedHandle->isValid();
}
S32 MatInstanceParameterHandle::getSamplerRegister( U32 pass ) const
{
if ( !mProcessedHandle )
return -1;
return mProcessedHandle->getSamplerRegister( pass );
}
void MatInstanceParameterHandle::loadHandle(ProcessedMaterial* pmat)
{
mProcessedHandle = pmat->getMaterialParameterHandle(mName);
}
MatInstParameters::MatInstParameters()
{
mOwnParameters = false;
mParameters = NULL;
}
MatInstParameters::MatInstParameters(MaterialParameters* matParams)
{
mOwnParameters = false;
mParameters = matParams;
}
void MatInstParameters::loadParameters(ProcessedMaterial* pmat)
{
mOwnParameters = true;
mParameters = pmat->allocMaterialParameters();
}
MatInstParameters::~MatInstParameters()
{
if (mOwnParameters)
SAFE_DELETE(mParameters);
}
const Vector<GFXShaderConstDesc>& MatInstParameters::getShaderConstDesc() const
{
return mParameters->getShaderConstDesc();
}
U32 MatInstParameters::getAlignmentValue(const GFXShaderConstType constType)
{
return mParameters->getAlignmentValue(constType);
}
#define MATINSTPARAMSET(handle, f) \
if (!mParameters) \
return; \
AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!"); \
MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle); \
mParameters->set(mph->mProcessedHandle, f); \
void MatInstParameters::set(MaterialParameterHandle* handle, const F32 f)
{
MATINSTPARAMSET(handle, f);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const Point2F& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const Point3F& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const Point4F& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const ColorF& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const S32 f)
{
MATINSTPARAMSET(handle, f);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const Point2I& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const Point3I& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const Point4I& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv)
{
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType)
{
AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!");
MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle);
mParameters->set(mph->mProcessedHandle, mat, matrixType);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
{
AssertFatal(dynamic_cast<MatInstanceParameterHandle*>(handle), "Invalid handle type!");
MatInstanceParameterHandle* mph = static_cast<MatInstanceParameterHandle*>(handle);
mParameters->set(mph->mProcessedHandle, mat, arraySize, matrixType);
}
#undef MATINSTPARAMSET
//****************************************************************************
// Material Instance
//****************************************************************************
MatInstance::MatInstance( Material &mat )
{
VECTOR_SET_ASSOCIATION( mCurrentHandles );
VECTOR_SET_ASSOCIATION( mCurrentParameters );
mMaterial = &mat;
mCreatedFromCustomMaterial = (dynamic_cast<CustomMaterial *>(&mat) != NULL);
construct();
}
//----------------------------------------------------------------------------
// Construct
//----------------------------------------------------------------------------
void MatInstance::construct()
{
mUserObject = NULL;
mCurPass = -1;
mProcessedMaterial = false;
mVertexFormat = NULL;
mMaxStages = 1;
mActiveParameters = NULL;
mDefaultParameters = NULL;
mHasNormalMaps = false;
mIsForwardLit = false;
mIsValid = false;
MATMGR->_track(this);
}
//----------------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------------
MatInstance::~MatInstance()
{
SAFE_DELETE(mProcessedMaterial);
SAFE_DELETE(mDefaultParameters);
for (U32 i = 0; i < mCurrentHandles.size(); i++)
SAFE_DELETE(mCurrentHandles[i]);
MATMGR->_untrack(this);
}
//----------------------------------------------------------------------------
// Init
//----------------------------------------------------------------------------
bool MatInstance::init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat )
{
AssertFatal( vertexFormat, "MatInstance::init - Got null vertex format!" );
mFeatureList = features;
mVertexFormat = vertexFormat;
SAFE_DELETE(mProcessedMaterial);
mIsValid = processMaterial();
return mIsValid;
}
//----------------------------------------------------------------------------
// reInitialize
//----------------------------------------------------------------------------
bool MatInstance::reInit()
{
SAFE_DELETE(mProcessedMaterial);
deleteAllHooks();
mIsValid = processMaterial();
if ( mIsValid )
{
for (U32 i = 0; i < mCurrentHandles.size(); i++)
mCurrentHandles[i]->loadHandle(mProcessedMaterial);
for (U32 i = 0; i < mCurrentParameters.size(); i++)
mCurrentParameters[i]->loadParameters(mProcessedMaterial);
}
return mIsValid;
}
//----------------------------------------------------------------------------
// Process stages
//----------------------------------------------------------------------------
bool MatInstance::processMaterial()
{
AssertFatal( mMaterial, "MatInstance::processMaterial - Got null material!" );
//AssertFatal( mVertexFormat, "MatInstance::processMaterial - Got null vertex format!" );
if ( !mMaterial || !mVertexFormat )
return false;
SAFE_DELETE(mDefaultParameters);
CustomMaterial *custMat = NULL;
if( dynamic_cast<CustomMaterial*>(mMaterial) )
{
F32 pixVersion = GFX->getPixelShaderVersion();
custMat = static_cast<CustomMaterial*>(mMaterial);
if ((custMat->mVersion > pixVersion) || (custMat->mVersion == 0.0))
{
if(custMat->mFallback)
{
mMaterial = custMat->mFallback;
return processMaterial();
}
else
{
AssertWarn(custMat->mVersion == 0.0f, avar("Can't load CustomMaterial %s for %s, using generic FF fallback",
String(mMaterial->getName()).isEmpty() ? "Unknown" : mMaterial->getName(), custMat->mMapTo.c_str()));
mProcessedMaterial = new ProcessedFFMaterial(*mMaterial);
}
}
else
mProcessedMaterial = new ProcessedCustomMaterial(*mMaterial);
}
else if(GFX->getPixelShaderVersion() > 0.001)
mProcessedMaterial = getShaderMaterial();
else
mProcessedMaterial = new ProcessedFFMaterial(*mMaterial);
if (mProcessedMaterial)
{
mProcessedMaterial->addStateBlockDesc( mUserDefinedState );
mProcessedMaterial->setShaderMacros( mUserMacros );
mProcessedMaterial->setUserObject( mUserObject );
FeatureSet features( mFeatureList );
features.exclude( MATMGR->getExclusionFeatures() );
if( !mProcessedMaterial->init(features, mVertexFormat, mFeaturesDelegate) )
{
Con::errorf( "Failed to initialize material '%s'", getMaterial()->getName() );
SAFE_DELETE( mProcessedMaterial );
return false;
}
mDefaultParameters = new MatInstParameters(mProcessedMaterial->getDefaultMaterialParameters());
mActiveParameters = mDefaultParameters;
const FeatureSet &finalFeatures = mProcessedMaterial->getFeatures();
mHasNormalMaps = finalFeatures.hasFeature( MFT_NormalMap );
mIsForwardLit = ( custMat && custMat->mForwardLit ) ||
( !finalFeatures.hasFeature( MFT_IsEmissive ) &&
finalFeatures.hasFeature( MFT_ForwardShading ) );
return true;
}
return false;
}
const MatStateHint& MatInstance::getStateHint() const
{
if ( mProcessedMaterial )
return mProcessedMaterial->getStateHint();
else
return MatStateHint::Default;
}
ProcessedMaterial* MatInstance::getShaderMaterial()
{
return new ProcessedShaderMaterial(*mMaterial);
}
void MatInstance::addStateBlockDesc(const GFXStateBlockDesc& desc)
{
mUserDefinedState = desc;
}
void MatInstance::updateStateBlocks()
{
if ( mProcessedMaterial )
mProcessedMaterial->updateStateBlocks();
}
void MatInstance::addShaderMacro( const String &name, const String &value )
{
// Check to see if we already have this macro.
Vector<GFXShaderMacro>::iterator iter = mUserMacros.begin();
for ( ; iter != mUserMacros.end(); iter++ )
{
if ( iter->name == name )
{
iter->value = value;
return;
}
}
// Add a new macro.
mUserMacros.increment();
mUserMacros.last().name = name;
mUserMacros.last().value = value;
}
//----------------------------------------------------------------------------
// Setup pass - needs scenegraph data because the lightmap will change across
// several materials.
//----------------------------------------------------------------------------
bool MatInstance::setupPass(SceneRenderState * state, const SceneData &sgData )
{
PROFILE_SCOPE( MatInstance_SetupPass );
if( !mProcessedMaterial )
return false;
++mCurPass;
if ( !mProcessedMaterial->setupPass( state, sgData, mCurPass ) )
{
mCurPass = -1;
return false;
}
return true;
}
void MatInstance::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state)
{
PROFILE_SCOPE(MatInstance_setTransforms);
mProcessedMaterial->setTransforms(matrixSet, state, getCurPass());
}
void MatInstance::setSceneInfo(SceneRenderState * state, const SceneData& sgData)
{
PROFILE_SCOPE(MatInstance_setSceneInfo);
mProcessedMaterial->setSceneInfo(state, sgData, getCurPass());
}
void MatInstance::setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer)
{
mProcessedMaterial->setBuffers(vertBuffer, primBuffer);
}
void MatInstance::setTextureStages(SceneRenderState * state, const SceneData &sgData )
{
PROFILE_SCOPE(MatInstance_setTextureStages);
mProcessedMaterial->setTextureStages(state, sgData, getCurPass());
}
bool MatInstance::isInstanced() const
{
return mProcessedMaterial->getFeatures().hasFeature( MFT_UseInstancing );
}
bool MatInstance::stepInstance()
{
AssertFatal( isInstanced(), "MatInstance::stepInstance - This material isn't instanced!" );
AssertFatal( mCurPass >= 0, "MatInstance::stepInstance - Must be within material setup pass!" );
return mProcessedMaterial->stepInstance();
}
U32 MatInstance::getCurStageNum()
{
return mProcessedMaterial->getStageFromPass(getCurPass());
}
RenderPassData* MatInstance::getPass(U32 pass)
{
return mProcessedMaterial->getPass(pass);
}
bool MatInstance::hasGlow()
{
if( mProcessedMaterial )
return mProcessedMaterial->hasGlow();
else
return false;
}
const FeatureSet& MatInstance::getFeatures() const
{
return mProcessedMaterial->getFeatures();
}
MaterialParameterHandle* MatInstance::getMaterialParameterHandle(const String& name)
{
AssertFatal(mProcessedMaterial, "Not init'ed!");
for (U32 i = 0; i < mCurrentHandles.size(); i++)
{
if (mCurrentHandles[i]->getName().equal(name))
{
return mCurrentHandles[i];
}
}
MatInstanceParameterHandle* mph = new MatInstanceParameterHandle(name);
mph->loadHandle(mProcessedMaterial);
mCurrentHandles.push_back(mph);
return mph;
}
MaterialParameters* MatInstance::allocMaterialParameters()
{
AssertFatal(mProcessedMaterial, "Not init'ed!");
MatInstParameters* mip = new MatInstParameters();
mip->loadParameters(mProcessedMaterial);
mCurrentParameters.push_back(mip);
return mip;
}
void MatInstance::setMaterialParameters(MaterialParameters* param)
{
AssertFatal(mProcessedMaterial, "Not init'ed!");
mProcessedMaterial->setMaterialParameters(param, mCurPass);
AssertFatal(dynamic_cast<MatInstParameters*>(param), "Incorrect param type!");
mActiveParameters = static_cast<MatInstParameters*>(param);
}
MaterialParameters* MatInstance::getMaterialParameters()
{
AssertFatal(mProcessedMaterial, "Not init'ed!");
return mActiveParameters;
}
void MatInstance::dumpShaderInfo() const
{
if ( mMaterial == NULL )
{
Con::errorf( "Trying to get Material information on an invalid MatInstance" );
return;
}
Con::printf( "Material Info for object %s - %s", mMaterial->getName(), mMaterial->mMapTo.c_str() );
if ( mProcessedMaterial == NULL )
{
Con::printf( " [no processed material!]" );
return;
}
mProcessedMaterial->dumpMaterialInfo();
}

View file

@ -0,0 +1,180 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATINSTANCE_H_
#define _MATINSTANCE_H_
#ifndef _MATERIALDEFINITION_H_
#include "materials/materialDefinition.h"
#endif
#ifndef _BASEMATINSTANCE_H_
#include "materials/baseMatInstance.h"
#endif
#ifndef _SCENEDATA_H_
#include "materials/sceneData.h"
#endif
#ifndef _GFXSTATEBLOCK_H_
#include "gfx/gfxStateBlock.h"
#endif
#ifndef _FEATURESET_H_
#include "shaderGen/featureSet.h"
#endif
class GFXShader;
class GFXCubemap;
class ShaderFeature;
class MatInstanceParameterHandle;
class MatInstParameters;
class ProcessedMaterial;
///
class MatInstance : public BaseMatInstance
{
public:
virtual ~MatInstance();
// BaseMatInstance
virtual bool init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat );
virtual bool reInit();
virtual void addStateBlockDesc(const GFXStateBlockDesc& desc);
virtual void updateStateBlocks();
virtual void addShaderMacro( const String &name, const String &value );
virtual MaterialParameters* allocMaterialParameters();
virtual void setMaterialParameters(MaterialParameters* param);
virtual MaterialParameters* getMaterialParameters();
virtual MaterialParameterHandle* getMaterialParameterHandle(const String& name);
virtual bool setupPass(SceneRenderState *, const SceneData &sgData );
virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state);
virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData);
virtual void setTextureStages(SceneRenderState * state, const SceneData &sgData );
virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer);
virtual bool isInstanced() const;
virtual bool stepInstance();
virtual bool isForwardLit() const { return mIsForwardLit; }
virtual void setUserObject( SimObject *userObject ) { mUserObject = userObject; }
virtual SimObject* getUserObject() const { return mUserObject; }
virtual Material *getMaterial() { return mMaterial; }
virtual bool hasGlow();
virtual U32 getCurPass() { return getMax( mCurPass, 0 ); }
virtual U32 getCurStageNum();
virtual RenderPassData *getPass(U32 pass);
virtual const MatStateHint& getStateHint() const;
virtual const GFXVertexFormat* getVertexFormat() const { return mVertexFormat; }
virtual const FeatureSet& getFeatures() const;
virtual const FeatureSet& getRequestedFeatures() const { return mFeatureList; }
virtual void dumpShaderInfo() const;
ProcessedMaterial *getProcessedMaterial() const { return mProcessedMaterial; }
virtual const GFXStateBlockDesc &getUserStateBlock() const { return mUserDefinedState; }
virtual bool isCustomMaterial() const { return mCreatedFromCustomMaterial; }
protected:
friend class Material;
/// Create a material instance by reference to a Material.
MatInstance( Material &mat );
virtual bool processMaterial();
virtual ProcessedMaterial* getShaderMaterial();
Material* mMaterial;
ProcessedMaterial* mProcessedMaterial;
/// The features requested at material creation time.
FeatureSet mFeatureList;
/// The vertex format on which this material will render.
const GFXVertexFormat *mVertexFormat;
/// If the processed material requires forward lighting or not.
bool mIsForwardLit;
S32 mCurPass;
U32 mMaxStages;
GFXStateBlockDesc mUserDefinedState;
Vector<GFXShaderMacro> mUserMacros;
SimObject *mUserObject;
Vector<MatInstanceParameterHandle*> mCurrentHandles;
Vector<MatInstParameters*> mCurrentParameters;
MatInstParameters* mActiveParameters;
MatInstParameters* mDefaultParameters;
bool mCreatedFromCustomMaterial;
private:
void construct();
};
//
// MatInstParameters
//
class MatInstParameters : public MaterialParameters
{
public:
MatInstParameters();
MatInstParameters(MaterialParameters* matParams);
virtual ~MatInstParameters();
void loadParameters(ProcessedMaterial* pmat);
/// Returns our list of shader constants, the material can get this and just set the constants it knows about
virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
/// @name Set shader constant values
/// @{
/// Actually set shader constant values
/// @param name Name of the constant, this should be a name contained in the array returned in getShaderConstDesc,
/// if an invalid name is used, it is ignored.
virtual void set(MaterialParameterHandle* handle, const F32 f);
virtual void set(MaterialParameterHandle* handle, const Point2F& fv);
virtual void set(MaterialParameterHandle* handle, const Point3F& fv);
virtual void set(MaterialParameterHandle* handle, const Point4F& fv);
virtual void set(MaterialParameterHandle* handle, const ColorF& fv);
virtual void set(MaterialParameterHandle* handle, const S32 f);
virtual void set(MaterialParameterHandle* handle, const Point2I& fv);
virtual void set(MaterialParameterHandle* handle, const Point3I& fv);
virtual void set(MaterialParameterHandle* handle, const Point4I& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv);
virtual void set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
virtual void set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
virtual U32 getAlignmentValue(const GFXShaderConstType constType);
private:
MaterialParameters* mParameters;
bool mOwnParameters;
};
#endif // _MATINSTANCE_H_

View file

@ -0,0 +1,35 @@
//-----------------------------------------------------------------------------
// 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/matInstanceHook.h"
MatInstanceHookType::MatInstanceHookType( const char *type )
{
TypeMap::Iterator iter = getTypeMap().find( type );
if ( iter == getTypeMap().end() )
iter = getTypeMap().insertUnique( type, getTypeMap().size() );
mTypeIndex = iter->value;
}

View file

@ -0,0 +1,87 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATINSTANCEHOOK_H_
#define _MATINSTANCEHOOK_H_
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
/// The hook type wrapper object
class MatInstanceHookType
{
protected:
typedef HashTable<String,U32> TypeMap;
/// Returns the map of all the hook types. We create
/// it as a method static so that its available to other
/// statics regardless of initialization order.
static inline TypeMap& getTypeMap()
{
static TypeMap smTypeMap;
return smTypeMap;
}
/// The hook type index for this type.
U32 mTypeIndex;
public:
MatInstanceHookType( const char *type );
inline MatInstanceHookType( const MatInstanceHookType &type )
: mTypeIndex( type.mTypeIndex )
{
}
inline operator U32 () const { return mTypeIndex; }
};
/// This class is used to define hook objects attached to
/// material instances and provide a registration system
/// for different hook types.
///
/// @see BaseMatInstance
/// @see MaterialManager
///
class MatInstanceHook
{
public:
///
virtual ~MatInstanceHook() {}
///
virtual const MatInstanceHookType& getType() const = 0;
};
#endif // _MATINSTANCEHOOK_H_

View file

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------------
// 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/matStateHint.h"
#include "materials/processedMaterial.h"
const MatStateHint MatStateHint::Default( "Default" );
void MatStateHint::init( const ProcessedMaterial *mat )
{
PROFILE_SCOPE( MatStateHint_init );
mState.clear();
// Write the material identifier so that we batch by material
// specific data like diffuse color and parallax scale.
//
// NOTE: This doesn't actually cause more draw calls, but it
// can cause some extra unnessasary material setup when materials
// are different by their properties are the same.
//
const Material *material = mat->getMaterial();
mState += String::ToString( "Material: '%s', %d\n", material->getName(), material->getId() );
// Go thru each pass and write its state into
// the string in the most compact but uniquely
// identifiable way.
U32 passes = mat->getNumPasses();
for ( U32 i=0; i < passes; i++ )
mState += mat->getPass( i )->describeSelf();
// Finally intern the state string for
// fast pointer comparisions.
mState = mState.intern();
}

View file

@ -0,0 +1,77 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATSTATEHINT_H_
#define _MATSTATEHINT_H_
#ifndef _TORQUE_STRING_H_
#include "core/util/str.h"
#endif
class ProcessedMaterial;
/// A simple object for generating and comparing string based
/// hints used for sorting and identifying materials uniquely
/// by its shaders and states.
class MatStateHint
{
public:
/// Constructor.
MatStateHint() {}
/// Constructor for building special hints.
MatStateHint( const String &state )
: mState( state.intern() )
{
}
/// Initialize the state hint from a ProcessMaterial. This
/// assumes that the ProcessedMaterial has properly initialized
/// its passes to describe the material uniquely.
void init( const ProcessedMaterial *mat );
/// Clears the hint.
void clear() { mState.clear(); }
/// Returns a 32bit hash key used for sorting by material state.
operator U32() const { return mState.getHashCaseSensitive(); }
/// Fast comparision of state for equality.
bool operator ==( const MatStateHint& hint ) const { return mState == hint.mState; }
/// Fast comparision of state for inequality.
bool operator !=( const MatStateHint& hint ) const { return mState != hint.mState; }
/// A default state hint.
static const MatStateHint Default;
protected:
/// An interned string of the combined material shader and state info
/// for evert pass of the processed material.
String mState;
};
#endif // _MATSTATEHINT_H_

View file

@ -0,0 +1,141 @@
//-----------------------------------------------------------------------------
// 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/matTextureTarget.h"
#include "console/console.h"
#include "platform/profiler.h"
#include "shaderGen/conditionerFeature.h"
#include "gfx/gfxTextureObject.h"
#include "gfx/gfxStructs.h"
NamedTexTarget::TargetMap NamedTexTarget::smTargets;
bool NamedTexTarget::registerWithName( const String &name )
{
if ( mIsRegistered )
{
// If we're already registered with
// this name then do nothing.
if ( mName == name )
return true;
// Else unregister ourselves first.
unregister();
}
// Make sure the target name isn't empty or already taken.
if ( name.isEmpty() || smTargets.contains( name ) )
return false;
mName = name;
mIsRegistered = true;
smTargets.insert( mName, this );
return true;
}
void NamedTexTarget::unregister()
{
if ( !mIsRegistered )
return;
TargetMap::Iterator iter = smTargets.find( mName );
AssertFatal( iter != smTargets.end() &&
iter->value == this,
"NamedTexTarget::unregister - Bad registration!" );
mIsRegistered = false;
mName = String::EmptyString;
smTargets.erase( iter );
}
NamedTexTarget* NamedTexTarget::find( const String &name )
{
PROFILE_SCOPE( NamedTexTarget_find );
TargetMap::Iterator iter = smTargets.find( name );
if ( iter != smTargets.end() )
return iter->value;
else
return NULL;
}
NamedTexTarget::NamedTexTarget()
: mViewport( RectI::One ),
mIsRegistered( false ),
mConditioner( NULL )
{
}
NamedTexTarget::~NamedTexTarget()
{
unregister();
}
void NamedTexTarget::setTexture( U32 index, GFXTextureObject *tex )
{
AssertFatal( index < 4, "NamedTexTarget::setTexture - Got invalid index!" );
mTex[index] = tex;
}
void NamedTexTarget::release()
{
mTex[0] = NULL;
mTex[1] = NULL;
mTex[2] = NULL;
mTex[3] = NULL;
}
void NamedTexTarget::getShaderMacros( Vector<GFXShaderMacro> *outMacros )
{
ConditionerFeature *cond = getConditioner();
if ( !cond )
return;
// TODO: No check for duplicates is
// going on here which might be a problem?
String targetName = String::ToLower( mName );
// Add both the condition and uncondition macros.
const String &condMethod = cond->getShaderMethodName( ConditionerFeature::ConditionMethod );
if ( condMethod.isNotEmpty() )
{
GFXShaderMacro macro;
macro.name = targetName + "Condition";
macro.value = condMethod;
outMacros->push_back( macro );
}
const String &uncondMethod = cond->getShaderMethodName( ConditionerFeature::UnconditionMethod );
if ( uncondMethod.isNotEmpty() )
{
GFXShaderMacro macro;
macro.name = targetName + "Uncondition";
macro.value = uncondMethod;
outMacros->push_back( macro );
}
}

View file

@ -0,0 +1,163 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATTEXTURETARGET_H_
#define _MATTEXTURETARGET_H_
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
#ifndef _MRECT_H_
#include "math/mRect.h"
#endif
#ifndef _GFXSTATEBLOCK_H_
#include "gfx/gfxStateBlock.h"
#endif
#ifndef _UTIL_DELEGATE_H_
#include "core/util/delegate.h"
#endif
struct GFXShaderMacro;
class ConditionerFeature;
///
class NamedTexTarget : public WeakRefBase
{
public:
///
static NamedTexTarget* find( const String &name );
///
NamedTexTarget();
///
virtual ~NamedTexTarget();
///
bool registerWithName( const String &name );
///
void unregister();
///
bool isRegistered() const { return mIsRegistered; }
/// Returns the target name we were registered with.
const String& getName() const { return mName; }
// Register the passed texture with our name, unregistering "anyone"
// priorly registered with that name.
// Pass NULL to only unregister.
void setTexture( GFXTextureObject *tex ) { setTexture( 0, tex ); }
///
void setTexture( U32 index, GFXTextureObject *tex );
///
GFXTextureObject* getTexture( U32 index = 0 ) const;
/// The delegate used to override the getTexture method.
/// @see getTexture
typedef Delegate<GFXTextureObject*(U32)> TexDelegate;
///
/// @see getTexture
TexDelegate& getTextureDelegate() { return mTexDelegate; }
const TexDelegate& getTextureDelegate() const { return mTexDelegate; }
/// Release all the textures.
void release();
// NOTE:
//
// The following members are here to support the existing conditioner
// and target system used for the deferred gbuffer and lighting.
//
// We will refactor that system as part of material2 removing the concept
// of conditioners from C++ (moving them to HLSL/GLSL) and make the shader
// features which use the texture responsible for setting the correct sampler
// states.
//
// It could be that at this time this class could completely
// be removed and instead these textures can be registered
// with the TEXMGR and looked up there exclusively.
//
void setViewport( const RectI &viewport ) { mViewport = viewport; }
const RectI& getViewport() const { return mViewport; }
void setSamplerState( const GFXSamplerStateDesc &desc ) { mSamplerDesc = desc; }
void setupSamplerState( GFXSamplerStateDesc *desc ) const { *desc = mSamplerDesc; }
void setConditioner( ConditionerFeature *cond ) { mConditioner = cond; }
ConditionerFeature* getConditioner() const { return mConditioner; }
void getShaderMacros( Vector<GFXShaderMacro> *outMacros );
protected:
typedef Map<String,NamedTexTarget*> TargetMap;
///
static TargetMap smTargets;
///
bool mIsRegistered;
/// The target name we were registered with.
String mName;
/// The held textures.
GFXTexHandle mTex[4];
///
TexDelegate mTexDelegate;
///
RectI mViewport;
///
GFXSamplerStateDesc mSamplerDesc;
///
ConditionerFeature *mConditioner;
};
inline GFXTextureObject* NamedTexTarget::getTexture( U32 index ) const
{
AssertFatal( index < 4, "NamedTexTarget::getTexture - Got invalid index!" );
if ( mTexDelegate.empty() )
return mTex[index];
return mTexDelegate( index );
}
/// A weak reference to a texture target.
typedef WeakRefPtr<NamedTexTarget> NamedTexTargetRef;
#endif // _MATTEXTURETARGET_H_

View file

@ -0,0 +1,668 @@
//-----------------------------------------------------------------------------
// 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/materialDefinition.h"
#include "console/consoleTypes.h"
#include "math/mathTypes.h"
#include "materials/materialManager.h"
#include "sceneData.h"
#include "gfx/sim/cubemapData.h"
#include "gfx/gfxCubemap.h"
#include "math/mathIO.h"
#include "materials/matInstance.h"
#include "sfx/sfxTrack.h"
#include "sfx/sfxTypes.h"
#include "core/util/safeDelete.h"
IMPLEMENT_CONOBJECT( Material );
ConsoleDocClass( Material,
"@brief A material in Torque 3D is a data structure that describes a surface.\n\n"
"It contains many different types of information for rendering properties. "
"Torque 3D generates shaders from Material definitions. The shaders are compiled "
"at runtime and output into the example/shaders directory. Any errors or warnings "
"generated from compiling the procedurally generated shaders are output to the console "
"as well as the output window in the Visual C IDE.\n\n"
"@tsexample\n"
"singleton Material(DECAL_scorch)\n"
"{\n"
" baseTex[0] = \"./scorch_decal.png\";\n"
" vertColor[ 0 ] = true;\n\n"
" translucent = true;\n"
" translucentBlendOp = None;\n"
" translucentZWrite = true;\n"
" alphaTest = true;\n"
" alphaRef = 84;\n"
"};\n"
"@endtsexample\n\n"
"@see Rendering\n"
"@see ShaderData\n"
"@ingroup GFX\n");
ImplementBitfieldType( MaterialAnimType,
"The type of animation effect to apply to this material.\n"
"@ingroup GFX\n\n")
{ Material::Scroll, "Scroll", "Scroll the material along the X/Y axis.\n" },
{ Material::Rotate, "Rotate" , "Rotate the material around a point.\n"},
{ Material::Wave, "Wave" , "Warps the material with an animation using Sin, Triangle or Square mathematics.\n"},
{ Material::Scale, "Scale", "Scales the material larger and smaller with a pulsing effect.\n" },
{ Material::Sequence, "Sequence", "Enables the material to have multiple frames of animation in its imagemap.\n" }
EndImplementBitfieldType;
ImplementEnumType( MaterialBlendOp,
"The type of graphical blending operation to apply to this material\n"
"@ingroup GFX\n\n")
{ Material::None, "None", "Disable blending for this material." },
{ Material::Mul, "Mul", "Multiplicative blending." },
{ Material::Add, "Add", "Adds the color of the material to the frame buffer with full alpha for each pixel." },
{ Material::AddAlpha, "AddAlpha", "The color is modulated by the alpha channel before being added to the frame buffer." },
{ Material::Sub, "Sub", "Subtractive Blending. Reverses the color model, causing dark colors to have a stronger visual effect." },
{ Material::LerpAlpha, "LerpAlpha", "Linearly interpolates between Material color and frame buffer color based on alpha." }
EndImplementEnumType;
ImplementEnumType( MaterialWaveType,
"When using the Wave material animation, one of these Wave Types will be used to determine the type of wave to display.\n"
"@ingroup GFX\n")
{ Material::Sin, "Sin", "Warps the material along a curved Sin Wave." },
{ Material::Triangle, "Triangle", "Warps the material along a sharp Triangle Wave." },
{ Material::Square, "Square", "Warps the material along a wave which transitions between two oppposite states. As a Square Wave, the transition is quick and sudden." },
EndImplementEnumType;
bool Material::sAllowTextureTargetAssignment = false;
GFXCubemap * Material::GetNormalizeCube()
{
if(smNormalizeCube)
return smNormalizeCube;
smNormalizeCube = GFX->createCubemap();
smNormalizeCube->initNormalize(64);
return smNormalizeCube;
}
GFXCubemapHandle Material::smNormalizeCube;
Material::Material()
{
for( U32 i=0; i<MAX_STAGES; i++ )
{
mDiffuse[i].set( 1.0f, 1.0f, 1.0f, 1.0f );
mSpecular[i].set( 1.0f, 1.0f, 1.0f, 1.0f );
mSpecularPower[i] = 8.0f;
mPixelSpecular[i] = false;
mParallaxScale[i] = 0.0f;
mVertLit[i] = false;
mVertColor[ i ] = false;
mGlow[i] = false;
mEmissive[i] = false;
mDetailScale[i].set( 2.0f, 2.0f );
mDetailNormalMapStrength[i] = 1.0f;
mMinnaertConstant[i] = -1.0f;
mSubSurface[i] = false;
mSubSurfaceColor[i].set( 1.0f, 0.2f, 0.2f, 1.0f );
mSubSurfaceRolloff[i] = 0.2f;
mAnimFlags[i] = 0;
mScrollDir[i].set( 0.0f, 0.0f );
mScrollSpeed[i] = 0.0f;
mScrollOffset[i].set( 0.0f, 0.0f );
mRotSpeed[i] = 0.0f;
mRotPivotOffset[i].set( 0.0f, 0.0f );
mRotPos[i] = 0.0f;
mWavePos[i] = 0.0f;
mWaveFreq[i] = 0.0f;
mWaveAmp[i] = 0.0f;
mWaveType[i] = 0;
mSeqFramePerSec[i] = 0.0f;
mSeqSegSize[i] = 0.0f;
}
dMemset(mCellIndex, 0, sizeof(mCellIndex));
dMemset(mCellLayout, 0, sizeof(mCellLayout));
dMemset(mCellSize, 0, sizeof(mCellSize));
dMemset(mNormalMapAtlas, 0, sizeof(mNormalMapAtlas));
dMemset(mUseAnisotropic, 0, sizeof(mUseAnisotropic));
mImposterLimits = Point4F::Zero;
mDoubleSided = false;
mTranslucent = false;
mTranslucentBlendOp = LerpAlpha;
mTranslucentZWrite = false;
mAlphaTest = false;
mAlphaRef = 1;
mCastShadows = true;
mPlanarReflection = false;
mCubemapData = NULL;
mDynamicCubemap = NULL;
mLastUpdateTime = 0;
mAutoGenerated = false;
mShowDust = false;
mShowFootprints = true;
dMemset( mEffectColor, 0, sizeof( mEffectColor ) );
mFootstepSoundId = -1; mImpactSoundId = -1;
mFootstepSoundCustom = 0; mImpactSoundCustom = 0;
mFriction = 0.0;
mDirectSoundOcclusion = 1.f;
mReverbSoundOcclusion = 1.0;
}
void Material::initPersistFields()
{
addField("mapTo", TypeRealString, Offset(mMapTo, Material),
"Used to map this material to the material name used by TSShape." );
addArray( "Stages", MAX_STAGES );
addField("diffuseColor", TypeColorF, Offset(mDiffuse, Material), MAX_STAGES,
"This color is multiplied against the diffuse texture color. If no diffuse texture "
"is present this is the material color." );
addField("diffuseMap", TypeImageFilename, Offset(mDiffuseMapFilename, Material), MAX_STAGES,
"The diffuse color texture map." );
addField("overlayMap", TypeImageFilename, Offset(mOverlayMapFilename, Material), MAX_STAGES,
"A secondary diffuse color texture map which will use the second texcoord of a mesh." );
addField("lightMap", TypeImageFilename, Offset(mLightMapFilename, Material), MAX_STAGES,
"The lightmap texture used with pureLight." );
addField("toneMap", TypeImageFilename, Offset(mToneMapFilename, Material), MAX_STAGES,
"The tonemap texture used with pureLight.");
addField("detailMap", TypeImageFilename, Offset(mDetailMapFilename, Material), MAX_STAGES,
"A typically greyscale detail texture additively blended into the material." );
addField("detailScale", TypePoint2F, Offset(mDetailScale, Material), MAX_STAGES,
"The scale factor for the detail map." );
addField( "normalMap", TypeImageFilename, Offset(mNormalMapFilename, Material), MAX_STAGES,
"The normal map texture. You can use the DXTnm format only when per-pixel "
"specular highlights are disabled, or a specular map is in use." );
addField( "detailNormalMap", TypeImageFilename, Offset(mDetailNormalMapFilename, Material), MAX_STAGES,
"A second normal map texture applied at the detail scale. You can use the DXTnm "
"format only when per-pixel specular highlights are disabled." );
addField( "detailNormalMapStrength", TypeF32, Offset(mDetailNormalMapStrength, Material), MAX_STAGES,
"Used to scale the strength of the detail normal map when blended with the base normal map." );
addField("specular", TypeColorF, Offset(mSpecular, Material), MAX_STAGES,
"The color of the specular highlight when not using a specularMap." );
addField("specularPower", TypeF32, Offset(mSpecularPower, Material), MAX_STAGES,
"The intensity of the specular highlight when not using a specularMap." );
addField("pixelSpecular", TypeBool, Offset(mPixelSpecular, Material), MAX_STAGES,
"This enables per-pixel specular highlights controlled by the alpha channel of the "
"normal map texture. Note that if pixel specular is enabled the DXTnm format will not "
"work with your normal map, unless you are also using a specular map." );
addField( "specularMap", TypeImageFilename, Offset(mSpecularMapFilename, Material), MAX_STAGES,
"The specular map texture. The RGB channels of this texture provide a per-pixel replacement for the 'specular' parameter on the material. "
"If this texture contains alpha information, the alpha channel of the texture will be used as the gloss map. "
"This provides a per-pixel replacement for the 'specularPower' on the material" );
addField( "parallaxScale", TypeF32, Offset(mParallaxScale, Material), MAX_STAGES,
"Enables parallax mapping and defines the scale factor for the parallax effect. Typically "
"this value is less than 0.4 else the effect breaks down." );
addField( "useAnisotropic", TypeBool, Offset(mUseAnisotropic, Material), MAX_STAGES,
"Use anisotropic filtering for the textures of this stage." );
addField("envMap", TypeImageFilename, Offset(mEnvMapFilename, Material), MAX_STAGES,
"The name of an environment map cube map to apply to this material." );
addField("vertLit", TypeBool, Offset(mVertLit, Material), MAX_STAGES,
"If true the vertex color is used for lighting." );
addField( "vertColor", TypeBool, Offset( mVertColor, Material ), MAX_STAGES,
"If enabled, vertex colors are premultiplied with diffuse colors." );
addField("minnaertConstant", TypeF32, Offset(mMinnaertConstant, Material), MAX_STAGES,
"The Minnaert shading constant value. Must be greater than 0 to enable the effect." );
addField("subSurface", TypeBool, Offset(mSubSurface, Material), MAX_STAGES,
"Enables the subsurface scattering approximation." );
addField("subSurfaceColor", TypeColorF, Offset(mSubSurfaceColor, Material), MAX_STAGES,
"The color used for the subsurface scattering approximation." );
addField("subSurfaceRolloff", TypeF32, Offset(mSubSurfaceRolloff, Material), MAX_STAGES,
"The 0 to 1 rolloff factor used in the subsurface scattering approximation." );
addField("glow", TypeBool, Offset(mGlow, Material), MAX_STAGES,
"Enables rendering this material to the glow buffer." );
addField("emissive", TypeBool, Offset(mEmissive, Material), MAX_STAGES,
"Enables emissive lighting for the material." );
addField("doubleSided", TypeBool, Offset(mDoubleSided, Material),
"Disables backface culling casing surfaces to be double sided. "
"Note that the lighting on the backside will be a mirror of the front "
"side of the surface." );
addField("animFlags", TYPEID< AnimType >(), Offset(mAnimFlags, Material), MAX_STAGES,
"The types of animation to play on this material." );
addField("scrollDir", TypePoint2F, Offset(mScrollDir, Material), MAX_STAGES,
"The scroll direction in UV space when scroll animation is enabled." );
addField("scrollSpeed", TypeF32, Offset(mScrollSpeed, Material), MAX_STAGES,
"The speed to scroll the texture in UVs per second when scroll animation is enabled." );
addField("rotSpeed", TypeF32, Offset(mRotSpeed, Material), MAX_STAGES,
"The speed to rotate the texture in degrees per second when rotation animation is enabled." );
addField("rotPivotOffset", TypePoint2F, Offset(mRotPivotOffset, Material), MAX_STAGES,
"The piviot position in UV coordinates to center the rotation animation." );
addField("waveType", TYPEID< WaveType >(), Offset(mWaveType, Material), MAX_STAGES,
"The type of wave animation to perform when wave animation is enabled." );
addField("waveFreq", TypeF32, Offset(mWaveFreq, Material), MAX_STAGES,
"The wave frequency when wave animation is enabled." );
addField("waveAmp", TypeF32, Offset(mWaveAmp, Material), MAX_STAGES,
"The wave amplitude when wave animation is enabled." );
addField("sequenceFramePerSec", TypeF32, Offset(mSeqFramePerSec, Material), MAX_STAGES,
"The number of frames per second for frame based sequence animations if greater than zero." );
addField("sequenceSegmentSize", TypeF32, Offset(mSeqSegSize, Material), MAX_STAGES,
"The size of each frame in UV units for sequence animations." );
// Texture atlasing
addField("cellIndex", TypePoint2I, Offset(mCellIndex, Material), MAX_STAGES,
"@internal" );
addField("cellLayout", TypePoint2I, Offset(mCellLayout, Material), MAX_STAGES,
"@internal");
addField("cellSize", TypeS32, Offset(mCellSize, Material), MAX_STAGES,
"@internal");
addField("bumpAtlas", TypeBool, Offset(mNormalMapAtlas, Material), MAX_STAGES,
"@internal");
// For backwards compatibility.
//
// They point at the new 'map' fields, but reads always return
// an empty string and writes only apply if the value is not empty.
//
addProtectedField("baseTex", TypeImageFilename, Offset(mDiffuseMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see diffuseMap\n" );
addProtectedField("detailTex", TypeImageFilename, Offset(mDetailMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see detailMap\n");
addProtectedField("overlayTex", TypeImageFilename, Offset(mOverlayMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see overlayMap\n");
addProtectedField("bumpTex", TypeImageFilename, Offset(mNormalMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see normalMap\n");
addProtectedField("envTex", TypeImageFilename, Offset(mEnvMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see envMap\n");
addProtectedField("colorMultiply", TypeColorF, Offset(mDiffuse, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see diffuseColor\n");
endArray( "Stages" );
addField( "castShadows", TypeBool, Offset(mCastShadows, Material),
"If set to false the lighting system will not cast shadows from this material." );
addField("planarReflection", TypeBool, Offset(mPlanarReflection, Material), "@internal" );
addField("translucent", TypeBool, Offset(mTranslucent, Material),
"If true this material is translucent blended." );
addField("translucentBlendOp", TYPEID< BlendOp >(), Offset(mTranslucentBlendOp, Material),
"The type of blend operation to use when the material is translucent." );
addField("translucentZWrite", TypeBool, Offset(mTranslucentZWrite, Material),
"If enabled and the material is translucent it will write into the depth buffer." );
addField("alphaTest", TypeBool, Offset(mAlphaTest, Material),
"Enables alpha test when rendering the material.\n@see alphaRef\n" );
addField("alphaRef", TypeS32, Offset(mAlphaRef, Material),
"The alpha reference value for alpha testing. Must be between 0 to 255.\n@see alphaTest\n" );
addField("cubemap", TypeRealString, Offset(mCubemapName, Material),
"The name of a CubemapData for environment mapping." );
addField("dynamicCubemap", TypeBool, Offset(mDynamicCubemap, Material),
"Enables the material to use the dynamic cubemap from the ShapeBase object its applied to." );
addGroup( "Behavioral" );
addField( "showFootprints", TypeBool, Offset( mShowFootprints, Material ),
"Whether to show player footprint decals on this material.\n\n"
"@see PlayerData::decalData" );
addField( "showDust", TypeBool, Offset( mShowDust, Material ),
"Whether to emit dust particles from a shape moving over the material. This is, for example, used by "
"vehicles or players to decide whether to show dust trails." );
addField( "effectColor", TypeColorF, Offset( mEffectColor, Material ), NUM_EFFECT_COLOR_STAGES,
"If #showDust is true, this is the set of colors to use for the ParticleData of the dust "
"emitter.\n\n"
"@see ParticleData::colors" );
addField( "footstepSoundId", TypeS32, Offset( mFootstepSoundId, Material ),
"What sound to play from the PlayerData sound list when the player walks over the material. -1 (default) to not play any sound.\n"
"\n"
"The IDs are:\n\n"
"- 0: PlayerData::FootSoftSound\n"
"- 1: PlayerData::FootHardSound\n"
"- 2: PlayerData::FootMetalSound\n"
"- 3: PlayerData::FootSnowSound\n"
"- 4: PlayerData::FootShallowSound\n"
"- 5: PlayerData::FootWadingSound\n"
"- 6: PlayerData::FootUnderwaterSound\n"
"- 7: PlayerData::FootBubblesSound\n"
"- 8: PlayerData::movingBubblesSound\n"
"- 9: PlayerData::waterBreathSound\n"
"- 10: PlayerData::impactSoftSound\n"
"- 11: PlayerData::impactHardSound\n"
"- 12: PlayerData::impactMetalSound\n"
"- 13: PlayerData::impactSnowSound\n"
"- 14: PlayerData::impactWaterEasy\n"
"- 15: PlayerData::impactWaterMedium\n"
"- 16: PlayerData::impactWaterHard\n"
"- 17: PlayerData::exitingWater\n" );
addField( "customFootstepSound", TypeSFXTrackName, Offset( mFootstepSoundCustom, Material ),
"The sound to play when the player walks over the material. If this is set, it overrides #footstepSoundId. This field is "
"useful for directly assigning custom footstep sounds to materials without having to rely on the PlayerData sound assignment.\n\n"
"@warn Be aware that materials are client-side objects. This means that the SFXTracks assigned to materials must be client-side, too." );
addField( "impactSoundId", TypeS32, Offset( mImpactSoundId, Material ),
"What sound to play from the PlayerData sound list when the player impacts on the surface with a velocity equal or greater "
"than PlayerData::groundImpactMinSpeed.\n\n"
"For a list of IDs, see #footstepSoundId" );
addField( "customImpactSound", TypeSFXTrackName, Offset( mImpactSoundCustom, Material ),
"The sound to play when the player impacts on the surface with a velocity equal or greater than PlayerData::groundImpactMinSpeed. "
"If this is set, it overrides #impactSoundId. This field is useful for directly assigning custom impact sounds to materials "
"without having to rely on the PlayerData sound assignment.\n\n"
"@warn Be aware that materials are client-side objects. This means that the SFXTracks assigned to materials must be client-side, too." );
//Deactivate these for the moment as they are not used.
#if 0
addField( "friction", TypeF32, Offset( mFriction, Material ) );
addField( "directSoundOcclusion", TypeF32, Offset( mDirectSoundOcclusion, Material ) );
addField( "reverbSoundOcclusion", TypeF32, Offset( mReverbSoundOcclusion, Material ) );
#endif
endGroup( "Behavioral" );
Parent::initPersistFields();
}
bool Material::writeField( StringTableEntry fieldname, const char *value )
{
// Never allow the old field names to be written.
if ( fieldname == StringTable->insert("baseTex") ||
fieldname == StringTable->insert("detailTex") ||
fieldname == StringTable->insert("overlayTex") ||
fieldname == StringTable->insert("bumpTex") ||
fieldname == StringTable->insert("envTex") ||
fieldname == StringTable->insert("colorMultiply") )
return false;
return Parent::writeField( fieldname, value );
}
bool Material::onAdd()
{
if (Parent::onAdd() == false)
return false;
mCubemapData = dynamic_cast<CubemapData*>(Sim::findObject( mCubemapName ) );
if( mTranslucentBlendOp >= NumBlendTypes || mTranslucentBlendOp < 0 )
{
Con::errorf( "Invalid blend op in material: %s", getName() );
mTranslucentBlendOp = LerpAlpha;
}
SimSet *matSet = MATMGR->getMaterialSet();
if( matSet )
matSet->addObject( (SimObject*)this );
// save the current script path for texture lookup later
const String scriptFile = Con::getVariable("$Con::File"); // current script file - local materials.cs
String::SizeType slash = scriptFile.find( '/', scriptFile.length(), String::Right );
if ( slash != String::NPos )
mPath = scriptFile.substr( 0, slash + 1 );
_mapMaterial();
return true;
}
void Material::onRemove()
{
smNormalizeCube = NULL;
Parent::onRemove();
}
void Material::inspectPostApply()
{
Parent::inspectPostApply();
// Reload the material instances which
// use this material.
if ( isProperlyAdded() )
reload();
}
bool Material::isLightmapped() const
{
bool ret = false;
for( U32 i=0; i<MAX_STAGES; i++ )
ret |= mLightMapFilename[i].isNotEmpty() || mToneMapFilename[i].isNotEmpty() || mVertLit[i];
return ret;
}
void Material::updateTimeBasedParams()
{
U32 lastTime = MATMGR->getLastUpdateTime();
F32 dt = MATMGR->getDeltaTime();
if (mLastUpdateTime != lastTime)
{
for (U32 i = 0; i < MAX_STAGES; i++)
{
mScrollOffset[i] += mScrollDir[i] * mScrollSpeed[i] * dt;
mRotPos[i] += mRotSpeed[i] * dt;
mWavePos[i] += mWaveFreq[i] * dt;
}
mLastUpdateTime = lastTime;
}
}
void Material::_mapMaterial()
{
if( String(getName()).isEmpty() )
{
Con::warnf( "[Material::mapMaterial] - Cannot map unnamed Material" );
return;
}
// If mapTo not defined in script, try to use the base texture name instead
if( mMapTo.isEmpty() )
{
if ( mDiffuseMapFilename[0].isEmpty() )
return;
else
{
// extract filename from base texture
if ( mDiffuseMapFilename[0].isNotEmpty() )
{
U32 slashPos = mDiffuseMapFilename[0].find('/',0,String::Right);
if (slashPos == String::NPos)
// no '/' character, must be no path, just the filename
mMapTo = mDiffuseMapFilename[0];
else
// use everything after the last slash
mMapTo = mDiffuseMapFilename[0].substr(slashPos+1, mDiffuseMapFilename[0].length() - slashPos - 1);
}
}
}
// add mapping
MATMGR->mapMaterial(mMapTo,getName());
}
BaseMatInstance* Material::createMatInstance()
{
return new MatInstance(*this);
}
void Material::flush()
{
MATMGR->flushInstance( this );
}
void Material::reload()
{
MATMGR->reInitInstance( this );
}
void Material::StageData::getFeatureSet( FeatureSet *outFeatures ) const
{
TextureTable::ConstIterator iter = mTextures.begin();
for ( ; iter != mTextures.end(); iter++ )
{
if ( iter->value.isValid() )
outFeatures->addFeature( *iter->key );
}
}
ConsoleMethod( Material, flush, void, 2, 2,
"Flushes all material instances that use this material." )
{
object->flush();
}
ConsoleMethod( Material, reload, void, 2, 2,
"Reloads all material instances that use this material." )
{
object->reload();
}
ConsoleMethod( Material, dumpInstances, void, 2, 2,
"Dumps a formatted list of the currently allocated material instances for this material to the console." )
{
MATMGR->dumpMaterialInstances( object );
}
ConsoleMethod( Material, getAnimFlags, const char*, 3, 3, "" )
{
char * animFlags = Con::getReturnBuffer(512);
if(object->mAnimFlags[ dAtoi(argv[2]) ] & Material::Scroll)
{
if(dStrcmp( animFlags, "" ) == 0)
dStrcpy( animFlags, "$Scroll" );
}
if(object->mAnimFlags[ dAtoi(argv[2]) ] & Material::Rotate)
{
if(dStrcmp( animFlags, "" ) == 0)
dStrcpy( animFlags, "$Rotate" );
else
dStrcat( animFlags, " | $Rotate");
}
if(object->mAnimFlags[ dAtoi(argv[2]) ] & Material::Wave)
{
if(dStrcmp( animFlags, "" ) == 0)
dStrcpy( animFlags, "$Wave" );
else
dStrcat( animFlags, " | $Wave");
}
if(object->mAnimFlags[ dAtoi(argv[2]) ] & Material::Scale)
{
if(dStrcmp( animFlags, "" ) == 0)
dStrcpy( animFlags, "$Scale" );
else
dStrcat( animFlags, " | $Scale");
}
if(object->mAnimFlags[ dAtoi(argv[2]) ] & Material::Sequence)
{
if(dStrcmp( animFlags, "" ) == 0)
dStrcpy( animFlags, "$Sequence" );
else
dStrcat( animFlags, " | $Sequence");
}
return animFlags;
}
ConsoleMethod(Material, getFilename, const char*, 2, 2, "Get filename of material")
{
SimObject *material = static_cast<SimObject *>(object);
return material->getFilename();
}
ConsoleMethod( Material, isAutoGenerated, bool, 2, 2,
"Returns true if this Material was automatically generated by MaterialList::mapMaterials()" )
{
return object->isAutoGenerated();
}
ConsoleMethod( Material, setAutoGenerated, void, 3, 3,
"setAutoGenerated(bool isAutoGenerated): Set whether or not the Material is autogenerated." )
{
object->setAutoGenerated(dAtob(argv[2]));
}

View file

@ -0,0 +1,401 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALDEFINITION_H_
#define _MATERIALDEFINITION_H_
#ifndef _BASEMATERIALDEFINITION_H_
#include "materials/baseMaterialDefinition.h"
#endif
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
#ifndef _GFXSTRUCTS_H_
#include "gfx/gfxStructs.h"
#endif
#ifndef _GFXCUBEMAP_H_
#include "gfx/gfxCubemap.h"
#endif
#ifndef _DYNAMIC_CONSOLETYPES_H_
#include "console/dynamicTypes.h"
#endif
class CubemapData;
class SFXTrack;
struct SceneData;
class FeatureSet;
class FeatureType;
class MaterialSoundProfile;
class MaterialPhysicsProfile;
/// The basic material definition.
class Material : public BaseMaterialDefinition
{
typedef BaseMaterialDefinition Parent;
public:
static GFXCubemap *GetNormalizeCube();
//-----------------------------------------------------------------------
// Enums
//-----------------------------------------------------------------------
enum Constants
{
MAX_TEX_PER_PASS = 8, ///< Number of textures per pass
MAX_STAGES = 4,
NUM_EFFECT_COLOR_STAGES = 2, ///< Number of effect color definitions for transitioning effects.
};
enum TexType
{
NoTexture = 0,
Standard = 1,
Detail,
Bump,
DetailBump,
Env,
Cube,
SGCube, // scene graph cube - probably dynamic
Lightmap,
ToneMapTex,
Mask,
BackBuff,
ReflectBuff,
Misc,
DynamicLight,
DynamicLightMask,
NormalizeCube,
TexTarget,
};
enum BlendOp
{
None = 0,
Mul,
Add,
AddAlpha, // add modulated with alpha channel
Sub,
LerpAlpha, // linear interpolation modulated with alpha channel
ToneMap,
NumBlendTypes
};
enum AnimType
{
Scroll = 1,
Rotate = 2,
Wave = 4,
Scale = 8,
Sequence = 16,
};
enum WaveType
{
Sin = 0,
Triangle,
Square,
};
class StageData
{
protected:
///
typedef HashTable<const FeatureType*,GFXTexHandle> TextureTable;
/// The sparse table of textures by feature index.
/// @see getTex
/// @see setTex
TextureTable mTextures;
/// The cubemap for this stage.
GFXCubemap *mCubemap;
public:
StageData()
: mCubemap( NULL )
{
}
/// Returns the texture object or NULL if there is no
/// texture entry for that feature type in the table.
inline GFXTextureObject* getTex( const FeatureType &type ) const
{
TextureTable::ConstIterator iter = mTextures.find( &type );
if ( iter == mTextures.end() )
return NULL;
return iter->value.getPointer();
}
/// Assigns a texture object by feature type.
inline void setTex( const FeatureType &type, GFXTextureObject *tex )
{
if ( !tex )
{
TextureTable::Iterator iter = mTextures.find( &type );
if ( iter != mTextures.end() )
mTextures.erase( iter );
return;
}
TextureTable::Iterator iter = mTextures.findOrInsert( &type );
iter->value = tex;
}
/// Returns true if we have a valid texture assigned to
/// any feature in the texture table.
inline bool hasValidTex() const
{
TextureTable::ConstIterator iter = mTextures.begin();
for ( ; iter != mTextures.end(); iter++ )
{
if ( iter->value.isValid() )
return true;
}
return false;
}
/// Returns the active texture features.
void getFeatureSet( FeatureSet *outFeatures ) const;
/// Returns the stage cubemap.
GFXCubemap* getCubemap() const { return mCubemap; }
/// Set the stage cubemap.
void setCubemap( GFXCubemap *cubemap ) { mCubemap = cubemap; }
};
public:
//-----------------------------------------------------------------------
// Data
//-----------------------------------------------------------------------
FileName mDiffuseMapFilename[MAX_STAGES];
FileName mOverlayMapFilename[MAX_STAGES];
FileName mLightMapFilename[MAX_STAGES];
FileName mToneMapFilename[MAX_STAGES];
FileName mDetailMapFilename[MAX_STAGES];
FileName mNormalMapFilename[MAX_STAGES];
FileName mSpecularMapFilename[MAX_STAGES];
/// A second normal map which repeats at the detail map
/// scale and blended with the base normal map.
FileName mDetailNormalMapFilename[MAX_STAGES];
/// The strength scalar for the detail normal map.
F32 mDetailNormalMapStrength[MAX_STAGES];
FileName mEnvMapFilename[MAX_STAGES];
/// This color is the diffuse color of the material
/// or if it has a texture it is multiplied against
/// the diffuse texture color.
ColorF mDiffuse[MAX_STAGES];
ColorF mSpecular[MAX_STAGES];
F32 mSpecularPower[MAX_STAGES];
bool mPixelSpecular[MAX_STAGES];
bool mVertLit[MAX_STAGES];
/// If true for a stage, vertex colors are multiplied
/// against diffuse colors.
bool mVertColor[ MAX_STAGES ];
F32 mParallaxScale[MAX_STAGES];
F32 mMinnaertConstant[MAX_STAGES];
bool mSubSurface[MAX_STAGES];
ColorF mSubSurfaceColor[MAX_STAGES];
F32 mSubSurfaceRolloff[MAX_STAGES];
/// The repetition scale of the detail texture
/// over the base texture.
Point2F mDetailScale[MAX_STAGES];
U32 mAnimFlags[MAX_STAGES];
Point2F mScrollDir[MAX_STAGES];
F32 mScrollSpeed[MAX_STAGES];
Point2F mScrollOffset[MAX_STAGES];
F32 mRotSpeed[MAX_STAGES];
Point2F mRotPivotOffset[MAX_STAGES];
F32 mRotPos[MAX_STAGES];
F32 mWavePos[MAX_STAGES];
F32 mWaveFreq[MAX_STAGES];
F32 mWaveAmp[MAX_STAGES];
U32 mWaveType[MAX_STAGES];
F32 mSeqFramePerSec[MAX_STAGES];
F32 mSeqSegSize[MAX_STAGES];
bool mGlow[MAX_STAGES]; // entire stage glows
bool mEmissive[MAX_STAGES];
Point2I mCellIndex[MAX_STAGES];
Point2I mCellLayout[MAX_STAGES];
U32 mCellSize[MAX_STAGES];
bool mNormalMapAtlas[MAX_STAGES];
/// Special array of UVs for imposter rendering.
/// @see TSLastDetail
Vector<RectF> mImposterUVs;
/// Specual imposter rendering paramters.
/// @see TSLastDetail
Point4F mImposterLimits;
/// If the stage should use anisotropic filtering.
bool mUseAnisotropic[MAX_STAGES];
bool mDoubleSided;
String mCubemapName;
CubemapData* mCubemapData;
bool mDynamicCubemap;
bool mTranslucent;
BlendOp mTranslucentBlendOp;
bool mTranslucentZWrite;
/// A generic setting which tells the system to skip
/// generation of shadows from this material.
bool mCastShadows;
bool mAlphaTest;
U32 mAlphaRef;
bool mPlanarReflection;
bool mAutoGenerated;
static bool sAllowTextureTargetAssignment;
///@{
/// Behavioral properties.
bool mShowFootprints; ///< If true, show footprints when walking on surface with this material. Defaults to false.
bool mShowDust; ///< If true, show dust emitters (footpuffs, hover trails, etc) when on surface with this material. Defaults to false.
/// Color to use for particle effects and such when located on this material.
ColorF mEffectColor[ NUM_EFFECT_COLOR_STAGES ];
/// Footstep sound to play when walking on surface with this material.
/// Numeric ID of footstep sound defined on player datablock (0 == soft,
/// 1 == hard, 2 == metal, 3 == snow).
/// Defaults to -1 which deactivates default sound.
/// @see mFootstepSoundCustom
S32 mFootstepSoundId;
S32 mImpactSoundId;
/// Sound effect to play when walking on surface with this material.
/// If defined, overrides mFootstepSoundId.
/// @see mFootstepSoundId
SFXTrack* mFootstepSoundCustom;
SFXTrack* mImpactSoundCustom;
F32 mFriction; ///< Friction coefficient when moving along surface.
F32 mDirectSoundOcclusion; ///< Amount of volume occlusion on direct sounds.
F32 mReverbSoundOcclusion; ///< Amount of volume occlusion on reverb sounds.
///@}
String mMapTo; // map Material to this texture name
///
/// Material interface
///
Material();
/// Allocates and returns a BaseMatInstance for this material. Caller is responsible
/// for freeing the instance
virtual BaseMatInstance* createMatInstance();
virtual bool isTranslucent() const { return mTranslucent && mTranslucentBlendOp != Material::None; }
virtual bool isDoubleSided() const { return mDoubleSided; }
virtual bool isAutoGenerated() const { return mAutoGenerated; }
virtual void setAutoGenerated(bool isAutoGenerated) { mAutoGenerated = isAutoGenerated; }
virtual bool isLightmapped() const;
virtual bool castsShadows() const { return mCastShadows; }
const String &getPath() const { return mPath; }
void flush();
/// Re-initializes all the material instances
/// that use this material.
void reload();
/// Called to update time based parameters for a material. Ensures
/// that it only happens once per tick.
void updateTimeBasedParams();
// SimObject
virtual bool onAdd();
virtual void onRemove();
virtual void inspectPostApply();
virtual bool writeField( StringTableEntry fieldname, const char *value );
//
// ConsoleObject interface
//
static void initPersistFields();
DECLARE_CONOBJECT(Material);
protected:
// Per material animation parameters
U32 mLastUpdateTime;
String mPath;
static EnumTable mAnimFlagTable;
static EnumTable mBlendOpTable;
static EnumTable mWaveTypeTable;
/// Map this material to the texture specified
/// in the "mapTo" data variable.
virtual void _mapMaterial();
private:
static GFXCubemapHandle smNormalizeCube;
};
typedef Material::AnimType MaterialAnimType;
typedef Material::BlendOp MaterialBlendOp;
typedef Material::WaveType MaterialWaveType;
DefineBitfieldType( MaterialAnimType );
DefineEnumType( MaterialBlendOp );
DefineEnumType( MaterialWaveType );
#endif // _MATERIALDEFINITION_H_

View file

@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// 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/materialFeatureData.h"
MaterialFeatureData::MaterialFeatureData()
{
}
MaterialFeatureData::MaterialFeatureData( const MaterialFeatureData &data )
: features( data.features ),
materialFeatures( data.materialFeatures )
{
}
MaterialFeatureData::MaterialFeatureData( const FeatureSet &handle )
: features( handle )
{
}
void MaterialFeatureData::clear()
{
features.clear();
materialFeatures.clear();
}

View file

@ -0,0 +1,75 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALFEATUREDATA_H_
#define _MATERIALFEATUREDATA_H_
#ifndef _UTIL_DELEGATE_H_
#include "core/util/delegate.h"
#endif
#ifndef _FEATURESET_H_
#include "shaderGen/featureSet.h"
#endif
class ProcessedMaterial;
//-----------------------------------------------------------------------------
// MaterialFeatureData, this is basically a series of flags which a material can
// ask for. Shader processed materials will use the shadergen system to accomplish this,
// FF processed materials will do the best they can.
//-----------------------------------------------------------------------------
struct MaterialFeatureData
{
public:
// General feature data for a pass or for other purposes.
FeatureSet features;
// This is to give hints to shader creation code. It contains
// all the features that are in a material stage instead of just
// the current pass.
FeatureSet materialFeatures;
public:
MaterialFeatureData();
MaterialFeatureData( const MaterialFeatureData &data );
MaterialFeatureData( const FeatureSet &handle );
void clear();
const FeatureSet& codify() const { return features; }
};
///
typedef Delegate< void( ProcessedMaterial *mat,
U32 stageNum,
MaterialFeatureData &fd,
const FeatureSet &features) > MatFeaturesDelegate;
#endif // _MATERIALFEATUREDATA_H_

View file

@ -0,0 +1,86 @@
//-----------------------------------------------------------------------------
// 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/materialFeatureTypes.h"
ImplementFeatureType( MFT_UseInstancing, U32(-1), -1, false );
ImplementFeatureType( MFT_VertTransform, MFG_Transform, 0, true );
ImplementFeatureType( MFT_TexAnim, MFG_PreTexture, 1.0f, true );
ImplementFeatureType( MFT_Parallax, MFG_PreTexture, 2.0f, true );
ImplementFeatureType( MFT_DiffuseVertColor, MFG_PreTexture, 3.0f, true );
ImplementFeatureType( MFT_DiffuseMap, MFG_Texture, 2.0f, true );
ImplementFeatureType( MFT_OverlayMap, MFG_Texture, 3.0f, true );
ImplementFeatureType( MFT_DetailMap, MFG_Texture, 4.0f, true );
ImplementFeatureType( MFT_DiffuseColor, MFG_Texture, 5.0f, true );
ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true );
ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true );
ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true );
ImplementFeatureType( MFT_DetailNormalMap, MFG_Texture, 10.0f, true );
ImplementFeatureType( MFT_RTLighting, MFG_Lighting, 2.0f, true );
ImplementFeatureType( MFT_SubSurface, MFG_Lighting, 3.0f, true );
ImplementFeatureType( MFT_LightMap, MFG_Lighting, 4.0f, true );
ImplementFeatureType( MFT_ToneMap, MFG_Lighting, 5.0f, true );
ImplementFeatureType( MFT_VertLitTone, MFG_Lighting, 6.0f, false );
ImplementFeatureType( MFT_VertLit, MFG_Lighting, 7.0f, true );
ImplementFeatureType( MFT_EnvMap, MFG_Lighting, 8.0f, true );
ImplementFeatureType( MFT_CubeMap, MFG_Lighting, 9.0f, true );
ImplementFeatureType( MFT_PixSpecular, MFG_Lighting, 10.0f, true );
ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 12.0f, true );
ImplementFeatureType( MFT_GlowMask, MFG_PostLighting, 1.0f, true );
ImplementFeatureType( MFT_Visibility, MFG_PostLighting, 2.0f, true );
ImplementFeatureType( MFT_Fog, MFG_PostProcess, 3.0f, true );
ImplementFeatureType( MFT_HDROut, MFG_PostProcess, 999.0f, true );
ImplementFeatureType( MFT_IsDXTnm, U32(-1), -1, true );
ImplementFeatureType( MFT_IsTranslucent, U32(-1), -1, true );
ImplementFeatureType( MFT_IsTranslucentZWrite, U32(-1), -1, true );
ImplementFeatureType( MFT_IsEmissive, U32(-1), -1, true );
ImplementFeatureType( MFT_GlossMap, U32(-1), -1, true );
ImplementFeatureType( MFT_DiffuseMapAtlas, U32(-1), -1, true );
ImplementFeatureType( MFT_NormalMapAtlas, U32(-1), -1, true );
ImplementFeatureType( MFT_InterlacedPrePass, U32(-1), -1, true );
ImplementFeatureType( MFT_ParaboloidVertTransform, MFG_Transform, -1, false );
ImplementFeatureType( MFT_IsSinglePassParaboloid, U32(-1), -1, false );
ImplementFeatureType( MFT_EyeSpaceDepthOut, MFG_PostLighting, 2.0f, false );
ImplementFeatureType( MFT_DepthOut, MFG_PostLighting, 3.0f, false );
ImplementFeatureType( MFT_PrePassConditioner, MFG_PostProcess, 1.0f, false );
ImplementFeatureType( MFT_NormalsOut, MFG_PreLighting, 1.0f, false );
ImplementFeatureType( MFT_LightbufferMRT, MFG_PreLighting, 1.0f, false );
ImplementFeatureType( MFT_RenderTarget1_Zero, MFG_PreTexture, 1.0f, false );
ImplementFeatureType( MFT_Foliage, MFG_PreTransform, 1.0f, false );
ImplementFeatureType( MFT_ParticleNormal, MFG_PreTransform, 2.0f, false );
ImplementFeatureType( MFT_ForwardShading, U32(-1), -1, true );
ImplementFeatureType( MFT_ImposterVert, MFG_PreTransform, 1.0, false );

View file

@ -0,0 +1,174 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALFEATURETYPES_H_
#define _MATERIALFEATURETYPES_H_
#ifndef _FEATURETYPE_H_
#include "shaderGen/featureType.h"
#endif
///
enum MaterialFeatureGroup
{
/// One or more pre-transform features are
/// allowed at any one time and are executed
/// in order to each other.
MFG_PreTransform,
/// Only one transform feature is allowed at
/// any one time.
MFG_Transform,
///
MFG_PostTransform,
/// The features that need to occur before texturing
/// takes place. Usually these are features that will
/// manipulate or generate texture coords.
MFG_PreTexture,
/// The different diffuse color features including
/// textures and colors.
MFG_Texture,
///
MFG_PreLighting,
///
MFG_Lighting,
///
MFG_PostLighting,
/// Final features like fogging.
MFG_PostProcess,
/// Miscellaneous features that require no specialized
/// ShaderFeature object and are just queried as flags.
MFG_Misc = -1,
};
/// If defined then this shader should use hardware mesh instancing.
DeclareFeatureType( MFT_UseInstancing );
/// The standard vertex transform.
DeclareFeatureType( MFT_VertTransform );
/// A special transform with paraboloid warp used
/// in shadow and reflection rendering.
DeclareFeatureType( MFT_ParaboloidVertTransform );
/// This feature is queried from the MFT_ParaboloidVertTransform
/// feature to detect if it needs to generate a single pass.
DeclareFeatureType( MFT_IsSinglePassParaboloid );
/// This feature does normal map decompression for DXT1/5.
DeclareFeatureType( MFT_IsDXTnm );
DeclareFeatureType( MFT_TexAnim );
DeclareFeatureType( MFT_Parallax );
DeclareFeatureType( MFT_DiffuseMap );
DeclareFeatureType( MFT_OverlayMap );
DeclareFeatureType( MFT_DetailMap );
DeclareFeatureType( MFT_DiffuseColor );
DeclareFeatureType( MFT_DetailNormalMap );
/// This feature enables vertex coloring for the diffuse channel.
DeclareFeatureType( MFT_DiffuseVertColor );
/// This feature is used to do alpha test clipping in
/// the shader which can be faster on SM3 and is needed
/// when the render state alpha test is not available.
DeclareFeatureType( MFT_AlphaTest );
DeclareFeatureType( MFT_NormalMap );
DeclareFeatureType( MFT_RTLighting );
DeclareFeatureType( MFT_IsEmissive );
DeclareFeatureType( MFT_SubSurface );
DeclareFeatureType( MFT_LightMap );
DeclareFeatureType( MFT_ToneMap );
DeclareFeatureType( MFT_VertLit );
DeclareFeatureType( MFT_VertLitTone );
DeclareFeatureType( MFT_EnvMap );
DeclareFeatureType( MFT_CubeMap );
DeclareFeatureType( MFT_PixSpecular );
DeclareFeatureType( MFT_SpecularMap );
DeclareFeatureType( MFT_GlossMap );
/// This feature is only used to detect alpha transparency
/// and does not have any code associtated with it.
DeclareFeatureType( MFT_IsTranslucent );
///
DeclareFeatureType( MFT_IsTranslucentZWrite );
/// This feature causes MFT_NormalMap to set the world
/// space normal vector to the output color rgb.
DeclareFeatureType( MFT_NormalsOut );
DeclareFeatureType( MFT_MinnaertShading );
DeclareFeatureType( MFT_GlowMask );
DeclareFeatureType( MFT_Visibility );
DeclareFeatureType( MFT_EyeSpaceDepthOut );
DeclareFeatureType( MFT_DepthOut );
DeclareFeatureType( MFT_Fog );
/// This should be the last feature of any material that
/// renders to a HDR render target. It converts the high
/// dynamic range color into the correct HDR encoded format.
DeclareFeatureType( MFT_HDROut );
///
DeclareFeatureType( MFT_PrePassConditioner );
DeclareFeatureType( MFT_InterlacedPrePass );
/// This feature causes MFT_ToneMap and MFT_LightMap to output their light color
/// to the second render-target
DeclareFeatureType( MFT_LightbufferMRT );
/// This feature outputs black to RenderTarget1
DeclareFeatureType( MFT_RenderTarget1_Zero );
DeclareFeatureType( MFT_Foliage );
// Texture atlasing features
DeclareFeatureType( MFT_DiffuseMapAtlas );
DeclareFeatureType( MFT_NormalMapAtlas );
// Particle features
DeclareFeatureType( MFT_ParticleNormal );
/// This feature is used to indicate that the material should use forward shading
/// instead of deferred shading (if applicable)
DeclareFeatureType( MFT_ForwardShading );
/// A special vertex feature which unpacks the imposter vertex
/// so that the rest of the material features can work on it.
DeclareFeatureType( MFT_ImposterVert );
#endif // _MATERIALFEATURETYPES_H_

View file

@ -0,0 +1,412 @@
//-----------------------------------------------------------------------------
// 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/materialList.h"
#include "materials/matInstance.h"
#include "materials/materialManager.h"
#include "materials/materialFeatureTypes.h"
#include "materials/processedMaterial.h"
#include "core/volume.h"
#include "console/simSet.h"
MaterialList::MaterialList()
{
VECTOR_SET_ASSOCIATION(mMatInstList);
VECTOR_SET_ASSOCIATION(mMaterialNames);
}
MaterialList::MaterialList(const MaterialList* pCopy)
{
VECTOR_SET_ASSOCIATION(mMatInstList);
VECTOR_SET_ASSOCIATION(mMaterialNames);
mMaterialNames.setSize(pCopy->mMaterialNames.size());
S32 i;
for (i = 0; i < mMaterialNames.size(); i++)
{
mMaterialNames[i] = pCopy->mMaterialNames[i];
}
clearMatInstList();
mMatInstList.setSize(pCopy->size());
for( i = 0; i < mMatInstList.size(); i++ )
{
if( i < pCopy->mMatInstList.size() && pCopy->mMatInstList[i] )
{
mMatInstList[i] = pCopy->mMatInstList[i]->getMaterial()->createMatInstance();
}
else
{
mMatInstList[i] = NULL;
}
}
}
MaterialList::MaterialList(U32 materialCount, const char **materialNames)
{
VECTOR_SET_ASSOCIATION(mMaterialNames);
set(materialCount, materialNames);
}
//--------------------------------------
void MaterialList::set(U32 materialCount, const char **materialNames)
{
free();
mMaterialNames.setSize(materialCount);
clearMatInstList();
mMatInstList.setSize(materialCount);
for(U32 i = 0; i < materialCount; i++)
{
mMaterialNames[i] = materialNames[i];
mMatInstList[i] = NULL;
}
}
//--------------------------------------
MaterialList::~MaterialList()
{
free();
}
//--------------------------------------
void MaterialList::setMaterialName(U32 index, const String& name)
{
if (index < mMaterialNames.size())
mMaterialNames[index] = name;
}
//--------------------------------------
GFXTextureObject *MaterialList::getDiffuseTexture(U32 index)
{
AssertFatal(index < (U32) mMatInstList.size(), "MaterialList::getDiffuseTex: index lookup out of range.");
MatInstance *matInst = dynamic_cast<MatInstance*>(mMatInstList[index]);
if (matInst && matInst->getProcessedMaterial())
return matInst->getProcessedMaterial()->getStageTexture(0, MFT_DiffuseMap);
else
return NULL;
}
//--------------------------------------
void MaterialList::free()
{
clearMatInstList();
mMatInstList.clear();
mMaterialNames.clear();
}
/*
//--------------------------------------
U32 MaterialList::push_back(GFXTexHandle textureHandle, const String &filename)
{
mMaterialNames.push_back(filename);
mMatInstList.push_back(NULL);
// return the index
return mMaterialNames.size()-1;
}
*/
//--------------------------------------
U32 MaterialList::push_back(const String &filename, Material* material)
{
mMaterialNames.push_back(filename);
mMatInstList.push_back(material ? material->createMatInstance() : NULL);
// return the index
return mMaterialNames.size()-1;
}
//--------------------------------------
bool MaterialList::read(Stream &stream)
{
free();
// check the stream version
U8 version;
if ( stream.read(&version) && version != BINARY_FILE_VERSION)
return readText(stream,version);
// how many materials?
U32 count;
if ( !stream.read(&count) )
return false;
// pre-size the vectors for efficiency
mMaterialNames.reserve(count);
// read in the materials
for (U32 i=0; i<count; i++)
{
// Load the bitmap name
char buffer[256];
stream.readString(buffer);
if( !buffer[0] )
{
AssertWarn(0, "MaterialList::read: error reading stream");
return false;
}
// Material paths are a legacy of Tribes tools,
// strip them off...
char *name = &buffer[dStrlen(buffer)];
while (name != buffer && name[-1] != '/' && name[-1] != '\\')
name--;
// Add it to the list
mMaterialNames.push_back(name);
mMatInstList.push_back(NULL);
}
return (stream.getStatus() == Stream::Ok);
}
//--------------------------------------
bool MaterialList::write(Stream &stream)
{
stream.write((U8)BINARY_FILE_VERSION); // version
stream.write((U32)mMaterialNames.size()); // material count
for(S32 i=0; i < mMaterialNames.size(); i++) // material names
stream.writeString(mMaterialNames[i]);
return (stream.getStatus() == Stream::Ok);
}
//--------------------------------------
bool MaterialList::readText(Stream &stream, U8 firstByte)
{
free();
if (!firstByte)
return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);
char buf[1024];
buf[0] = firstByte;
U32 offset = 1;
for(;;)
{
stream.readLine((U8*)(buf+offset), sizeof(buf)-offset);
if(!buf[0])
break;
offset = 0;
// Material paths are a legacy of Tribes tools,
// strip them off...
char *name = &buf[dStrlen(buf)];
while (name != buf && name[-1] != '/' && name[-1] != '\\')
name--;
// Add it to the list
mMaterialNames.push_back(name);
mMatInstList.push_back(NULL);
}
return (stream.getStatus() == Stream::Ok || stream.getStatus() == Stream::EOS);
}
bool MaterialList::readText(Stream &stream)
{
U8 firstByte;
stream.read(&firstByte);
return readText(stream,firstByte);
}
//--------------------------------------
bool MaterialList::writeText(Stream &stream)
{
for(S32 i=0; i < mMaterialNames.size(); i++)
stream.writeLine((U8*)(mMaterialNames[i].c_str()));
stream.writeLine((U8*)"");
return (stream.getStatus() == Stream::Ok);
}
//--------------------------------------------------------------------------
// Clear all materials in the mMatInstList member variable
//--------------------------------------------------------------------------
void MaterialList::clearMatInstList()
{
// clear out old materials. any non null element of the list should be pointing at deletable memory,
// although multiple indexes may be pointing at the same memory so we have to be careful (see
// comment in loop body)
for (U32 i=0; i<mMatInstList.size(); i++)
{
if (mMatInstList[i])
{
BaseMatInstance* current = mMatInstList[i];
delete current;
mMatInstList[i] = NULL;
// ok, since ts material lists can remap difference indexes to the same object
// we need to make sure that we don't delete the same memory twice. walk the
// rest of the list and null out any pointers that match the one we deleted.
for (U32 j=0; j<mMatInstList.size(); j++)
if (mMatInstList[j] == current)
mMatInstList[j] = NULL;
}
}
}
//--------------------------------------------------------------------------
// Map materials - map materials to the textures in the list
//--------------------------------------------------------------------------
void MaterialList::mapMaterials()
{
mMatInstList.setSize( mMaterialNames.size() );
for( U32 i=0; i<mMaterialNames.size(); i++ )
mapMaterial( i );
}
/// Map the material name at the given index to a material instance.
///
/// @note The material instance that is created will <em>not be initialized.</em>
void MaterialList::mapMaterial( U32 i )
{
AssertFatal( i < size(), "MaterialList::mapMaterialList - index out of bounds" );
if( mMatInstList[i] != NULL )
return;
// lookup a material property entry
const String &matName = getMaterialName(i);
// JMQ: this code assumes that all materials have names.
if( matName.isEmpty() )
{
mMatInstList[i] = NULL;
return;
}
String materialName = MATMGR->getMapEntry(matName);
// IF we didn't find it, then look for a PolyStatic generated Material
// [a little cheesy, but we need to allow for user override of generated Materials]
if ( materialName.isEmpty() )
materialName = MATMGR->getMapEntry( String::ToString( "polyMat_%s", matName.c_str() ) );
if ( materialName.isNotEmpty() )
{
Material * mat = MATMGR->getMaterialDefinitionByName( materialName );
mMatInstList[i] = mat ? mat->createMatInstance() : MATMGR->createWarningMatInstance();
}
else
{
if ( Con::getBoolVariable( "$Materials::createMissing", true ) )
{
// No Material found, create new "default" material with just a diffuseMap
// First see if there is a valid diffuse texture
GFXTexHandle texHandle;
if (mLookupPath.isEmpty())
{
texHandle.set( mMaterialNames[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
}
else
{
// Should we strip off the extension of the path here before trying
// to load the texture?
String fullPath = String::ToString( "%s/%s", mLookupPath.c_str(), mMaterialNames[i].c_str() );
texHandle.set( fullPath, &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
}
if ( texHandle.isValid() )
{
String newMatName = Sim::getUniqueName( "DefaultMaterial" );
Material *newMat = MATMGR->allocateAndRegister( newMatName, mMaterialNames[i] );
// Flag this as an autogenerated Material
newMat->mAutoGenerated = true;
// Overwrite diffuseMap in new material
newMat->mDiffuseMapFilename[0] = texHandle->mTextureLookupName;
// Set up some defaults for transparent textures
if (texHandle->mHasTransparency)
{
newMat->mTranslucent = true;
newMat->mTranslucentBlendOp = Material::LerpAlpha;
newMat->mTranslucentZWrite = true;
newMat->mAlphaRef = 20;
}
// create a MatInstance for the new material
mMatInstList[i] = newMat->createMatInstance();
#ifndef TORQUE_SHIPPING
Con::warnf( "[MaterialList::mapMaterials] Creating missing material for texture: %s", texHandle->mTextureLookupName.c_str() );
#endif
}
else
{
Con::errorf( "[MaterialList::mapMaterials] Unable to find material for texture: %s", mMaterialNames[i].c_str() );
mMatInstList[i] = MATMGR->createWarningMatInstance();
}
}
else
{
mMatInstList[i] = MATMGR->createWarningMatInstance();
}
}
}
void MaterialList::initMatInstances( const FeatureSet &features,
const GFXVertexFormat *vertexFormat )
{
for( U32 i=0; i < mMatInstList.size(); i++ )
{
BaseMatInstance *matInst = mMatInstList[i];
if ( !matInst )
continue;
if ( !matInst->init( features, vertexFormat ) )
{
Con::errorf( "MaterialList::initMatInstances - failed to initialize material instance for '%s'",
matInst->getMaterial()->getName() );
// Fall back to warning material.
SAFE_DELETE( matInst );
matInst = MATMGR->createMatInstance( "WarningMaterial" );
matInst->init( MATMGR->getDefaultFeatures(), vertexFormat );
mMatInstList[ i ] = matInst;
}
}
}
void MaterialList::setMaterialInst( BaseMatInstance *matInst, U32 texIndex )
{
AssertFatal( texIndex < mMatInstList.size(), "MaterialList::setMaterialInst - index out of bounds" );
mMatInstList[texIndex] = matInst;
}

View file

@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALLIST_H_
#define _MATERIALLIST_H_
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _GFXTEXTUREHANDLE_H_
#include "gfx/gfxTextureHandle.h"
#endif
class Material;
class BaseMatInstance;
class Stream;
class GFXVertexFormat;
class FeatureSet;
class MaterialList
{
public:
MaterialList();
MaterialList(U32 materialCount, const char **materialNames);
virtual ~MaterialList();
/// Note: this is not to be confused with MaterialList(const MaterialList&). Copying
/// a material list in the middle of it's lifetime is not a good thing, so we force
/// it to copy at construction time by restricting the copy syntax to
/// ML* pML = new ML(&copy);
explicit MaterialList(const MaterialList*);
const Vector<String> &getMaterialNameList() const { return mMaterialNames; }
const String &getMaterialName(U32 index) const { return mMaterialNames[index]; }
GFXTextureObject *getDiffuseTexture(U32 index);
void setTextureLookupPath(const String& path) { mLookupPath = path; }
void setMaterialName(U32 index, const String& name);
void set(U32 materialCount, const char **materialNames);
U32 push_back(const String &filename, Material* = 0);
virtual void free();
void clearMatInstList();
bool empty() const { return mMaterialNames.empty(); }
U32 size() const { return (U32)mMaterialNames.size(); }
bool read(Stream &stream);
bool write(Stream &stream);
bool readText(Stream &stream, U8 firstByte);
bool readText(Stream &stream);
bool writeText(Stream &stream);
void mapMaterials();
/// Initialize material instances in material list.
void initMatInstances( const FeatureSet &features,
const GFXVertexFormat *vertexFormat );
/// Return the material instance or NULL if the
/// index is out of bounds.
inline BaseMatInstance* getMaterialInst( U32 index ) const
{
return index < mMatInstList.size() ? mMatInstList[index] : NULL;
}
void setMaterialInst( BaseMatInstance *matInst, U32 index );
// Needs to be accessible if were going to freely edit instances
Vector<BaseMatInstance*> mMatInstList;
protected:
String mLookupPath;
Vector<String> mMaterialNames; //!< Material 'mapTo' targets
virtual void mapMaterial( U32 index );
private:
enum Constants { BINARY_FILE_VERSION = 1 };
};
#endif // _MATERIALLIST_H_

View file

@ -0,0 +1,491 @@
//-----------------------------------------------------------------------------
// 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/materialManager.h"
#include "materials/matInstance.h"
#include "materials/materialFeatureTypes.h"
#include "lighting/lightManager.h"
#include "core/util/safeDelete.h"
#include "shaderGen/shaderGen.h"
#include "core/module.h"
#include "console/consoleTypes.h"
MODULE_BEGIN( MaterialManager )
MODULE_INIT_BEFORE( GFX )
MODULE_SHUTDOWN_BEFORE( GFX )
MODULE_INIT
{
MaterialManager::createSingleton();
}
MODULE_SHUTDOWN
{
MaterialManager::deleteSingleton();
}
MODULE_END;
MaterialManager::MaterialManager()
{
VECTOR_SET_ASSOCIATION( mMatInstanceList );
mDt = 0.0f;
mAccumTime = 0.0f;
mLastTime = 0;
mWarningInst = NULL;
GFXDevice::getDeviceEventSignal().notify( this, &MaterialManager::_handleGFXEvent );
// Make sure we get activation signals
// and that we're the last to get them.
LightManager::smActivateSignal.notify( this, &MaterialManager::_onLMActivate, 9999 );
mMaterialSet = NULL;
mUsingPrePass = false;
mFlushAndReInit = false;
mDefaultAnisotropy = 1;
Con::addVariable( "$pref::Video::defaultAnisotropy", TypeS32, &mDefaultAnisotropy,
"@brief Global variable defining the default anisotropy value.\n\n"
"Controls the default anisotropic texture filtering level for all materials, including the terrain. "
"This value can be changed at runtime to see its affect without reloading.\n\n "
"@ingroup Materials");
Con::NotifyDelegate callabck( this, &MaterialManager::_updateDefaultAnisotropy );
Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck );
Con::NotifyDelegate callabck2( this, &MaterialManager::_onDisableMaterialFeature );
Con::setVariable( "$pref::Video::disableNormalMapping", false );
Con::addVariableNotify( "$pref::Video::disableNormalMapping", callabck2 );
Con::setVariable( "$pref::Video::disablePixSpecular", false );
Con::addVariableNotify( "$pref::Video::disablePixSpecular", callabck2 );
Con::setVariable( "$pref::Video::disableCubemapping", false );
Con::addVariableNotify( "$pref::Video::disableCubemapping", callabck2 );
Con::setVariable( "$pref::Video::disableParallaxMapping", false );
Con::addVariableNotify( "$pref::Video::disableParallaxMapping", callabck2 );
}
MaterialManager::~MaterialManager()
{
GFXDevice::getDeviceEventSignal().remove( this, &MaterialManager::_handleGFXEvent );
LightManager::smActivateSignal.remove( this, &MaterialManager::_onLMActivate );
SAFE_DELETE( mWarningInst );
#ifndef TORQUE_SHIPPING
DebugMaterialMap::Iterator itr = mMeshDebugMaterialInsts.begin();
for ( ; itr != mMeshDebugMaterialInsts.end(); itr++ )
delete itr->value;
#endif
}
void MaterialManager::_onLMActivate( const char *lm, bool activate )
{
if ( !activate )
return;
// Since the light manager usually swaps shadergen features
// and changes system wide shader defines we need to completely
// flush and rebuild all the material instances.
mFlushAndReInit = true;
}
void MaterialManager::_updateDefaultAnisotropy()
{
// Update all the materials.
Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
for ( ; iter != mMatInstanceList.end(); iter++ )
(*iter)->updateStateBlocks();
}
Material * MaterialManager::allocateAndRegister(const String &objectName, const String &mapToName)
{
Material *newMat = new Material();
if ( mapToName.isNotEmpty() )
newMat->mMapTo = mapToName;
bool registered = newMat->registerObject(objectName );
AssertFatal( registered, "Unable to register material" );
if (registered)
Sim::getRootGroup()->addObject( newMat );
else
{
delete newMat;
newMat = NULL;
}
return newMat;
}
Material * MaterialManager::getMaterialDefinitionByName(const String &matName)
{
// Get the material
Material * foundMat;
if(!Sim::findObject(matName, foundMat))
{
Con::errorf("MaterialManager: Unable to find material '%s'", matName.c_str());
return NULL;
}
return foundMat;
}
BaseMatInstance* MaterialManager::createMatInstance(const String &matName)
{
BaseMaterialDefinition* mat = NULL;
if (Sim::findObject(matName, mat))
return mat->createMatInstance();
return NULL;
}
BaseMatInstance* MaterialManager::createMatInstance( const String &matName,
const GFXVertexFormat *vertexFormat )
{
return createMatInstance( matName, getDefaultFeatures(), vertexFormat );
}
BaseMatInstance* MaterialManager::createMatInstance( const String &matName,
const FeatureSet& features,
const GFXVertexFormat *vertexFormat )
{
BaseMatInstance* mat = createMatInstance(matName);
if (mat)
{
mat->init( features, vertexFormat );
return mat;
}
return NULL;
}
BaseMatInstance * MaterialManager::createWarningMatInstance()
{
Material *warnMat = static_cast<Material*>(Sim::findObject("WarningMaterial"));
BaseMatInstance *warnMatInstance = NULL;
if( warnMat != NULL )
{
warnMatInstance = warnMat->createMatInstance();
GFXStateBlockDesc desc;
desc.setCullMode(GFXCullNone);
warnMatInstance->addStateBlockDesc(desc);
warnMatInstance->init( getDefaultFeatures(),
getGFXVertexFormat<GFXVertexPNTTB>() );
}
return warnMatInstance;
}
// Gets the global warning material instance, callers should not free this copy
BaseMatInstance * MaterialManager::getWarningMatInstance()
{
if (!mWarningInst)
mWarningInst = createWarningMatInstance();
return mWarningInst;
}
#ifndef TORQUE_SHIPPING
BaseMatInstance * MaterialManager::createMeshDebugMatInstance(const ColorF &meshColor)
{
String meshDebugStr = String::ToString( "Torque_MeshDebug_%d", meshColor.getRGBAPack() );
Material *debugMat;
if (!Sim::findObject(meshDebugStr,debugMat))
{
debugMat = allocateAndRegister( meshDebugStr );
debugMat->mDiffuse[0] = meshColor;
debugMat->mEmissive[0] = true;
}
BaseMatInstance *debugMatInstance = NULL;
if( debugMat != NULL )
{
debugMatInstance = debugMat->createMatInstance();
GFXStateBlockDesc desc;
desc.setCullMode(GFXCullNone);
desc.fillMode = GFXFillWireframe;
debugMatInstance->addStateBlockDesc(desc);
// Disable fog and other stuff.
FeatureSet debugFeatures;
debugFeatures.addFeature( MFT_DiffuseColor );
debugMatInstance->init( debugFeatures, getGFXVertexFormat<GFXVertexPCN>() );
}
return debugMatInstance;
}
// Gets the global material instance for a given color, callers should not free this copy
BaseMatInstance *MaterialManager::getMeshDebugMatInstance(const ColorF &meshColor)
{
DebugMaterialMap::Iterator itr = mMeshDebugMaterialInsts.find( meshColor.getRGBAPack() );
BaseMatInstance *inst = NULL;
if ( itr == mMeshDebugMaterialInsts.end() )
inst = createMeshDebugMatInstance( meshColor );
else
inst = itr->value;
mMeshDebugMaterialInsts.insert( meshColor.getRGBAPack(), inst );
return inst;
}
#endif
void MaterialManager::mapMaterial(const String & textureName, const String & materialName)
{
if (getMapEntry(textureName).isNotEmpty())
{
if (!textureName.equal("unmapped_mat", String::NoCase))
Con::warnf(ConsoleLogEntry::General, "Warning, overwriting material for: %s", textureName.c_str());
}
mMaterialMap[String::ToLower(textureName)] = materialName;
}
String MaterialManager::getMapEntry(const String & textureName) const
{
MaterialMap::ConstIterator iter = mMaterialMap.find(String::ToLower(textureName));
if ( iter == mMaterialMap.end() )
return String();
return iter->value;
}
void MaterialManager::flushAndReInitInstances()
{
// Clear the flag if its set.
mFlushAndReInit = false;
// Check to see if any shader preferences have changed.
recalcFeaturesFromPrefs();
// First we flush all the shader gen shaders which will
// invalidate all GFXShader* to them.
SHADERGEN->flushProceduralShaders();
mFlushSignal.trigger();
// First do a pass deleting all hooks as they can contain
// materials themselves. This means we have to restart the
// loop every time we delete any hooks... lame.
Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
while ( iter != mMatInstanceList.end() )
{
if ( (*iter)->deleteAllHooks() != 0 )
{
// Restart the loop.
iter = mMatInstanceList.begin();
continue;
}
iter++;
}
// Now do a pass re-initializing materials.
iter = mMatInstanceList.begin();
for ( ; iter != mMatInstanceList.end(); iter++ )
(*iter)->reInit();
}
// Used in the materialEditor. This flushes the material preview object so it can be reloaded easily.
void MaterialManager::flushInstance( BaseMaterialDefinition *target )
{
Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
while ( iter != mMatInstanceList.end() )
{
if ( (*iter)->getMaterial() == target )
{
(*iter)->deleteAllHooks();
return;
}
iter++;
}
}
void MaterialManager::reInitInstance( BaseMaterialDefinition *target )
{
Vector<BaseMatInstance*>::iterator iter = mMatInstanceList.begin();
for ( ; iter != mMatInstanceList.end(); iter++ )
{
if ( (*iter)->getMaterial() == target )
(*iter)->reInit();
}
}
void MaterialManager::updateTime()
{
U32 curTime = Sim::getCurrentTime();
if(curTime > mLastTime)
{
mDt = (curTime - mLastTime) / 1000.0f;
mLastTime = curTime;
mAccumTime += mDt;
}
else
mDt = 0.0f;
}
SimSet * MaterialManager::getMaterialSet()
{
if(!mMaterialSet)
mMaterialSet = static_cast<SimSet*>( Sim::findObject( "MaterialSet" ) );
AssertFatal( mMaterialSet, "MaterialSet not found" );
return mMaterialSet;
}
void MaterialManager::dumpMaterialInstances( BaseMaterialDefinition *target ) const
{
if ( !mMatInstanceList.size() )
return;
if ( target )
Con::printf( "--------------------- %s MatInstances ---------------------", target->getName() );
else
Con::printf( "--------------------- MatInstances %d ---------------------", mMatInstanceList.size() );
for( U32 i=0; i<mMatInstanceList.size(); i++ )
{
BaseMatInstance *inst = mMatInstanceList[i];
if ( target && inst->getMaterial() != target )
continue;
inst->dumpShaderInfo();
Con::printf( "" );
}
Con::printf( "---------------------- Dump complete ----------------------");
}
void MaterialManager::_track( MatInstance *matInstance )
{
mMatInstanceList.push_back( matInstance );
}
void MaterialManager::_untrack( MatInstance *matInstance )
{
mMatInstanceList.remove( matInstance );
}
void MaterialManager::recalcFeaturesFromPrefs()
{
mDefaultFeatures.clear();
FeatureType::addDefaultTypes( &mDefaultFeatures );
mExclusionFeatures.setFeature( MFT_NormalMap,
Con::getBoolVariable( "$pref::Video::disableNormalMapping", false ) );
mExclusionFeatures.setFeature( MFT_PixSpecular,
Con::getBoolVariable( "$pref::Video::disablePixSpecular", false ) );
mExclusionFeatures.setFeature( MFT_CubeMap,
Con::getBoolVariable( "$pref::Video::disableCubemapping", false ) );
mExclusionFeatures.setFeature( MFT_Parallax,
Con::getBoolVariable( "$pref::Video::disableParallaxMapping", false ) );
}
bool MaterialManager::_handleGFXEvent( GFXDevice::GFXDeviceEventType event_ )
{
switch ( event_ )
{
case GFXDevice::deInit:
recalcFeaturesFromPrefs();
break;
case GFXDevice::deDestroy :
SAFE_DELETE( mWarningInst );
break;
case GFXDevice::deStartOfFrame:
if ( mFlushAndReInit )
flushAndReInitInstances();
break;
default:
break;
}
return true;
}
ConsoleFunction( reInitMaterials, void, 1, 1,
"@brief Flushes all procedural shaders and re-initializes all active material instances.\n\n"
"@ingroup Materials")
{
MATMGR->flushAndReInitInstances();
}
ConsoleFunction( addMaterialMapping, void, 3, 3, "(string texName, string matName)\n"
"@brief Maps the given texture to the given material.\n\n"
"Generates a console warning before overwriting.\n\n"
"Material maps are used by terrain and interiors for triggering "
"effects when an object moves onto a terrain "
"block or interior surface using the associated texture.\n\n"
"@ingroup Materials")
{
MATMGR->mapMaterial(argv[1],argv[2]);
}
ConsoleFunction( getMaterialMapping, const char*, 2, 2, "(string texName)\n"
"@brief Returns the name of the material mapped to this texture.\n\n"
"If no materials are found, an empty string is returned.\n\n"
"@param texName Name of the texture\n\n"
"@ingroup Materials")
{
return MATMGR->getMapEntry(argv[1]).c_str();
}
ConsoleFunction( dumpMaterialInstances, void, 1, 1,
"@brief Dumps a formatted list of currently allocated material instances to the console.\n\n"
"@ingroup Materials")
{
MATMGR->dumpMaterialInstances();
}
ConsoleFunction( getMapEntry, const char *, 2, 2,
"@hide")
{
return MATMGR->getMapEntry( String(argv[1]) );
}

View file

@ -0,0 +1,184 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIAL_MGR_H_
#define _MATERIAL_MGR_H_
#ifndef _MATERIALDEFINITION_H_
#include "materials/materialDefinition.h"
#endif
#ifndef _FEATURESET_H_
#include "shaderGen/featureSet.h"
#endif
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
#ifndef _TSINGLETON_H_
#include "core/util/tSingleton.h"
#endif
class SimSet;
class MatInstance;
class MaterialManager : public ManagedSingleton<MaterialManager>
{
public:
MaterialManager();
~MaterialManager();
// ManagedSingleton
static const char* getSingletonName() { return "MaterialManager"; }
Material * allocateAndRegister(const String &objectName, const String &mapToName = String());
Material * getMaterialDefinitionByName(const String &matName);
SimSet * getMaterialSet();
// map textures to materials
void mapMaterial(const String & textureName, const String & materialName);
String getMapEntry(const String & textureName) const;
// Return instance of named material caller is responsible for memory
BaseMatInstance * createMatInstance( const String &matName );
// Create a BaseMatInstance with the default feature flags.
BaseMatInstance * createMatInstance( const String &matName, const GFXVertexFormat *vertexFormat );
BaseMatInstance * createMatInstance( const String &matName, const FeatureSet &features, const GFXVertexFormat *vertexFormat );
/// The default feature set for materials.
const FeatureSet& getDefaultFeatures() const { return mDefaultFeatures; }
/// The feature exclusion list for disabling features.
const FeatureSet& getExclusionFeatures() const { return mExclusionFeatures; }
void recalcFeaturesFromPrefs();
/// Get the default texture anisotropy.
U32 getDefaultAnisotropy() const { return mDefaultAnisotropy; }
/// Allocate and return an instance of special materials. Caller is responsible for the memory.
BaseMatInstance * createWarningMatInstance();
/// Gets the global warning material instance, callers should not free this copy
BaseMatInstance * getWarningMatInstance();
/// Set the prepass enabled state.
void setPrePassEnabled( bool enabled ) { mUsingPrePass = enabled; }
/// Get the prepass enabled state.
bool getPrePassEnabled() const { return mUsingPrePass; }
#ifndef TORQUE_SHIPPING
// Allocate and return an instance of mesh debugging materials. Caller is responsible for the memory.
BaseMatInstance * createMeshDebugMatInstance(const ColorF &meshColor);
// Gets the global material instance for a given color, callers should not free this copy
BaseMatInstance * getMeshDebugMatInstance(const ColorF &meshColor);
#endif
void dumpMaterialInstances( BaseMaterialDefinition *target = NULL ) const;
void updateTime();
F32 getTotalTime() const { return mAccumTime; }
F32 getDeltaTime() const { return mDt; }
U32 getLastUpdateTime() const { return mLastTime; }
/// Signal used to notify systems that
/// procedural shaders have been flushed.
typedef Signal<void()> FlushSignal;
/// Returns the signal used to notify systems that the
/// procedural shaders have been flushed.
FlushSignal& getFlushSignal() { return mFlushSignal; }
/// Flushes all the procedural shaders and re-initializes all
/// the active materials instances immediately.
void flushAndReInitInstances();
// Flush the instance
void flushInstance( BaseMaterialDefinition *target );
/// Re-initializes the material instances for a specific target material.
void reInitInstance( BaseMaterialDefinition *target );
protected:
// MatInstance tracks it's instances here
friend class MatInstance;
void _track(MatInstance*);
void _untrack(MatInstance*);
/// @see LightManager::smActivateSignal
void _onLMActivate( const char *lm, bool activate );
bool _handleGFXEvent(GFXDevice::GFXDeviceEventType event);
SimSet* mMaterialSet;
Vector<BaseMatInstance*> mMatInstanceList;
/// The default material features.
FeatureSet mDefaultFeatures;
/// The feature exclusion set.
FeatureSet mExclusionFeatures;
/// Signal used to notify systems that
/// procedural shaders have been flushed.
FlushSignal mFlushSignal;
/// If set we flush and reinitialize all materials at the
/// start of the next rendered frame.
bool mFlushAndReInit;
// material map
typedef Map<String, String> MaterialMap;
MaterialMap mMaterialMap;
bool mUsingPrePass;
// time tracking
F32 mDt;
F32 mAccumTime;
U32 mLastTime;
BaseMatInstance* mWarningInst;
/// The default max anisotropy used in texture filtering.
S32 mDefaultAnisotropy;
/// Called when $pref::Video::defaultAnisotropy is changed.
void _updateDefaultAnisotropy();
/// Called when one of the feature disabling $pref::s are changed.
void _onDisableMaterialFeature() { mFlushAndReInit = true; }
#ifndef TORQUE_SHIPPING
typedef Map<U32, BaseMatInstance *> DebugMaterialMap;
DebugMaterialMap mMeshDebugMaterialInsts;
#endif
};
/// Helper for accessing MaterialManager singleton.
#define MATMGR MaterialManager::instance()
#endif // _MATERIAL_MGR_H_

View file

@ -0,0 +1,99 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALPARAMETERS_H_
#define _MATERIALPARAMETERS_H_
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
///
/// Similar class to GFXShaderConsts, but this is to describe generic material parameters.
///
class MaterialParameterHandle
{
public:
virtual ~MaterialParameterHandle() {}
virtual const String& getName() const = 0;
// This is similar to GFXShaderConstHandle, but a Material will always return a handle when
// asked for one. Even if it doesn't have that material parameter. This is because after a
// reInitMaterials call, the constants can change underneath the MatInstance.
// Note: GFXShaderConstHandle actually works this way too, now.
virtual bool isValid() const = 0;
/// Returns -1 if this handle does not point to a Sampler.
virtual S32 getSamplerRegister( U32 pass ) const = 0;
};
class MaterialParameters
{
public:
MaterialParameters()
{
VECTOR_SET_ASSOCIATION( mShaderConstDesc );
}
virtual ~MaterialParameters() {}
/// Returns our list of shader constants, the material can get this and just set the constants it knows about
virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const { return mShaderConstDesc; }
/// An inline helper which ensures the handle is valid
/// before the virtual set method is called.
template< typename VALUE >
inline void setSafe( MaterialParameterHandle *handle, const VALUE& v )
{
if ( handle->isValid() )
set( handle, v );
}
/// @name Set shader constant values
/// @{
/// Actually set shader constant values
/// @param name Name of the constant, this should be a name contained in the array returned in getShaderConstDesc,
/// if an invalid name is used, it is ignored.
virtual void set(MaterialParameterHandle* handle, const F32 f) {}
virtual void set(MaterialParameterHandle* handle, const Point2F& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point3F& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point4F& fv) {}
virtual void set(MaterialParameterHandle* handle, const ColorF& fv) {}
virtual void set(MaterialParameterHandle* handle, const S32 f) {}
virtual void set(MaterialParameterHandle* handle, const Point2I& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point3I& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point4I& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv) {}
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv) {}
virtual void set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType = GFXSCT_Float4x4) {}
virtual void set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4) {}
/// Returns the alignment value for the constType in bytes.
virtual U32 getAlignmentValue(const GFXShaderConstType constType) { return 0; }
protected:
Vector<GFXShaderConstDesc> mShaderConstDesc;
};
#endif

View file

@ -0,0 +1,57 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MISCSHDRDAT_H_
#define _MISCSHDRDAT_H_
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
//**************************************************************************
// This file is an attempt to keep certain classes from having to know about
// the ShaderGen class
//**************************************************************************
//-----------------------------------------------------------------------
// Enums
//-----------------------------------------------------------------------
enum RegisterType
{
RT_POSITION = 0,
RT_NORMAL,
RT_BINORMAL,
RT_TANGENT,
RT_COLOR,
RT_TEXCOORD,
RT_VPOS,
};
enum Components
{
C_VERT_STRUCT = 0,
C_CONNECTOR,
C_VERT_MAIN,
C_PIX_MAIN,
};
#endif // _MISCSHDRDAT_H_

View file

@ -0,0 +1,498 @@
//-----------------------------------------------------------------------------
// 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/processedCustomMaterial.h"
#include "gfx/sim/cubemapData.h"
#include "materials/sceneData.h"
#include "shaderGen/shaderGenVars.h"
#include "scene/sceneRenderState.h"
#include "materials/customMaterialDefinition.h"
#include "materials/shaderData.h"
#include "materials/materialManager.h"
#include "materials/matTextureTarget.h"
#include "materials/materialFeatureTypes.h"
#include "materials/materialParameters.h"
#include "gfx/sim/gfxStateBlockData.h"
#include "core/util/safeDelete.h"
#include "gfx/genericConstBuffer.h"
#include "console/simFieldDictionary.h"
#include "console/propertyParsing.h"
#include "gfx/util/screenspace.h"
ProcessedCustomMaterial::ProcessedCustomMaterial(Material &mat)
{
mMaterial = &mat;
AssertFatal(dynamic_cast<CustomMaterial*>(mMaterial), "Incompatible Material type!");
mCustomMaterial = static_cast<CustomMaterial*>(mMaterial);
mHasSetStageData = false;
mHasGlow = false;
mMaxStages = 0;
mMaxTex = 0;
}
ProcessedCustomMaterial::~ProcessedCustomMaterial()
{
}
void ProcessedCustomMaterial::_setStageData()
{
// Only do this once
if ( mHasSetStageData )
return;
mHasSetStageData = true;
ShaderRenderPassData* rpd = _getRPD(0);
mConditionerMacros.clear();
// Loop through all the possible textures, set the right flags, and load them if needed
for(U32 i=0; i<CustomMaterial::MAX_TEX_PER_PASS; i++ )
{
rpd->mTexType[i] = Material::NoTexture; // Set none as the default in case none of the cases below catch it.
String filename = mCustomMaterial->mTexFilename[i];
if(filename.isEmpty())
continue;
if(filename.equal(String("$dynamiclight"), String::NoCase))
{
rpd->mTexType[i] = Material::DynamicLight;
mMaxTex = i+1;
continue;
}
if(filename.equal(String("$dynamiclightmask"), String::NoCase))
{
rpd->mTexType[i] = Material::DynamicLightMask;
mMaxTex = i+1;
continue;
}
if(filename.equal(String("$lightmap"), String::NoCase))
{
rpd->mTexType[i] = Material::Lightmap;
mMaxTex = i+1;
continue;
}
if(filename.equal(String("$cubemap"), String::NoCase))
{
if( mCustomMaterial->mCubemapData )
{
rpd->mTexType[i] = Material::Cube;
mMaxTex = i+1;
}
else
{
mCustomMaterial->logError( "Could not find CubemapData - %s", mCustomMaterial->mCubemapName.c_str());
}
continue;
}
if(filename.equal(String("$dynamicCubemap"), String::NoCase))
{
rpd->mTexType[i] = Material::SGCube;
mMaxTex = i+1;
continue;
}
if(filename.equal(String("$backbuff"), String::NoCase))
{
rpd->mTexType[i] = Material::BackBuff;
mMaxTex = i+1;
continue;
}
if(filename.equal(String("$reflectbuff"), String::NoCase))
{
rpd->mTexType[i] = Material::ReflectBuff;
mMaxTex = i+1;
continue;
}
if(filename.equal(String("$miscbuff"), String::NoCase))
{
rpd->mTexType[i] = Material::Misc;
mMaxTex = i+1;
continue;
}
// Check for a RenderTexTargetBin assignment
if (filename.substr( 0, 1 ).equal("#"))
{
String texTargetBufferName = filename.substr(1, filename.length() - 1);
NamedTexTarget *texTarget = NamedTexTarget::find( texTargetBufferName );
rpd->mTexSlot[i].texTarget = texTarget;
// Get the conditioner macros.
if ( texTarget )
texTarget->getShaderMacros( &mConditionerMacros );
rpd->mTexType[i] = Material::TexTarget;
mMaxTex = i+1;
continue;
}
rpd->mTexSlot[i].texObject = _createTexture( filename, &GFXDefaultStaticDiffuseProfile );
if ( !rpd->mTexSlot[i].texObject )
{
mMaterial->logError("Failed to load texture %s", _getTexturePath(filename).c_str());
continue;
}
rpd->mTexType[i] = Material::Standard;
mMaxTex = i+1;
}
// We only get one cubemap
if( mCustomMaterial->mCubemapData )
{
mCustomMaterial->mCubemapData->createMap();
rpd->mCubeMap = mMaterial->mCubemapData->mCubemap; // BTRTODO ?
if ( !rpd->mCubeMap )
mMaterial->logError("Failed to load cubemap");
}
// If this has a output target defined, it may be writing
// to a tex target bin with a conditioner, so search for
// one and add its macros.
if ( mCustomMaterial->mOutputTarget.isNotEmpty() )
{
NamedTexTarget *texTarget = NamedTexTarget::find( mCustomMaterial->mOutputTarget );
if ( texTarget )
texTarget->getShaderMacros( &mConditionerMacros );
}
// Copy the glow state over.
mHasGlow = mCustomMaterial->mGlow[0];
}
bool ProcessedCustomMaterial::init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat,
const MatFeaturesDelegate &featuresDelegate )
{
// If we don't have a shader data... we have nothing to do.
if ( !mCustomMaterial->mShaderData )
return true;
// Custom materials only do one pass at the moment... so
// add one for the stage data to fill in.
ShaderRenderPassData *rpd = new ShaderRenderPassData();
mPasses.push_back( rpd );
_setStageData();
_initPassStateBlocks();
mStateHint.clear();
// Note: We don't use the vertex format in a custom
// material at all right now.
//
// Maybe we can add some required semantics and
// validate that the format fits the shader?
// Build a composite list of shader macros from
// the conditioner and the user defined lists.
Vector<GFXShaderMacro> macros;
macros.merge( mConditionerMacros );
macros.merge( mUserMacros );
// Ask the shader data to give us a shader instance.
rpd->shader = mCustomMaterial->mShaderData->getShader( macros );
if ( !rpd->shader )
{
delete rpd;
mPasses.clear();
return false;
}
rpd->shaderHandles.init( rpd->shader, mCustomMaterial );
_initMaterialParameters();
mDefaultParameters = allocMaterialParameters();
setMaterialParameters( mDefaultParameters, 0 );
mStateHint.init( this );
return true;
}
void ProcessedCustomMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc &result )
{
Parent::_initPassStateBlock( rpd, result );
if (mCustomMaterial->getStateBlockData())
result.addDesc(mCustomMaterial->getStateBlockData()->getState());
}
void ProcessedCustomMaterial::_initPassStateBlocks()
{
AssertFatal(mHasSetStageData, "State data must be set before initializing state block!");
ShaderRenderPassData* rpd = _getRPD(0);
_initRenderStateStateBlocks( rpd );
}
bool ProcessedCustomMaterial::_hasCubemap(U32 pass)
{
// If the material doesn't have a cubemap, we don't
if( mMaterial->mCubemapData ) return true;
else return false;
}
bool ProcessedCustomMaterial::setupPass( SceneRenderState *state, const SceneData& sgData, U32 pass )
{
PROFILE_SCOPE( ProcessedCustomMaterial_SetupPass );
// Make sure we have a pass.
if ( pass >= mPasses.size() )
return false;
ShaderRenderPassData* rpd = _getRPD( pass );
U32 currState = _getRenderStateIndex( state, sgData );
GFX->setStateBlock(rpd->mRenderStates[currState]);
// activate shader
if ( rpd->shader )
GFX->setShader( rpd->shader );
else
GFX->disableShaders();
// Set our textures
setTextureStages( state, sgData, pass );
GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
GFX->setShaderConstBuffer(shaderConsts);
// Set our shader constants.
_setTextureTransforms(pass);
_setShaderConstants(state, sgData, pass);
LightManager* lm = state ? LIGHTMGR : NULL;
if (lm)
lm->setLightInfo(this, NULL, sgData, state, pass, shaderConsts);
shaderConsts->setSafe(rpd->shaderHandles.mAccumTimeSC, MATMGR->getTotalTime());
return true;
}
void ProcessedCustomMaterial::setTextureStages( SceneRenderState *state, const SceneData &sgData, U32 pass )
{
LightManager* lm = state ? LIGHTMGR : NULL;
ShaderRenderPassData* rpd = _getRPD(pass);
ShaderConstHandles* handles = _getShaderConstHandles(pass);
GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
const NamedTexTarget *texTarget;
GFXTextureObject *texObject;
for( U32 i=0; i<mMaxTex; i++ )
{
U32 currTexFlag = rpd->mTexType[i];
if ( !lm || !lm->setTextureStage(sgData, currTexFlag, i, shaderConsts, handles ) )
{
GFXShaderConstHandle* handle = handles->mTexHandlesSC[i];
if ( !handle->isValid() )
continue;
S32 samplerRegister = handle->getSamplerRegister();
switch( currTexFlag )
{
case 0:
default:
break;
case Material::Mask:
case Material::Standard:
case Material::Bump:
case Material::Detail:
{
GFX->setTexture( samplerRegister, rpd->mTexSlot[i].texObject );
break;
}
case Material::Lightmap:
{
GFX->setTexture( samplerRegister, sgData.lightmap );
break;
}
case Material::Cube:
{
GFX->setCubeTexture( samplerRegister, rpd->mCubeMap );
break;
}
case Material::SGCube:
{
GFX->setCubeTexture( samplerRegister, sgData.cubemap );
break;
}
case Material::BackBuff:
{
GFX->setTexture( samplerRegister, sgData.backBuffTex );
break;
}
case Material::ReflectBuff:
{
GFX->setTexture( samplerRegister, sgData.reflectTex );
break;
}
case Material::Misc:
{
GFX->setTexture( samplerRegister, sgData.miscTex );
break;
}
case Material::TexTarget:
{
texTarget = rpd->mTexSlot[i].texTarget;
if ( !texTarget )
{
GFX->setTexture( samplerRegister, NULL );
break;
}
texObject = texTarget->getTexture();
// If no texture is available then map the default 2x2
// black texture to it. This at least will ensure that
// we get consistant behavior across GPUs and platforms.
if ( !texObject )
texObject = GFXTexHandle::ZERO;
if ( handles->mRTParamsSC[samplerRegister]->isValid() && texObject )
{
const Point3I &targetSz = texObject->getSize();
const RectI &targetVp = texTarget->getViewport();
Point4F rtParams;
ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
shaderConsts->set(handles->mRTParamsSC[samplerRegister], rtParams);
}
GFX->setTexture( samplerRegister, texObject );
break;
}
}
}
}
}
template <typename T>
void ProcessedCustomMaterial::setMaterialParameter(MaterialParameters* param,
MaterialParameterHandle* handle,
const String& value)
{
T typedValue;
if (PropertyInfo::default_scan(value, typedValue))
{
param->set(handle, typedValue);
} else {
Con::errorf("Error setting %s, parse error: %s", handle->getName().c_str(), value.c_str());
}
}
void ProcessedCustomMaterial::setMatrixParameter(MaterialParameters* param,
MaterialParameterHandle* handle,
const String& value, GFXShaderConstType matrixType)
{
MatrixF result(true);
F32* m = result;
switch (matrixType)
{
case GFXSCT_Float2x2 :
dSscanf(value.c_str(),"%g %g %g %g",
m[result.idx(0,0)], m[result.idx(0,1)],
m[result.idx(1,0)], m[result.idx(1,1)]);
break;
case GFXSCT_Float3x3 :
dSscanf(value.c_str(),"%g %g %g %g %g %g %g %g %g",
m[result.idx(0,0)], m[result.idx(0,1)], m[result.idx(0,2)],
m[result.idx(1,0)], m[result.idx(1,1)], m[result.idx(1,2)],
m[result.idx(2,0)], m[result.idx(2,1)], m[result.idx(2,2)]);
break;
default:
AssertFatal(false, "Invalid type!");
break;
}
}
// BTRTODO: Support arrays!?
MaterialParameters* ProcessedCustomMaterial::allocMaterialParameters()
{
MaterialParameters* ret = Parent::allocMaterialParameters();
// See if any of the dynamic fields match up with shader constants we have.
SimFieldDictionary* fields = mMaterial->getFieldDictionary();
if (!fields || fields->getNumFields() == 0)
return ret;
const Vector<GFXShaderConstDesc>& consts = ret->getShaderConstDesc();
for (U32 i = 0; i < consts.size(); i++)
{
// strip the dollar sign from the front.
String stripped(consts[i].name);
stripped.erase(0, 1);
SimFieldDictionary::Entry* field = fields->findDynamicField(stripped);
if (field)
{
MaterialParameterHandle* handle = getMaterialParameterHandle(consts[i].name);
switch (consts[i].constType)
{
case GFXSCT_Float :
setMaterialParameter<F32>(ret, handle, field->value);
break;
case GFXSCT_Float2:
setMaterialParameter<Point2F>(ret, handle, field->value);
break;
case GFXSCT_Float3:
setMaterialParameter<Point3F>(ret, handle, field->value);
break;
case GFXSCT_Float4:
setMaterialParameter<Point4F>(ret, handle, field->value);
break;
case GFXSCT_Float2x2:
case GFXSCT_Float3x3:
setMatrixParameter(ret, handle, field->value, consts[i].constType);
break;
case GFXSCT_Float4x4:
setMaterialParameter<MatrixF>(ret, handle, field->value);
break;
case GFXSCT_Int:
setMaterialParameter<S32>(ret, handle, field->value);
break;
case GFXSCT_Int2:
setMaterialParameter<Point2I>(ret, handle, field->value);
break;
case GFXSCT_Int3:
setMaterialParameter<Point3I>(ret, handle, field->value);
break;
case GFXSCT_Int4:
setMaterialParameter<Point4I>(ret, handle, field->value);
break;
// Do we want to ignore these?
case GFXSCT_Sampler:
case GFXSCT_SamplerCube:
default:
break;
}
}
}
return ret;
}

View file

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALS_PROCESSEDCUSTOMMATERIAL_H_
#define _MATERIALS_PROCESSEDCUSTOMMATERIAL_H_
#ifndef _MATERIALS_PROCESSEDSHADERMATERIAL_H_
#include "materials/processedShaderMaterial.h"
#endif
#ifndef _CUSTOMMATERIALDEFINITION_H_
#include "materials/customMaterialDefinition.h"
#endif
///
class ProcessedCustomMaterial : public ProcessedShaderMaterial
{
typedef ProcessedShaderMaterial Parent;
public:
ProcessedCustomMaterial(Material &mat);
~ProcessedCustomMaterial();
virtual bool setupPass(SceneRenderState *, const SceneData& sgData, U32 pass);
virtual bool init( const FeatureSet &features, const GFXVertexFormat *vertexFormat, const MatFeaturesDelegate &featuresDelegate );
virtual void setTextureStages(SceneRenderState *, const SceneData &sgData, U32 pass );
virtual MaterialParameters* allocMaterialParameters();
protected:
virtual void _setStageData();
virtual bool _hasCubemap(U32 pass);
void _initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc &result );
virtual void _initPassStateBlocks();
private:
CustomMaterial* mCustomMaterial;
/// The conditioner macros passed to the
/// shader on construction.
Vector<GFXShaderMacro> mConditionerMacros;
/// How many texture slots are we using.
U32 mMaxTex;
template <typename T>
void setMaterialParameter(MaterialParameters* param, MaterialParameterHandle* handle,
const String& value);
void setMatrixParameter(MaterialParameters* param,
MaterialParameterHandle* handle, const String& value, GFXShaderConstType matrixType);
};
#endif // _MATERIALS_PROCESSEDCUSTOMMATERIAL_H_

View file

@ -0,0 +1,378 @@
//-----------------------------------------------------------------------------
// 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/processedFFMaterial.h"
#include "gfx/sim/cubemapData.h"
#include "materials/sceneData.h"
#include "materials/customMaterialDefinition.h"
#include "materials/materialFeatureTypes.h"
#include "gfx/sim/gfxStateBlockData.h"
#include "gfx/gfxDevice.h"
#include "gfx/genericConstBuffer.h"
#include "materials/materialParameters.h"
#include "lighting/lightInfo.h"
#include "scene/sceneRenderState.h"
#include "core/util/safeDelete.h"
#include "math/util/matrixSet.h"
class FFMaterialParameterHandle : public MaterialParameterHandle
{
public:
virtual ~FFMaterialParameterHandle() {}
virtual const String& getName() const { return mName; }
virtual bool isValid() const { return false; }
virtual S32 getSamplerRegister( U32 pass ) const { return -1; }
private:
String mName;
};
ProcessedFFMaterial::ProcessedFFMaterial()
{
VECTOR_SET_ASSOCIATION( mParamDesc );
_construct();
}
ProcessedFFMaterial::ProcessedFFMaterial(Material &mat, const bool isLightingMaterial)
{
VECTOR_SET_ASSOCIATION( mParamDesc );
_construct();
mMaterial = &mat;
mIsLightingMaterial = isLightingMaterial;
}
void ProcessedFFMaterial::_construct()
{
mHasSetStageData = false;
mHasGlow = false;
mIsLightingMaterial = false;
mDefaultHandle = new FFMaterialParameterHandle();
mDefaultParameters = new MaterialParameters();
mCurrentParams = mDefaultParameters;
}
ProcessedFFMaterial::~ProcessedFFMaterial()
{
SAFE_DELETE(mDefaultParameters);
SAFE_DELETE( mDefaultHandle );
}
void ProcessedFFMaterial::_createPasses( U32 stageNum, const FeatureSet &features )
{
FixedFuncFeatureData featData;
_determineFeatures(stageNum, featData, features);
// Just create a simple pass!
_addPass(0, featData);
mFeatures.clear();
if ( featData.features[FixedFuncFeatureData::DiffuseMap] )
mFeatures.addFeature( MFT_DiffuseMap );
if ( featData.features[FixedFuncFeatureData::LightMap] )
mFeatures.addFeature( MFT_LightMap );
if ( featData.features[FixedFuncFeatureData::ToneMap] )
mFeatures.addFeature( MFT_ToneMap );
}
void ProcessedFFMaterial::_determineFeatures( U32 stageNum,
FixedFuncFeatureData& featData,
const FeatureSet &features )
{
if ( mStages[stageNum].getTex( MFT_DiffuseMap ) )
featData.features[FixedFuncFeatureData::DiffuseMap] = true;
if ( features.hasFeature( MFT_LightMap ) )
featData.features[FixedFuncFeatureData::LightMap] = true;
if ( features.hasFeature( MFT_ToneMap ))
featData.features[FixedFuncFeatureData::ToneMap] = true;
}
U32 ProcessedFFMaterial::getNumStages()
{
// Loops through all stages to determine how many stages we actually use
U32 numStages = 0;
U32 i;
for( i=0; i<Material::MAX_STAGES; i++ )
{
// Assume stage is inactive
bool stageActive = false;
// Cubemaps only on first stage
if( i == 0 )
{
// If we have a cubemap the stage is active
if( mMaterial->mCubemapData || mMaterial->mDynamicCubemap )
{
numStages++;
continue;
}
}
// If we have a texture for the a feature the
// stage is active.
if ( mStages[i].hasValidTex() )
stageActive = true;
// If this stage has specular lighting, it's active
if ( mMaterial->mPixelSpecular[i] )
stageActive = true;
// If we have a Material that is vertex lit
// then it may not have a texture
if( mMaterial->mVertLit[i] )
{
stageActive = true;
}
// Increment the number of active stages
numStages += stageActive;
}
return numStages;
}
bool ProcessedFFMaterial::setupPass( SceneRenderState *state, const SceneData &sgData, U32 pass )
{
PROFILE_SCOPE( ProcessedFFMaterial_SetupPass );
// Make sure we have a pass
if(pass >= mPasses.size())
return false;
_setRenderState( state, sgData, pass );
// Bind our textures
setTextureStages( state, sgData, pass );
return true;
}
void ProcessedFFMaterial::setTextureStages(SceneRenderState * state, const SceneData& sgData, U32 pass)
{
// We may need to do some trickery in here for fixed function, this is just copy/paste from MatInstance
#ifdef TORQUE_DEBUG
AssertFatal( pass<mPasses.size(), "Pass out of bounds" );
#endif
RenderPassData *rpd = mPasses[pass];
for( U32 i=0; i<rpd->mNumTex; i++ )
{
U32 currTexFlag = rpd->mTexType[i];
if (!LIGHTMGR || !LIGHTMGR->setTextureStage(sgData, currTexFlag, i, NULL, NULL))
{
switch( currTexFlag )
{
case Material::NoTexture:
if (rpd->mTexSlot[i].texObject)
GFX->setTexture( i, rpd->mTexSlot[i].texObject );
break;
case Material::NormalizeCube:
GFX->setCubeTexture(i, Material::GetNormalizeCube());
break;
case Material::Lightmap:
GFX->setTexture( i, sgData.lightmap );
break;
case Material::Cube:
// TODO: Is this right?
GFX->setTexture( i, rpd->mTexSlot[0].texObject );
break;
case Material::SGCube:
// No cubemap support just yet
//GFX->setCubeTexture( i, sgData.cubemap );
GFX->setTexture( i, rpd->mTexSlot[0].texObject );
break;
case Material::BackBuff:
GFX->setTexture( i, sgData.backBuffTex );
break;
}
}
}
}
MaterialParameters* ProcessedFFMaterial::allocMaterialParameters()
{
return new MaterialParameters();
}
MaterialParameters* ProcessedFFMaterial::getDefaultMaterialParameters()
{
return mDefaultParameters;
}
MaterialParameterHandle* ProcessedFFMaterial::getMaterialParameterHandle(const String& name)
{
return mDefaultHandle;
}
void ProcessedFFMaterial::setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass)
{
GFX->setWorldMatrix(matrixSet.getObjectToWorld());
GFX->setViewMatrix(matrixSet.getWorldToCamera());
GFX->setProjectionMatrix(matrixSet.getCameraToScreen());
}
void ProcessedFFMaterial::setSceneInfo(SceneRenderState * state, const SceneData& sgData, U32 pass)
{
_setPrimaryLightInfo(*sgData.objTrans, sgData.lights[0], pass);
_setSecondaryLightInfo(*sgData.objTrans, sgData.lights[1]);
}
void ProcessedFFMaterial::_setPrimaryLightInfo(const MatrixF &_objTrans, LightInfo* light, U32 pass)
{
// Just in case
GFX->setGlobalAmbientColor(ColorF(0.0f, 0.0f, 0.0f, 1.0f));
if ( light->getType() == LightInfo::Ambient )
{
// Ambient light
GFX->setGlobalAmbientColor( light->getAmbient() );
return;
}
GFX->setLight(0, NULL);
GFX->setLight(1, NULL);
// This is a quick hack that lets us use FF lights
GFXLightMaterial lightMat;
lightMat.ambient = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
lightMat.diffuse = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
lightMat.emissive = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
lightMat.specular = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
lightMat.shininess = 128.0f;
GFX->setLightMaterial(lightMat);
// set object transform
MatrixF objTrans = _objTrans;
objTrans.inverse();
// fill in primary light
//-------------------------
GFXLightInfo xlatedLight;
light->setGFXLight(&xlatedLight);
Point3F lightPos = light->getPosition();
Point3F lightDir = light->getDirection();
objTrans.mulP(lightPos);
objTrans.mulV(lightDir);
xlatedLight.mPos = lightPos;
xlatedLight.mDirection = lightDir;
GFX->setLight(0, &xlatedLight);
}
void ProcessedFFMaterial::_setSecondaryLightInfo(const MatrixF &_objTrans, LightInfo* light)
{
// set object transform
MatrixF objTrans = _objTrans;
objTrans.inverse();
// fill in secondary light
//-------------------------
GFXLightInfo xlatedLight;
light->setGFXLight(&xlatedLight);
Point3F lightPos = light->getPosition();
Point3F lightDir = light->getDirection();
objTrans.mulP(lightPos);
objTrans.mulV(lightDir);
xlatedLight.mPos = lightPos;
xlatedLight.mDirection = lightDir;
GFX->setLight(1, &xlatedLight);
}
bool ProcessedFFMaterial::init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat,
const MatFeaturesDelegate &featuresDelegate )
{
TORQUE_UNUSED( vertexFormat );
TORQUE_UNUSED( featuresDelegate );
_setStageData();
// Just create a simple pass
_createPasses(0, features);
_initRenderPassDataStateBlocks();
mStateHint.init( this );
return true;
}
void ProcessedFFMaterial::_addPass(U32 stageNum, FixedFuncFeatureData& featData)
{
U32 numTex = 0;
// Just creates a simple pass, but it can still glow!
RenderPassData rpd;
// Base texture, texunit 0
if(featData.features[FixedFuncFeatureData::DiffuseMap])
{
rpd.mTexSlot[0].texObject = mStages[stageNum].getTex( MFT_DiffuseMap );
rpd.mTexType[0] = Material::NoTexture;
numTex++;
}
// lightmap, texunit 1
if(featData.features[FixedFuncFeatureData::LightMap])
{
rpd.mTexType[1] = Material::Lightmap;
numTex++;
}
rpd.mNumTex = numTex;
rpd.mStageNum = stageNum;
rpd.mGlow = false;
mPasses.push_back( new RenderPassData(rpd) );
}
void ProcessedFFMaterial::_setPassBlendOp()
{
}
void ProcessedFFMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc &result )
{
Parent::_initPassStateBlock( rpd, result );
if ( mIsLightingMaterial )
{
result.ffLighting = true;
result.blendDefined = true;
result.blendEnable = true;
result.blendSrc = GFXBlendOne;
result.blendSrc = GFXBlendOne;
}
// This is here for generic FF shader fallbacks.
CustomMaterial* custmat = dynamic_cast<CustomMaterial*>(mMaterial);
if (custmat && custmat->getStateBlockData() )
result.addDesc(custmat->getStateBlockData()->getState());
}

View file

@ -0,0 +1,125 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALS_PROCESSEDFFMATERIAL_H_
#define _MATERIALS_PROCESSEDFFMATERIAL_H_
#ifndef _MATERIALS_PROCESSEDMATERIAL_H_
#include "materials/processedMaterial.h"
#endif
class LightInfo;
struct GFXShaderConstDesc;
/// Fixed function rendering. Does not load or use shaders. Does not rely on GFXMaterialFeatureData.
/// Tries very hard to not rely on anything possibly related to shaders.
///
/// @note Does not always succeed.
class ProcessedFFMaterial : public ProcessedMaterial
{
typedef ProcessedMaterial Parent;
public:
ProcessedFFMaterial();
ProcessedFFMaterial(Material &mat, const bool isLightingMaterial = false);
~ProcessedFFMaterial();
/// @name Render state setting
///
/// @{
/// Sets necessary textures and texture ops for rendering
virtual void setTextureStages(SceneRenderState *, const SceneData &sgData, U32 pass );
virtual MaterialParameters* allocMaterialParameters();
virtual MaterialParameterHandle* getMaterialParameterHandle(const String& name);
virtual MaterialParameters* getDefaultMaterialParameters();
virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass);
virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass);
/// @}
virtual bool init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat,
const MatFeaturesDelegate &featuresDelegate );
/// Sets up the given pass
///
/// @returns false if the pass could not be set up
virtual bool setupPass(SceneRenderState *, const SceneData& sgData, U32 pass);
/// Returns the number of stages we're using (not to be confused with the number of passes)
virtual U32 getNumStages();
protected:
MaterialParameterHandle* mDefaultHandle;
MaterialParameters* mDefaultParameters;
struct FixedFuncFeatureData
{
enum
{
DiffuseMap,
LightMap,
ToneMap,
NumFeatures
};
bool features[NumFeatures];
};
bool mIsLightingMaterial;
Vector<GFXShaderConstDesc> mParamDesc;
/// @name Internal functions
///
/// @{
/// Adds a pass for the given stage
virtual void _addPass(U32 stageNum, FixedFuncFeatureData& featData);
/// Chooses a blend op for the pass during pass creation
virtual void _setPassBlendOp();
/// Creates all necessary passes for the given stage
void _createPasses( U32 stageNum, const FeatureSet &features );
/// Determine what features we need
void _determineFeatures( U32 stageNum,
FixedFuncFeatureData &featData,
const FeatureSet &features);
/// Sets light info for the first light
virtual void _setPrimaryLightInfo(const MatrixF &objTrans, LightInfo* light, U32 pass);
/// Sets light info for the second light
virtual void _setSecondaryLightInfo(const MatrixF &objTrans, LightInfo* light);
/// Does the base render state block setting, normally per pass
virtual void _initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc &result );
/// @}
void _construct();
};
#endif

View file

@ -0,0 +1,480 @@
//-----------------------------------------------------------------------------
// 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"
#include "gfx/sim/cubemapData.h"
RenderPassData::RenderPassData()
{
reset();
}
void RenderPassData::reset()
{
for( U32 i = 0; i < Material::MAX_TEX_PER_PASS; ++ i )
destructInPlace( &mTexSlot[ i ] );
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 ),
mMaxStages( 0 ),
mVertexFormat( NULL ),
mUserObject( NULL )
{
VECTOR_SET_ASSOCIATION( mPasses );
}
ProcessedMaterial::~ProcessedMaterial()
{
for_each( mPasses.begin(), mPasses.end(), delete_pointer() );
}
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;
desc.blendDest = GFXBlendZero;
break;
}
case Material::LerpAlpha:
{
desc.blendSrc = GFXBlendSrcAlpha;
desc.blendDest = GFXBlendInvSrcAlpha;
break;
}
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__) );
}
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;
stateTranslucent.samplers[0].textureColorOp = GFXTOPModulate;
stateTranslucent.samplers[0].alphaOp = GFXTOPModulate;
stateTranslucent.samplers[0].alphaArg1 = GFXTATexture;
stateTranslucent.samplers[0].alphaArg2 = GFXTADiffuse;
// 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 );
}
if (mMaterial->isDoubleSided())
{
result.cullDefined = true;
result.cullMode = GFXCullNone;
}
if(mMaterial->mAlphaTest)
{
result.alphaDefined = true;
result.alphaTestEnable = mMaterial->mAlphaTest;
result.alphaTestRef = mMaterial->mAlphaRef;
result.alphaTestFunc = GFXCmpGreaterEqual;
}
result.samplersDefined = true;
NamedTexTarget *texTarget;
U32 maxAnisotropy = 1;
if ( mMaterial->mUseAnisotropic[ rpd->mStageNum ] )
maxAnisotropy = MATMGR->getDefaultAnisotropy();
for( U32 i=0; i < rpd->mNumTex; i++ )
{
U32 currTexFlag = rpd->mTexType[i];
switch( currTexFlag )
{
default:
{
result.samplers[i].textureColorOp = GFXTOPModulate;
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;
break;
}
case Material::TexTarget:
{
texTarget = mPasses[0]->mTexSlot[i].texTarget;
if ( texTarget )
texTarget->setupSamplerState( &result.samplers[i] );
break;
}
}
}
// The prepass will take care of writing to the
// zbuffer, so we don't have to by default.
// The prepass can't write to the backbuffer's zbuffer in OpenGL.
if ( MATMGR->getPrePassEnabled() &&
!GFX->getAdapterType() == OpenGL &&
!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;
if ( sgData.binType != SceneData::PrePassBin &&
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
if ( mHasSetStageData )
return;
mHasSetStageData = true;
U32 i;
// Load up all the textures for every possible stage
for( i=0; i<Material::MAX_STAGES; i++ )
{
// DiffuseMap
if( mMaterial->mDiffuseMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_DiffuseMap, _createTexture( mMaterial->mDiffuseMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if (!mStages[i].getTex( MFT_DiffuseMap ))
{
mMaterial->logError("Failed to load diffuse map %s for stage %i", _getTexturePath(mMaterial->mDiffuseMapFilename[i]).c_str(), i);
// 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( "core/art/missingTexture", &GFXDefaultStaticDiffuseProfile ) );
}
}
// OverlayMap
if( mMaterial->mOverlayMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_OverlayMap, _createTexture( mMaterial->mOverlayMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_OverlayMap ))
mMaterial->logError("Failed to load overlay map %s for stage %i", _getTexturePath(mMaterial->mOverlayMapFilename[i]).c_str(), i);
}
// LightMap
if( mMaterial->mLightMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_LightMap, _createTexture( mMaterial->mLightMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_LightMap ))
mMaterial->logError("Failed to load light map %s for stage %i", _getTexturePath(mMaterial->mLightMapFilename[i]).c_str(), i);
}
// ToneMap
if( mMaterial->mToneMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_ToneMap, _createTexture( mMaterial->mToneMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_ToneMap ))
mMaterial->logError("Failed to load tone map %s for stage %i", _getTexturePath(mMaterial->mToneMapFilename[i]).c_str(), i);
}
// DetailMap
if( mMaterial->mDetailMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_DetailMap, _createTexture( mMaterial->mDetailMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_DetailMap ))
mMaterial->logError("Failed to load detail map %s for stage %i", _getTexturePath(mMaterial->mDetailMapFilename[i]).c_str(), i);
}
// NormalMap
if( mMaterial->mNormalMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_NormalMap, _createTexture( mMaterial->mNormalMapFilename[i], &GFXDefaultStaticNormalMapProfile ) );
if(!mStages[i].getTex( MFT_NormalMap ))
mMaterial->logError("Failed to load normal map %s for stage %i", _getTexturePath(mMaterial->mNormalMapFilename[i]).c_str(), i);
}
// Detail Normal Map
if( mMaterial->mDetailNormalMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_DetailNormalMap, _createTexture( mMaterial->mDetailNormalMapFilename[i], &GFXDefaultStaticNormalMapProfile ) );
if(!mStages[i].getTex( MFT_DetailNormalMap ))
mMaterial->logError("Failed to load normal map %s for stage %i", _getTexturePath(mMaterial->mDetailNormalMapFilename[i]).c_str(), i);
}
// SpecularMap
if( mMaterial->mSpecularMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_SpecularMap, _createTexture( mMaterial->mSpecularMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_SpecularMap ))
mMaterial->logError("Failed to load specular map %s for stage %i", _getTexturePath(mMaterial->mSpecularMapFilename[i]).c_str(), i);
}
// EnironmentMap
if( mMaterial->mEnvMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_EnvMap, _createTexture( mMaterial->mEnvMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_EnvMap ))
mMaterial->logError("Failed to load environment map %s for stage %i", _getTexturePath(mMaterial->mEnvMapFilename[i]).c_str(), i);
}
}
mMaterial->mCubemapData = dynamic_cast<CubemapData*>(Sim::findObject( mMaterial->mCubemapName ));
if( !mMaterial->mCubemapData )
mMaterial->mCubemapData = NULL;
// If we have a cubemap put it on stage 0 (cubemaps only supported on stage 0)
if( mMaterial->mCubemapData )
{
mMaterial->mCubemapData->createMap();
mStages[0].setCubemap( mMaterial->mCubemapData->mCubemap );
if ( !mStages[0].getCubemap() )
mMaterial->logError("Failed to load cubemap");
}
}

View file

@ -0,0 +1,306 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALS_PROCESSEDMATERIAL_H_
#define _MATERIALS_PROCESSEDMATERIAL_H_
#ifndef _MATERIALDEFINITION_H_
#include "materials/materialDefinition.h"
#endif
#ifndef _MATERIALFEATUREDATA_H_
#include "materials/materialFeatureData.h"
#endif
#ifndef _GFXSTATEBLOCK_H_
#include "gfx/gfxStateBlock.h"
#endif
#ifndef _MATTEXTURETARGET_H_
#include "materials/matTextureTarget.h"
#endif
#ifndef _MATSTATEHINT_H_
#include "materials/matStateHint.h"
#endif
class ShaderFeature;
class MaterialParameters;
class MaterialParameterHandle;
class SceneRenderState;
class GFXVertexBufferHandleBase;
class GFXPrimitiveBufferHandle;
class MatrixSet;
/// This contains the common data needed to render a pass.
struct RenderPassData
{
public:
struct TexSlotT
{
/// This is the default type of texture which
/// is valid with most texture types.
/// @see mTexType
GFXTexHandle texObject;
/// Only valid when the texture type is set
/// to Material::TexTarget.
/// @see mTexType
NamedTexTargetRef texTarget;
} mTexSlot[Material::MAX_TEX_PER_PASS];
U32 mTexType[Material::MAX_TEX_PER_PASS];
/// The cubemap to use when the texture type is
/// set to Material::Cube.
/// @see mTexType
GFXCubemap *mCubeMap;
U32 mNumTex;
U32 mNumTexReg;
MaterialFeatureData mFeatureData;
bool mGlow;
Material::BlendOp mBlendOp;
U32 mStageNum;
/// State permutations, used to index into
/// the render states array.
/// @see mRenderStates
enum
{
STATE_REFLECT = 1,
STATE_TRANSLUCENT = 2,
STATE_GLOW = 4,
STATE_WIREFRAME = 8,
STATE_MAX = 16
};
///
GFXStateBlockRef mRenderStates[STATE_MAX];
RenderPassData();
virtual ~RenderPassData() { reset(); }
virtual void reset();
/// Creates and returns a unique description string.
virtual String describeSelf() const;
};
/// This is an abstract base class which provides the external
/// interface all subclasses must implement. This interface
/// primarily consists of setting state. Pass creation
/// is implementation specific, and internal, thus it is
/// not in this base class.
class ProcessedMaterial
{
public:
ProcessedMaterial();
virtual ~ProcessedMaterial();
/// @name State setting functions
///
/// @{
///
virtual void addStateBlockDesc(const GFXStateBlockDesc& sb);
///
virtual void updateStateBlocks() { _initRenderPassDataStateBlocks(); }
/// Set the user defined shader macros.
virtual void setShaderMacros( const Vector<GFXShaderMacro> &macros ) { mUserMacros = macros; }
/// Sets the textures needed for rendering the current pass
virtual void setTextureStages(SceneRenderState *, const SceneData &sgData, U32 pass ) = 0;
/// Sets the transformation matrix, i.e. Model * View * Projection
virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass) = 0;
/// Sets the scene info like lights for the given pass.
virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass) = 0;
/// Sets the given vertex and primitive buffers so we can render geometry
virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer);
/// @see BaseMatInstance::setUserObject
virtual void setUserObject( SimObject *userObject ) { mUserObject = userObject; }
///
virtual bool stepInstance();
/// @}
/// Initializes us (eg. loads textures, creates passes, generates shaders)
virtual bool init( const FeatureSet& features,
const GFXVertexFormat *vertexFormat,
const MatFeaturesDelegate &featuresDelegate ) = 0;
/// Returns the state hint which can be used for
/// sorting and fast comparisions of the equality
/// of a material instance.
virtual const MatStateHint& getStateHint() const { return mStateHint; }
/// Sets up the given pass. Returns true if the pass was set up, false if there was an error or if
/// the specified pass is out of bounds.
virtual bool setupPass(SceneRenderState *, const SceneData& sgData, U32 pass) = 0;
// Material parameter methods
virtual MaterialParameters* allocMaterialParameters() = 0;
virtual MaterialParameters* getDefaultMaterialParameters() = 0;
virtual void setMaterialParameters(MaterialParameters* param, S32 pass) { mCurrentParams = param; };
virtual MaterialParameters* getMaterialParameters() { return mCurrentParams; }
virtual MaterialParameterHandle* getMaterialParameterHandle(const String& name) = 0;
/// Returns the pass data for the given pass.
RenderPassData* getPass(U32 pass)
{
if(pass >= mPasses.size())
return NULL;
return mPasses[pass];
}
/// Returns the pass data for the given pass.
const RenderPassData* getPass( U32 pass ) const { return mPasses[pass]; }
/// Returns the number of stages we're rendering (not to be confused with the number of passes).
virtual U32 getNumStages() = 0;
/// Returns the number of passes we are rendering (not to be confused with the number of stages).
U32 getNumPasses() const { return mPasses.size(); }
/// Returns true if any pass glows
bool hasGlow() const { return mHasGlow; }
/// Gets the stage number for a pass
U32 getStageFromPass(U32 pass) const
{
if(pass >= mPasses.size())
return 0;
return mPasses[pass]->mStageNum;
}
/// Returns the active features in use by this material.
/// @see BaseMatInstance::getFeatures
const FeatureSet& getFeatures() const { return mFeatures; }
/// Dump shader info, or FF texture info?
virtual void dumpMaterialInfo() { }
/// Returns the source material.
Material* getMaterial() const { return mMaterial; }
/// Returns the texture used by a stage
GFXTexHandle getStageTexture(U32 stage, const FeatureType &type)
{
return (stage < Material::MAX_STAGES) ? mStages[stage].getTex(type) : NULL;
}
protected:
/// Our passes.
Vector<RenderPassData*> mPasses;
/// The active features in use by this material.
FeatureSet mFeatures;
/// The material which we are processing.
Material* mMaterial;
MaterialParameters* mCurrentParams;
/// Material::StageData is used here because the shader
/// generator throws a fit if it's passed anything else.
Material::StageData mStages[Material::MAX_STAGES];
/// If we've already loaded the stage data
bool mHasSetStageData;
/// If we glow
bool mHasGlow;
/// Number of stages (not to be confused with number of passes)
U32 mMaxStages;
/// The vertex format on which this material will render.
const GFXVertexFormat *mVertexFormat;
/// Set by addStateBlockDesc, should be considered
/// when initPassStateBlock is called.
GFXStateBlockDesc mUserDefined;
/// The user defined macros to pass to the
/// shader initialization.
Vector<GFXShaderMacro> mUserMacros;
/// The user defined object to pass to ShaderFeature::createConstHandles.
SimObject *mUserObject;
/// The state hint used for material sorting
/// and quick equality comparision.
MatStateHint mStateHint;
/// Loads all the textures for all of the stages in the Material
virtual void _setStageData();
/// Sets the blend state for rendering
void _setBlendState(Material::BlendOp blendOp, GFXStateBlockDesc& desc );
/// Returns the path the material will attempt to load for a given texture filename.
String _getTexturePath(const String& filename);
/// Loads the texture located at _getTexturePath(filename) and gives it the specified profile
GFXTexHandle _createTexture( const char *filename, GFXTextureProfile *profile );
/// @name State blocks
///
/// @{
/// Creates the default state block templates, used by initStateBlocks.
virtual void _initStateBlockTemplates(GFXStateBlockDesc& stateTranslucent, GFXStateBlockDesc& stateGlow, GFXStateBlockDesc& stateReflect);
/// Does the base render state block setting, normally per pass.
virtual void _initPassStateBlock( RenderPassData *rpd, GFXStateBlockDesc& result);
/// Creates the default state blocks for a list of render states.
virtual void _initRenderStateStateBlocks( RenderPassData *rpd );
/// Creates the default state blocks for each RenderPassData item.
virtual void _initRenderPassDataStateBlocks();
/// This returns the index into the renderState array based on the sgData passed in.
virtual U32 _getRenderStateIndex( const SceneRenderState *state,
const SceneData &sgData );
/// Activates the correct mPasses[currPass].renderState based on scene graph info
virtual void _setRenderState( const SceneRenderState *state,
const SceneData &sgData,
U32 pass );
/// @
};
#endif // _MATERIALS_PROCESSEDMATERIAL_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,262 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _MATERIALS_PROCESSEDSHADERMATERIAL_H_
#define _MATERIALS_PROCESSEDSHADERMATERIAL_H_
#ifndef _MATERIALS_PROCESSEDMATERIAL_H_
#include "processedMaterial.h"
#endif
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
class GenericConstBufferLayout;
class ShaderData;
class LightInfo;
class ShaderMaterialParameterHandle;
class ShaderFeatureConstHandles;
class CustomMaterial;
class ShaderConstHandles
{
public:
GFXShaderConstHandle* mDiffuseColorSC;
GFXShaderConstHandle* mToneMapTexSC;
GFXShaderConstHandle* mTexMatSC;
GFXShaderConstHandle* mSpecularColorSC;
GFXShaderConstHandle* mSpecularPowerSC;
GFXShaderConstHandle* mParallaxInfoSC;
GFXShaderConstHandle* mFogDataSC;
GFXShaderConstHandle* mFogColorSC;
GFXShaderConstHandle* mDetailScaleSC;
GFXShaderConstHandle* mVisiblitySC;
GFXShaderConstHandle* mColorMultiplySC;
GFXShaderConstHandle* mAlphaTestValueSC;
GFXShaderConstHandle* mModelViewProjSC;
GFXShaderConstHandle* mWorldViewOnlySC;
GFXShaderConstHandle* mWorldToCameraSC;
GFXShaderConstHandle* mWorldToObjSC;
GFXShaderConstHandle* mViewToObjSC;
GFXShaderConstHandle* mCubeTransSC;
GFXShaderConstHandle* mObjTransSC;
GFXShaderConstHandle* mCubeEyePosSC;
GFXShaderConstHandle* mEyePosSC;
GFXShaderConstHandle* mEyePosWorldSC;
GFXShaderConstHandle* m_vEyeSC;
GFXShaderConstHandle* mEyeMatSC;
GFXShaderConstHandle* mOneOverFarplane;
GFXShaderConstHandle* mAccumTimeSC;
GFXShaderConstHandle* mMinnaertConstantSC;
GFXShaderConstHandle* mSubSurfaceParamsSC;
GFXShaderConstHandle* mDiffuseAtlasParamsSC;
GFXShaderConstHandle* mBumpAtlasParamsSC;
GFXShaderConstHandle* mDiffuseAtlasTileSC;
GFXShaderConstHandle* mBumpAtlasTileSC;
GFXShaderConstHandle *mRTSizeSC;
GFXShaderConstHandle *mOneOverRTSizeSC;
GFXShaderConstHandle* mDetailBumpStrength;
GFXShaderConstHandle* mViewProjSC;
GFXShaderConstHandle *mImposterUVs;
GFXShaderConstHandle *mImposterLimits;
GFXShaderConstHandle* mTexHandlesSC[Material::MAX_TEX_PER_PASS];
GFXShaderConstHandle* mRTParamsSC[TEXTURE_STAGE_COUNT];
void init( GFXShader* shader, CustomMaterial* mat = NULL );
};
class ShaderRenderPassData : public RenderPassData
{
typedef RenderPassData Parent;
public:
virtual ~ShaderRenderPassData() { reset(); }
GFXShaderRef shader;
ShaderConstHandles shaderHandles;
Vector<ShaderFeatureConstHandles*> featureShaderHandles;
virtual void reset();
virtual String describeSelf() const;
};
class ProcessedShaderMaterial : public ProcessedMaterial
{
typedef ProcessedMaterial Parent;
public:
ProcessedShaderMaterial();
ProcessedShaderMaterial(Material &mat);
~ProcessedShaderMaterial();
// ProcessedMaterial
virtual bool init( const FeatureSet &features,
const GFXVertexFormat *vertexFormat,
const MatFeaturesDelegate &featuresDelegate );
virtual bool setupPass(SceneRenderState *, const SceneData& sgData, U32 pass);
virtual void setTextureStages(SceneRenderState *, const SceneData &sgData, U32 pass );
virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass);
virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass);
virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer);
virtual bool stepInstance();
virtual void dumpMaterialInfo();
virtual MaterialParameters* allocMaterialParameters();
virtual MaterialParameters* getDefaultMaterialParameters() { return mDefaultParameters; }
virtual MaterialParameterHandle* getMaterialParameterHandle(const String& name);
virtual U32 getNumStages();
protected:
Vector<GFXShaderConstDesc> mShaderConstDesc;
MaterialParameters* mDefaultParameters;
Vector<ShaderMaterialParameterHandle*> mParameterHandles;
/// Hold the instancing state data for the material.
class InstancingState
{
const static U32 COUNT = 200;
public:
InstancingState()
: mInstFormat( NULL ),
mBuffer( NULL ),
mCount( -1 )
{
}
~InstancingState()
{
delete [] mBuffer;
}
void setFormat( const GFXVertexFormat *instFormat, const GFXVertexFormat *vertexFormat )
{
mInstFormat = instFormat;
mDeclFormat.copy( *vertexFormat );
mDeclFormat.append( *mInstFormat, 1 );
mDeclFormat.getDecl();
delete [] mBuffer;
mBuffer = new U8[ mInstFormat->getSizeInBytes() * COUNT ];
mCount = -1;
}
bool step( U8 **outPtr )
{
// Are we starting a new draw call?
if ( mCount < 0 )
{
*outPtr = mBuffer;
mCount = 0;
}
else
{
// Increment to the next instance.
*outPtr += mInstFormat->getSizeInBytes();
mCount++;
}
return mCount < COUNT;
}
void resetStep() { mCount = -1; }
U8* getBuffer() const { return mBuffer; }
S32 getCount() const { return mCount; }
const GFXVertexFormat* getFormat() const { return mInstFormat; }
const GFXVertexFormat* getDeclFormat() const { return &mDeclFormat; }
protected:
GFXVertexFormat mDeclFormat;
const GFXVertexFormat *mInstFormat;
U8 *mBuffer;
S32 mCount;
};
/// The instancing state if this material
/// supports instancing.
InstancingState *mInstancingState;
/// @name Internal functions
///
/// @{
/// Adds a pass for the given stage.
virtual bool _addPass( ShaderRenderPassData &rpd,
U32 &texIndex,
MaterialFeatureData &fd,
U32 stageNum,
const FeatureSet &features);
/// Chooses a blend op for the given pass
virtual void _setPassBlendOp( ShaderFeature *sf,
ShaderRenderPassData &passData,
U32 &texIndex,
MaterialFeatureData &stageFeatures,
U32 stageNum,
const FeatureSet &features);
/// Creates passes for the given stage
virtual bool _createPasses( MaterialFeatureData &fd, U32 stageNum, const FeatureSet &features );
/// Fills in the MaterialFeatureData for the given stage
virtual void _determineFeatures( U32 stageNum,
MaterialFeatureData &fd,
const FeatureSet &features );
/// Do we have a cubemap on pass?
virtual bool _hasCubemap(U32 pass);
/// Used by setTextureTransforms
F32 _getWaveOffset( U32 stage );
/// Sets texture transformation matrices for texture animations such as scale and wave
virtual void _setTextureTransforms(const U32 pass);
/// Sets all of the necessary shader constants for the given pass
virtual void _setShaderConstants(SceneRenderState *, const SceneData &sgData, U32 pass);
/// @}
void _setPrimaryLightConst(const LightInfo* light, const MatrixF& objTrans, const U32 stageNum);
/// This is here to deal with the differences between ProcessedCustomMaterials and ProcessedShaderMaterials.
virtual GFXShaderConstBuffer* _getShaderConstBuffer(const U32 pass);
virtual ShaderConstHandles* _getShaderConstHandles(const U32 pass);
///
virtual void _initMaterialParameters();
ShaderRenderPassData* _getRPD(const U32 pass) { return static_cast<ShaderRenderPassData*>(mPasses[pass]); }
};
#endif // _MATERIALS_PROCESSEDSHADERMATERIAL_H_

View file

@ -0,0 +1,128 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _SCENEDATA_H_
#define _SCENEDATA_H_
#ifndef _SCENERENDERSTATE_H_
#include "scene/sceneRenderState.h"
#endif
#ifndef _LIGHTMANAGER_H_
#include "lighting/lightManager.h"
#endif
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
class GFXTexHandle;
class GFXCubemap;
struct SceneData
{
/// The special bin types.
enum BinType
{
/// A normal render bin that isn't one of
/// the special bins we care about.
RegularBin = 0,
/// The glow render bin.
/// @see RenderGlowMgr
GlowBin,
/// The prepass render bin.
/// @RenderPrePassMgr
PrePassBin,
};
/// This defines when we're rendering a special bin
/// type that the material or lighting system needs
/// to know about.
BinType binType;
// textures
GFXTextureObject *lightmap;
GFXTextureObject *backBuffTex;
GFXTextureObject *reflectTex;
GFXTextureObject *miscTex;
/// The current lights to use in rendering
/// in order of the light importance.
LightInfo* lights[8];
///
ColorF ambientLightColor;
// fog
F32 fogDensity;
F32 fogDensityOffset;
F32 fogHeightFalloff;
ColorF fogColor;
// misc
const MatrixF *objTrans;
GFXCubemap *cubemap;
F32 visibility;
/// Enables wireframe rendering for the object.
bool wireframe;
/// A generic hint value passed from the game
/// code down to the material for use by shader
/// features.
void *materialHint;
/// Constructor.
SceneData()
{
dMemset( this, 0, sizeof( SceneData ) );
objTrans = &MatrixF::Identity;
visibility = 1.0f;
}
/// Initializes the data with the scene state setting
/// common scene wide parameters.
inline void init( const SceneRenderState *state, BinType type = RegularBin )
{
dMemset( this, 0, sizeof( SceneData ) );
setFogParams( state->getSceneManager()->getFogData() );
wireframe = GFXDevice::getWireframe();
binType = type;
objTrans = &MatrixF::Identity;
visibility = 1.0f;
ambientLightColor = state->getAmbientLightColor();
}
inline void setFogParams( const FogData &data )
{
fogDensity = data.density;
fogDensityOffset = data.densityOffset;
if ( !mIsZero( data.atmosphereHeight ) )
fogHeightFalloff = 1.0f / data.atmosphereHeight;
else
fogHeightFalloff = 0.0f;
fogColor = data.color;
}
};
#endif // _SCENEDATA_H_

View file

@ -0,0 +1,282 @@
//-----------------------------------------------------------------------------
// 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/shaderData.h"
#include "console/consoleTypes.h"
#include "gfx/gfxDevice.h"
#include "core/strings/stringUnit.h"
#include "lighting/lightManager.h"
#include "console/engineAPI.h"
using namespace Torque;
Vector<ShaderData*> ShaderData::smAllShaderData;
IMPLEMENT_CONOBJECT( ShaderData );
ConsoleDocClass( ShaderData,
"@brief Special type of data block that stores information about a handwritten shader.\n\n"
"To use hand written shaders, a ShaderData datablock must be used. This datablock "
"refers only to the vertex and pixel shader filenames and a hardware target level. "
"Shaders are API specific, so DirectX and OpenGL shaders must be explicitly identified.\n\n "
"@tsexample\n"
"// Used for the procedural clould system\n"
"singleton ShaderData( CloudLayerShader )\n"
"{\n"
" DXVertexShaderFile = \"shaders/common/cloudLayerV.hlsl\";\n"
" DXPixelShaderFile = \"shaders/common/cloudLayerP.hlsl\";\n"
" OGLVertexShaderFile = \"shaders/common/gl/cloudLayerV.glsl\";\n"
" OGLPixelShaderFile = \"shaders/common/gl/cloudLayerP.glsl\";\n"
" pixVersion = 2.0;\n"
"};\n"
"@endtsexample\n\n"
"@ingroup Shaders\n");
ShaderData::ShaderData()
{
VECTOR_SET_ASSOCIATION( mShaderMacros );
mUseDevicePixVersion = false;
mPixVersion = 1.0;
}
void ShaderData::initPersistFields()
{
addField("DXVertexShaderFile", TypeStringFilename, Offset(mDXVertexShaderName, ShaderData),
"@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n"
"It must contain only one program and no pixel shader, just the vertex shader."
"It can be either an HLSL or assembly level shader. HLSL's must have a "
"filename extension of .hlsl, otherwise its assumed to be an assembly file.");
addField("DXPixelShaderFile", TypeStringFilename, Offset(mDXPixelShaderName, ShaderData),
"@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n"
"It must contain only one program and no vertex shader, just the pixel "
"shader. It can be either an HLSL or assembly level shader. HLSL's "
"must have a filename extension of .hlsl, otherwise its assumed to be an assembly file.");
addField("OGLVertexShaderFile", TypeStringFilename, Offset(mOGLVertexShaderName, ShaderData),
"@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n"
"It must contain only one program and no pixel shader, just the vertex shader.");
addField("OGLPixelShaderFile", TypeStringFilename, Offset(mOGLPixelShaderName, ShaderData),
"@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n"
"It must contain only one program and no vertex shader, just the pixel "
"shader.");
addField("useDevicePixVersion", TypeBool, Offset(mUseDevicePixVersion, ShaderData),
"@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n"
"Otherwise, the script-defined pixel shader version will be used.\n\n");
addField("pixVersion", TypeF32, Offset(mPixVersion, ShaderData),
"@brief Indicates target level the shader should be compiled.\n\n"
"Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. "
"The shader will not run properly if the hardware does not support the "
"level of shader compiled.");
addField("defines", TypeRealString, Offset(mDefines, ShaderData),
"@brief String of case-sensitive defines passed to the shader compiler.\n\n"
"The string should be delimited by a semicolon, tab, or newline character."
"@tsexample\n"
"singleton ShaderData( FlashShader )\n"
"{\n"
"DXVertexShaderFile = \"shaders/common/postFx/flashV.hlsl\";\n"
"DXPixelShaderFile = \"shaders/common/postFx/flashP.hlsl\";\n\n"
" //Define setting the color of WHITE_COLOR.\n"
"defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n"
"pixVersion = 2.0\n"
"}\n"
"@endtsexample\n\n"
);
Parent::initPersistFields();
// Make sure we get activation signals.
LightManager::smActivateSignal.notify( &ShaderData::_onLMActivate );
}
bool ShaderData::onAdd()
{
if( !Parent::onAdd() )
return false;
mShaderMacros.clear();
// Keep track of it.
smAllShaderData.push_back( this );
// NOTE: We initialize the shader on request.
return true;
}
void ShaderData::onRemove()
{
// Remove it from the all shaders list.
smAllShaderData.remove( this );
Parent::onRemove();
}
const Vector<GFXShaderMacro>& ShaderData::_getMacros()
{
// If they have already been processed then
// return the cached result.
if ( mShaderMacros.size() != 0 || mDefines.isEmpty() )
return mShaderMacros;
mShaderMacros.clear();
GFXShaderMacro macro;
const U32 defineCount = StringUnit::getUnitCount( mDefines, ";\n\t" );
for ( U32 i=0; i < defineCount; i++ )
{
String define = StringUnit::getUnit( mDefines, i, ";\n\t" );
macro.name = StringUnit::getUnit( define, 0, "=" );
macro.value = StringUnit::getUnit( define, 1, "=" );
mShaderMacros.push_back( macro );
}
return mShaderMacros;
}
GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> &macros )
{
PROFILE_SCOPE( ShaderData_GetShader );
// Combine the dynamic macros with our script defined macros.
Vector<GFXShaderMacro> finalMacros;
finalMacros.merge( _getMacros() );
finalMacros.merge( macros );
// Convert the final macro list to a string.
String cacheKey;
GFXShaderMacro::stringize( macros, &cacheKey );
// Lookup the shader for this instance.
ShaderCache::Iterator iter = mShaders.find( cacheKey );
if ( iter != mShaders.end() )
return iter->value;
// Create the shader instance... if it fails then
// bail out and return nothing to the caller.
GFXShader *shader = _createShader( finalMacros );
if ( !shader )
return NULL;
// Store the shader in the cache and return it.
mShaders.insertUnique( cacheKey, shader );
return shader;
}
GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> &macros )
{
F32 pixver = mPixVersion;
if ( mUseDevicePixVersion )
pixver = getMax( pixver, GFX->getPixelShaderVersion() );
// Enable shader error logging.
GFXShader::setLogging( true, true );
GFXShader *shader = GFX->createShader();
bool success = false;
// Initialize the right shader type.
switch( GFX->getAdapterType() )
{
case Direct3D9_360:
case Direct3D9:
{
success = shader->init( mDXVertexShaderName,
mDXPixelShaderName,
pixver,
macros );
break;
}
case OpenGL:
{
success = shader->init( mOGLVertexShaderName,
mOGLPixelShaderName,
pixver,
macros );
break;
}
default:
// Other device types are assumed to not support shaders.
success = false;
break;
}
// If we failed to load the shader then
// cleanup and return NULL.
if ( !success )
SAFE_DELETE( shader );
return shader;
}
void ShaderData::reloadShaders()
{
ShaderCache::Iterator iter = mShaders.begin();
for ( ; iter != mShaders.end(); iter++ )
iter->value->reload();
}
void ShaderData::reloadAllShaders()
{
Vector<ShaderData*>::iterator iter = smAllShaderData.begin();
for ( ; iter != smAllShaderData.end(); iter++ )
(*iter)->reloadShaders();
}
void ShaderData::_onLMActivate( const char *lm, bool activate )
{
// Only on activations do we do anything.
if ( !activate )
return;
// Since the light manager usually swaps shadergen features
// and changes system wide shader defines we need to completely
// flush and rebuild all shaders.
reloadAllShaders();
}
DefineEngineMethod( ShaderData, reload, void, (),,
"@brief Rebuilds all the vertex and pixel shader instances created from this ShaderData.\n\n"
"@tsexample\n"
"// Rebuild the shader instances from ShaderData CloudLayerShader\n"
"CloudLayerShader.reload();\n"
"@endtsexample\n\n")
{
object->reloadShaders();
}

View file

@ -0,0 +1,122 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _SHADERTDATA_H_
#define _SHADERTDATA_H_
#ifndef _SIMOBJECT_H_
#include "console/simObject.h"
#endif
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
class GFXShader;
class ShaderData;
struct GFXShaderMacro;
///
class ShaderData : public SimObject
{
typedef SimObject Parent;
protected:
///
static Vector<ShaderData*> smAllShaderData;
typedef HashTable<String,GFXShaderRef> ShaderCache;
ShaderCache mShaders;
bool mUseDevicePixVersion;
F32 mPixVersion;
FileName mDXVertexShaderName;
FileName mDXPixelShaderName;
FileName mOGLVertexShaderName;
FileName mOGLPixelShaderName;
/// A semicolon, tab, or newline delimited string of case
/// sensitive defines that are passed to the shader compiler.
///
/// For example:
///
/// SAMPLE_TAPS=10;USE_TEXKILL;USE_TORQUE_FOG=1
///
String mDefines;
/// The shader macros built from mDefines.
/// @see _getMacros()
Vector<GFXShaderMacro> mShaderMacros;
/// Returns the shader macros taking care to rebuild
/// them if the content has changed.
const Vector<GFXShaderMacro>& _getMacros();
/// Helper for converting an array of macros
/// into a formatted string.
void _stringizeMacros( const Vector<GFXShaderMacro> &macros,
String *outString );
/// Creates a new shader returning NULL on error.
GFXShader* _createShader( const Vector<GFXShaderMacro> &macros );
/// @see LightManager::smActivateSignal
static void _onLMActivate( const char *lm, bool activate );
public:
ShaderData();
/// Returns an initialized shader instance or NULL
/// if the shader failed to be created.
GFXShader* getShader( const Vector<GFXShaderMacro> &macros = Vector<GFXShaderMacro>() );
/// Forces a reinitialization of all the instanced shaders.
void reloadShaders();
/// Forces a reinitialization of the instanced shaders for
/// all loaded ShaderData objects in the system.
static void reloadAllShaders();
/// Returns the required pixel shader version for this shader.
F32 getPixVersion() const { return mPixVersion; }
// SimObject
virtual bool onAdd();
virtual void onRemove();
// ConsoleObject
static void initPersistFields();
DECLARE_CONOBJECT(ShaderData);
};
#endif // _SHADERTDATA_H_

View file

@ -0,0 +1,229 @@
//-----------------------------------------------------------------------------
// 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/shaderMaterialParameters.h"
#include "console/console.h"
//
// ShaderMaterialParameters
//
ShaderMaterialParameterHandle::ShaderMaterialParameterHandle(const String& name)
{
VECTOR_SET_ASSOCIATION( mHandles );
mName = name;
}
ShaderMaterialParameterHandle::ShaderMaterialParameterHandle(const String& name, Vector<GFXShader*>& shaders)
{
VECTOR_SET_ASSOCIATION( mHandles );
mName = name;
mHandles.setSize(shaders.size());
for (U32 i = 0; i < shaders.size(); i++)
mHandles[i] = shaders[i]->getShaderConstHandle(name);
}
ShaderMaterialParameterHandle::~ShaderMaterialParameterHandle()
{
}
S32 ShaderMaterialParameterHandle::getSamplerRegister( U32 pass ) const
{
AssertFatal( mHandles.size() > pass, "ShaderMaterialParameterHandle::getSamplerRegister - out of bounds" );
return mHandles[pass]->getSamplerRegister();
}
//
// ShaderMaterialParameters
//
ShaderMaterialParameters::ShaderMaterialParameters()
: MaterialParameters()
{
VECTOR_SET_ASSOCIATION( mBuffers );
}
ShaderMaterialParameters::~ShaderMaterialParameters()
{
releaseBuffers();
}
void ShaderMaterialParameters::setBuffers(Vector<GFXShaderConstDesc>& constDesc, Vector<GFXShaderConstBufferRef>& buffers)
{
mShaderConstDesc = constDesc;
mBuffers = buffers;
}
void ShaderMaterialParameters::releaseBuffers()
{
for (U32 i = 0; i < mBuffers.size(); i++)
{
mBuffers[i] = NULL;
}
mBuffers.setSize(0);
}
U32 ShaderMaterialParameters::getAlignmentValue(const GFXShaderConstType constType)
{
if (mBuffers.size() > 0)
return mBuffers[0]->getShader()->getAlignmentValue(constType);
else
return 0;
}
#define SHADERMATPARAM_SET(handle, f) \
AssertFatal(handle, "Handle is NULL!" ); \
AssertFatal(handle->isValid(), "Handle is not valid!" ); \
AssertFatal(dynamic_cast<ShaderMaterialParameterHandle*>(handle), "Invalid handle type!"); \
ShaderMaterialParameterHandle* h = static_cast<ShaderMaterialParameterHandle*>(handle); \
AssertFatal(h->mHandles.size() == mBuffers.size(), "Handle length differs from buffer length!"); \
for (U32 i = 0; i < h->mHandles.size(); i++) \
{ \
GFXShaderConstHandle* shaderHandle = h->mHandles[i]; \
if (shaderHandle->isValid()) \
mBuffers[i]->set(shaderHandle, f); \
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const F32 f)
{
SHADERMATPARAM_SET(handle, f);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const Point2F& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const Point3F& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const Point4F& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const PlaneF& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const ColorF& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const S32 f)
{
SHADERMATPARAM_SET(handle, f);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const Point2I& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const Point3I& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const Point4I& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv)
{
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType)
{
if ((!handle) || !handle->isValid())
return;
AssertFatal(dynamic_cast<ShaderMaterialParameterHandle*>(handle), "Invalid handle type!");
ShaderMaterialParameterHandle* h = static_cast<ShaderMaterialParameterHandle*>(handle);
AssertFatal(h->mHandles.size() == mBuffers.size(), "Handle length differs from buffer length!");
for (U32 i = 0; i < h->mHandles.size(); i++)
{
GFXShaderConstHandle* shaderHandle = h->mHandles[i];
if (shaderHandle && shaderHandle->isValid())
mBuffers[i]->set(shaderHandle, mat, matrixType);
}
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
{
if ((!handle) || !handle->isValid())
return;
AssertFatal(dynamic_cast<ShaderMaterialParameterHandle*>(handle), "Invalid handle type!");
ShaderMaterialParameterHandle* h = static_cast<ShaderMaterialParameterHandle*>(handle);
AssertFatal(h->mHandles.size() == mBuffers.size(), "Handle length differs from buffer length!");
for (U32 i = 0; i < h->mHandles.size(); i++)
{
GFXShaderConstHandle* shaderHandle = h->mHandles[i];
if (shaderHandle && shaderHandle->isValid())
mBuffers[i]->set(shaderHandle, mat, arraySize, matrixType);
}
}
#undef SHADERMATPARAM_SET

View file

@ -0,0 +1,100 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _SHADERMATERIALPARAMETERS_H_
#define _SHADERMATERIALPARAMETERS_H_
#ifndef _MATERIALPARAMETERS_H_
#include "materials/materialParameters.h"
#endif
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
class ShaderMaterialParameterHandle : public MaterialParameterHandle
{
friend class ShaderMaterialParameters;
public:
virtual ~ShaderMaterialParameterHandle();
ShaderMaterialParameterHandle(const String& name);
ShaderMaterialParameterHandle(const String& name, Vector<GFXShader*>& shaders);
virtual const String& getName() const { return mName; }
virtual S32 getSamplerRegister( U32 pass ) const;
// NOTE: We always return true here instead of querying the
// children... often there is only one element, so lets just
// hit the loop once on the set.
virtual bool isValid() const { return true; };
protected:
Vector< GFXShaderConstHandle* > mHandles;
String mName;
};
// This is the union of all of the shaders contained in a material
class ShaderMaterialParameters : public MaterialParameters
{
public:
ShaderMaterialParameters();
virtual ~ShaderMaterialParameters();
void setBuffers(Vector<GFXShaderConstDesc>& constDesc, Vector<GFXShaderConstBufferRef>& buffers);
GFXShaderConstBuffer* getBuffer(U32 i) { return mBuffers[i]; }
///
/// MaterialParameter interface
///
/// Returns the material parameter handle for name.
virtual void set(MaterialParameterHandle* handle, const F32 f);
virtual void set(MaterialParameterHandle* handle, const Point2F& fv);
virtual void set(MaterialParameterHandle* handle, const Point3F& fv);
virtual void set(MaterialParameterHandle* handle, const Point4F& fv);
virtual void set(MaterialParameterHandle* handle, const PlaneF& fv);
virtual void set(MaterialParameterHandle* handle, const ColorF& fv);
virtual void set(MaterialParameterHandle* handle, const S32 f);
virtual void set(MaterialParameterHandle* handle, const Point2I& fv);
virtual void set(MaterialParameterHandle* handle, const Point3I& fv);
virtual void set(MaterialParameterHandle* handle, const Point4I& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<F32>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point2F>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point3F>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point4F>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<S32>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point2I>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point3I>& fv);
virtual void set(MaterialParameterHandle* handle, const AlignedArray<Point4I>& fv);
virtual void set(MaterialParameterHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
virtual void set(MaterialParameterHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
virtual U32 getAlignmentValue(const GFXShaderConstType constType);
private:
Vector<GFXShaderConstBufferRef> mBuffers;
void releaseBuffers();
};
#endif