Jelajahi Sumber

Merge branch 'CustomShaderFeatures' of https://github.com/Areloch/Torque3D into development

Areloch 6 tahun lalu
induk
melakukan
c283295f22
37 mengubah file dengan 1367 tambahan dan 40 penghapusan
  1. 13 0
      Engine/source/T3D/tsStatic.cpp
  2. 2 0
      Engine/source/T3D/tsStatic.h
  3. 10 1
      Engine/source/materials/baseMatInstance.h
  4. 89 0
      Engine/source/materials/customShaderBindingData.h
  5. 6 0
      Engine/source/materials/matInstance.cpp
  6. 1 0
      Engine/source/materials/matInstance.h
  7. 41 0
      Engine/source/materials/materialDefinition.cpp
  8. 9 1
      Engine/source/materials/materialDefinition.h
  9. 1 1
      Engine/source/materials/processedCustomMaterial.cpp
  10. 1 0
      Engine/source/materials/processedFFMaterial.h
  11. 9 1
      Engine/source/materials/processedMaterial.h
  12. 108 3
      Engine/source/materials/processedShaderMaterial.cpp
  13. 13 1
      Engine/source/materials/processedShaderMaterial.h
  14. 3 1
      Engine/source/materials/sceneData.h
  15. 28 20
      Engine/source/renderInstance/renderBinManager.cpp
  16. 9 0
      Engine/source/renderInstance/renderDeferredMgr.cpp
  17. 7 0
      Engine/source/renderInstance/renderGlowMgr.cpp
  18. 7 0
      Engine/source/renderInstance/renderMeshMgr.cpp
  19. 5 0
      Engine/source/renderInstance/renderPassManager.h
  20. 7 0
      Engine/source/renderInstance/renderTranslucentMgr.cpp
  21. 3 0
      Engine/source/scene/sceneObject.h
  22. 468 0
      Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp
  23. 123 0
      Engine/source/shaderGen/HLSL/customFeatureHLSL.h
  24. 190 0
      Engine/source/shaderGen/customShaderFeature.cpp
  25. 84 0
      Engine/source/shaderGen/customShaderFeature.h
  26. 1 0
      Engine/source/shaderGen/langElement.cpp
  27. 57 3
      Engine/source/shaderGen/shaderGen.cpp
  28. 9 2
      Engine/source/shaderGen/shaderGen.h
  29. 3 1
      Engine/source/terrain/terrCellMaterial.cpp
  30. 2 0
      Engine/source/ts/tsMesh.cpp
  31. 2 1
      Engine/source/ts/tsRenderState.cpp
  32. 16 3
      Engine/source/ts/tsRenderState.h
  33. TEMPAT SAMPAH
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial 12 (ansi).uft
  34. TEMPAT SAMPAH
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 16 (ansi).uft
  35. TEMPAT SAMPAH
      Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 18 (ansi).uft
  36. TEMPAT SAMPAH
      Templates/BaseGame/game/core/gui/scripts/fonts/ArialItalic 14 (ansi).uft
  37. 40 1
      Templates/Full/game/art/shapes/cube/materials.cs

+ 13 - 0
Engine/source/T3D/tsStatic.cpp

@@ -203,6 +203,9 @@ void TSStatic::initPersistFields()
       addField( "originSort",    TypeBool,   Offset( mUseOriginSort, TSStatic ), 
          "Enables translucent sorting of the TSStatic by its origin instead of the bounds." );
 
+	  addField("overrideColor", TypeColorF, Offset(mOverrideColor, TSStatic),
+		  "@brief The skin applied to the shape.\n\n");
+
    endGroup("Rendering");
 
    addGroup( "Reflection" );
@@ -676,6 +679,12 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
    // Acculumation
    rdata.setAccuTex(mAccuTex);
 
+   //Various arbitrary shader render bits to add
+   CustomShaderBindingData strudelCSB;
+   strudelCSB.setFloat4(StringTable->insert("overrideColor"), mOverrideColor);
+
+   rdata.addCustomShaderBinding(strudelCSB);
+
    // If we have submesh culling enabled then prepare
    // the object space frustum to pass to the shape.
    Frustum culler;
@@ -852,6 +861,8 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
    {
       stream->writeRangedU32( reflectorDesc->getId(), DataBlockObjectIdFirst,  DataBlockObjectIdLast );
    }
+
+   stream->write(mOverrideColor);
    return retMask;
 }
 
@@ -947,6 +958,8 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream)
       cubeDescId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
    }
 
+   stream->read(&mOverrideColor);
+
    if ( isProperlyAdded() )
       _updateShouldTick();
    set_special_typing();

+ 2 - 0
Engine/source/T3D/tsStatic.h

@@ -197,6 +197,8 @@ protected:
 
    PhysicsBody *mPhysicsRep;
 
+   LinearColorF mOverrideColor;
+
    // Debug stuff
    F32 mRenderNormalScalar;
    S32 mForceDetail;

+ 10 - 1
Engine/source/materials/baseMatInstance.h

@@ -49,6 +49,13 @@
 #ifndef _MATSTATEHINT_H_
 #include "materials/matStateHint.h"
 #endif
+#ifndef _GFXDEVICE_H_
+#include "gfx/gfxDevice.h"
+#endif
+
+#ifndef CUSTOMSHADERBINDINGDATA_H
+#include "materials/customShaderBindingData.h"
+#endif
 
 struct RenderPassData;
 class GFXVertexBufferHandleBase;
@@ -60,7 +67,6 @@ class GFXVertexFormat;
 class MatrixSet;
 class ProcessedMaterial;
 
-
 ///
 class BaseMatInstance
 {
@@ -155,6 +161,9 @@ public:
    /// Sets node transforms for the current stage. Used for hardware skinning.
    virtual void setNodeTransforms( const MatrixF *address, const U32 numTransforms ) = 0;
 
+   /// Sets custom shader data
+   virtual void setCustomShaderData(Vector<CustomShaderBindingData> &shaderData) = 0;
+
    /// This initializes various material scene state settings and
    /// should be called after setupPass() within the pass loop.
    /// @see setupPass

+ 89 - 0
Engine/source/materials/customShaderBindingData.h

@@ -0,0 +1,89 @@
+#pragma once
+
+#ifndef CUSTOMSHADERBINDINGDATA_H
+#define CUSTOMSHADERBINDINGDATA_H
+#ifndef _GFXDEVICE_H_
+#include "gfx/gfxDevice.h"
+#endif
+
+struct CustomShaderBindingData
+{
+public:
+	enum UniformType
+	{
+		Float = 0,
+		Float2,
+		Float3,
+		Float4,
+		Texture2D,
+		Texture3D,
+		Cubemap,
+		Matrix2x2,
+		Matrix2x3,
+		Matrix2x4,
+		Matrix3x2,
+		Matrix3x3,
+		Matrix3x4,
+		Matrix4x2,
+		Matrix4x3,
+		Matrix4x4
+	};
+private:
+	StringTableEntry targetedUniformName;
+
+	//ShaderConstHandles shaderConstHandle;
+
+	UniformType type;
+
+	F32 mFloat;
+	Point2F mFloat2;
+	Point3F mFloat3;
+	Point4F mFloat4;
+
+	//Image stuff
+	GFXTexHandle texture;
+	GFXSamplerStateDesc samplerState;
+
+public:
+	void setFloat(StringTableEntry shaderConstName, F32 f)
+	{
+		targetedUniformName = shaderConstName;
+		mFloat = f;
+		type = Float;
+	}
+	F32 getFloat() { return mFloat; }
+
+	void setFloat2(StringTableEntry shaderConstName, Point2F f)
+	{
+		targetedUniformName = shaderConstName;
+		mFloat2 = f;
+		type = Float2;
+	}
+	Point2F getFloat2() { return mFloat2; }
+
+	void setFloat3(StringTableEntry shaderConstName, Point3F f)
+	{
+		targetedUniformName = shaderConstName;
+		mFloat3 = f;
+		type = Float3;
+	}
+	Point3F getFloat3() { return mFloat3; }
+
+	void setFloat4(StringTableEntry shaderConstName, Point4F f)
+	{
+		targetedUniformName = shaderConstName;
+		mFloat4 = f;
+		type = Float4;
+	}
+	Point4F getFloat4() { return mFloat4; }
+
+	StringTableEntry getHandleName() {
+		return targetedUniformName;
+	}
+
+	UniformType getType() {
+		return type;
+	}
+};
+
+#endif

+ 6 - 0
Engine/source/materials/matInstance.cpp

@@ -473,6 +473,12 @@ void MatInstance::setNodeTransforms(const MatrixF *address, const U32 numTransfo
    mProcessedMaterial->setNodeTransforms(address, numTransforms, getCurPass());
 }
 
+void MatInstance::setCustomShaderData(Vector<CustomShaderBindingData> &shaderData)
+{
+	PROFILE_SCOPE(MatInstance_setCustomShaderData);
+	mProcessedMaterial->setCustomShaderData(shaderData, getCurPass());
+}
+
 void MatInstance::setSceneInfo(SceneRenderState * state, const SceneData& sgData)
 {
    PROFILE_SCOPE(MatInstance_setSceneInfo);

+ 1 - 0
Engine/source/materials/matInstance.h

@@ -66,6 +66,7 @@ public:
    virtual bool setupPass(SceneRenderState *, const SceneData &sgData );
    virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state);
    virtual void setNodeTransforms(const MatrixF *address, const U32 numTransforms);
+   virtual void setCustomShaderData(Vector<CustomShaderBindingData> &shaderData);
    virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData);
    virtual void setTextureStages(SceneRenderState * state, const SceneData &sgData );
    virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer);

+ 41 - 0
Engine/source/materials/materialDefinition.cpp

@@ -504,6 +504,11 @@ void Material::initPersistFields()
 
    endGroup( "Behavioral" );
 
+   addProtectedField("customShaderFeature", TypeRealString, NULL, &protectedSetCustomShaderFeature, &defaultProtectedGetFn,
+	   "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors);
+   addProtectedField("CustomShaderFeatureUniforms", TypeRealString, NULL, &protectedSetCustomShaderFeatureUniforms, &defaultProtectedGetFn,
+	   "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors);
+
    Parent::initPersistFields();
 }
 
@@ -521,6 +526,42 @@ bool Material::writeField( StringTableEntry fieldname, const char *value )
    return Parent::writeField( fieldname, value );
 }
 
+bool Material::protectedSetCustomShaderFeature(void *object, const char *index, const char *data)
+{
+	Material *material = static_cast< Material* >(object);
+
+	CustomShaderFeatureData* customFeature;
+	if (!Sim::findObject(data, customFeature))
+		return false;
+
+	material->mCustomShaderFeatures.push_back(customFeature);
+
+	return false;
+}
+
+bool Material::protectedSetCustomShaderFeatureUniforms(void *object, const char *index, const char *data)
+{
+	Material *material = static_cast< Material* >(object);
+
+	//CustomShaderFeatureData* customFeature;
+	//if (!Sim::findObject(data, customFeature))
+	//	return false;
+
+	//material->mCustomShaderFeatures.push_back(customFeature);
+	if (index != NULL)
+	{
+		char featureName[256] = { 0 };
+		U32 id = 0;
+		dSscanf(index, "%s_%i", featureName, id);
+
+		String uniformName = data;
+
+		bool tmp = true;
+	}
+
+	return false;
+}
+
 bool Material::onAdd()
 {
    if (Parent::onAdd() == false)

+ 9 - 1
Engine/source/materials/materialDefinition.h

@@ -41,6 +41,9 @@
    #include "console/dynamicTypes.h"
 #endif
 
+#ifndef CUSTOMSHADERFEATURE_H
+#include "shaderGen/customShaderFeature.h"
+#endif
 
 class CubemapData;
 class SFXTrack;
@@ -49,7 +52,7 @@ class FeatureSet;
 class FeatureType;
 class MaterialSoundProfile;
 class MaterialPhysicsProfile;
-
+class CustomShaderFeatureData;
 
 /// The basic material definition.
 class Material : public BaseMaterialDefinition
@@ -348,6 +351,8 @@ public:
    F32 mDirectSoundOcclusion;       ///< Amount of volume occlusion on direct sounds.
    F32 mReverbSoundOcclusion;       ///< Amount of volume occlusion on reverb sounds.
 
+   Vector<CustomShaderFeatureData*> mCustomShaderFeatures;
+
    ///@}
    
    String mMapTo; // map Material to this texture name
@@ -385,6 +390,9 @@ public:
    virtual void inspectPostApply();
    virtual bool writeField( StringTableEntry fieldname, const char *value );
 
+   static bool protectedSetCustomShaderFeature(void *object, const char *index, const char *data);
+   static bool protectedSetCustomShaderFeatureUniforms(void *object, const char *index, const char *data);
+
    //
    // ConsoleObject interface
    //

+ 1 - 1
Engine/source/materials/processedCustomMaterial.cpp

@@ -246,7 +246,7 @@ bool ProcessedCustomMaterial::init( const FeatureSet &features,
       return false;
    }
 
-   rpd->shaderHandles.init( rpd->shader, mCustomMaterial );      
+   rpd->shaderHandles.init( rpd->shader, mCustomMaterial->mCustomShaderFeatures, mCustomMaterial );
    _initMaterialParameters();
    mDefaultParameters = allocMaterialParameters();
    setMaterialParameters( mDefaultParameters, 0 );

+ 1 - 0
Engine/source/materials/processedFFMaterial.h

@@ -54,6 +54,7 @@ public:
    
    virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass);
    virtual void setNodeTransforms(const MatrixF *address, const U32 numTransforms, const U32 pass) {;}
+   virtual void setCustomShaderData(Vector<CustomShaderBindingData> &shaderData, const U32 pass) {;} //-JR
 
    virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass);
 

+ 9 - 1
Engine/source/materials/processedMaterial.h

@@ -39,6 +39,10 @@
 #include "materials/matStateHint.h"
 #endif
 
+#ifndef CUSTOMSHADERBINDINGDATA_H
+#include "materials/customShaderBindingData.h"
+#endif
+
 class ShaderFeature;
 class MaterialParameters;
 class MaterialParameterHandle;
@@ -47,7 +51,6 @@ class GFXVertexBufferHandleBase;
 class GFXPrimitiveBufferHandle;
 class MatrixSet;
 
-
 /// This contains the common data needed to render a pass.
 struct RenderPassData
 {
@@ -81,6 +84,8 @@ public:
 
    MaterialFeatureData mFeatureData;
 
+   Vector<CustomShaderFeatureData*> mCustomShaderFeatureData;
+
    bool mGlow;
 
    Material::BlendOp mBlendOp;
@@ -144,6 +149,9 @@ public:
    
    /// Sets the node transforms for HW Skinning
    virtual void setNodeTransforms(const MatrixF *address, const U32 numTransforms, const U32 pass) = 0;
+
+   /// Sets any custom shader data
+   virtual void setCustomShaderData(Vector<CustomShaderBindingData> &shaderData, const U32 pass) = 0;
    
    /// Sets the scene info like lights for the given pass.
    virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass) = 0;

+ 108 - 3
Engine/source/materials/processedShaderMaterial.cpp

@@ -43,6 +43,8 @@
 
 #include "renderInstance/renderProbeMgr.h"
 
+#include "ts/tsRenderState.h"
+
 // We need to include customMaterialDefinition for ShaderConstHandles::init
 #include "materials/customMaterialDefinition.h"
 
@@ -52,7 +54,7 @@
 ///
 /// ShaderConstHandles
 ///
-void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/ )
+void ShaderConstHandles::init( GFXShader *shader, Vector<CustomShaderFeatureData*> customFeatureData, CustomMaterial* mat /*=NULL*/)
 {
    mDiffuseColorSC = shader->getShaderConstHandle("$diffuseMaterialColor");
    mTexMatSC = shader->getShaderConstHandle(ShaderGenVars::texMat);
@@ -119,6 +121,19 @@ void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/
 
    // Deferred Shading
    mMatInfoFlagsSC = shader->getShaderConstHandle(ShaderGenVars::matInfoFlags);
+
+   //custom features
+   for (U32 f = 0; f < customFeatureData.size(); ++f)
+   {
+	   for (U32 i = 0; i < customFeatureData[f]->mAddedShaderConstants.size(); ++i)
+	   {
+		   customHandleData newSC;
+		   newSC.handle = shader->getShaderConstHandle(String("$") + String(customFeatureData[f]->mAddedShaderConstants[i]));
+		   newSC.handleName = customFeatureData[f]->mAddedShaderConstants[i];
+
+		   mCustomHandles.push_back(newSC);
+}
+   }
 }
 
 ///
@@ -655,10 +670,10 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd,
 
    // Generate shader
    GFXShader::setLogging( true, true );
-   rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros, samplers );
+   rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mMaterial->mCustomShaderFeatures, mVertexFormat, &mUserMacros, samplers );
    if( !rpd.shader )
       return false;
-   rpd.shaderHandles.init( rpd.shader );   
+   rpd.shaderHandles.init( rpd.shader, mMaterial->mCustomShaderFeatures);
 
    // If a pass glows, we glow
    if( rpd.mGlow )
@@ -1196,6 +1211,31 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons
       shaderConsts->set( handles->mAccuCoverageSC, mMaterial->mAccuCoverage[stageNum] );
    if( handles->mAccuSpecularSC->isValid() )
       shaderConsts->set( handles->mAccuSpecularSC, mMaterial->mAccuSpecular[stageNum] );
+
+	/*for (U32 i = 0; i < sgData.customShaderData.size(); i++)
+	{
+		//roll through and try setting our data!
+		for (U32 h = 0; h < handles->mCustomHandles.size(); ++h)
+		{
+			StringTableEntry handleName = sgData.customShaderData[i]->getHandleName();
+			StringTableEntry rpdHandleName = handles->mCustomHandles[h].handleName;
+			if (handles->mCustomHandles[h].handleName == sgData.customShaderData[i]->getHandleName())
+			{
+				if (handles->mCustomHandles[h].handle->isValid())
+				{
+					if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat());
+					else if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float2)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat2());
+					else if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float3)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat3());
+					else if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float4)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat4());
+					break;
+}
+			}
+		}
+	}*/
 }
 
 bool ProcessedShaderMaterial::_hasCubemap(U32 pass)
@@ -1262,6 +1302,46 @@ void ProcessedShaderMaterial::setNodeTransforms(const MatrixF *transforms, const
    }
 }
 
+void ProcessedShaderMaterial::setCustomShaderData(Vector<CustomShaderBindingData> &shaderData, const U32 pass)
+{
+	PROFILE_SCOPE(ProcessedShaderMaterial_setCustomShaderData);
+
+	GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
+	ShaderConstHandles* handles = _getShaderConstHandles(pass);
+
+	for (U32 i = 0; i < shaderData.size(); i++)
+	{
+		for (U32 h = 0; h < handles->mCustomHandles.size(); ++h)
+		{
+			StringTableEntry handleName = shaderData[i].getHandleName();
+			bool tmp = true;
+		}
+		//roll through and try setting our data!
+		for (U32 h = 0; h < handles->mCustomHandles.size(); ++h)
+		{
+			StringTableEntry handleName = shaderData[i].getHandleName();
+			StringTableEntry rpdHandleName = handles->mCustomHandles[h].handleName;
+			if (handles->mCustomHandles[h].handleName == shaderData[i].getHandleName())
+			{
+				if (handles->mCustomHandles[h].handle->isValid())
+				{
+					CustomShaderBindingData::UniformType type = shaderData[i].getType();
+
+					if (type == CustomShaderBindingData::Float)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat());
+					else if (type == CustomShaderBindingData::Float2)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat2());
+					else if (type == CustomShaderBindingData::Float3)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat3());
+					else if (type == CustomShaderBindingData::Float4)
+						shaderConsts->setSafe(handles->mCustomHandles[h].handle, shaderData[i].getFloat4());
+					break;
+				}
+			}
+		}
+	}
+}
+
 void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const SceneData& sgData, U32 pass)
 {
    PROFILE_SCOPE(ProcessedShaderMaterial_setSceneInfo);
@@ -1303,6 +1383,31 @@ void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const Scene
    for (U32 i = 0; i < rpd->featureShaderHandles.size(); i++)
       rpd->featureShaderHandles[i]->setConsts(state, sgData, shaderConsts);
 
+   /*for (U32 i = 0; i < sgData.customShaderData.size(); i++)
+   {
+	   //roll through and try setting our data!
+	   for (U32 h = 0; h < handles->mCustomHandles.size(); ++h)
+	   {
+		   StringTableEntry handleName = sgData.customShaderData[i]->getHandleName();
+		   StringTableEntry rpdHandleName = handles->mCustomHandles[h].handleName;
+		   if (handles->mCustomHandles[h].handleName == sgData.customShaderData[i]->getHandleName())
+		   {
+			   if (handles->mCustomHandles[h].handle->isValid())
+			   {
+				   if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float)
+					   shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat());
+				   else if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float2)
+					   shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat2());
+				   else if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float3)
+					   shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat3());
+				   else if (sgData.customShaderData[i]->getType() == CustomShaderBindingData::Float4)
+					   shaderConsts->setSafe(handles->mCustomHandles[h].handle, sgData.customShaderData[i]->getFloat4());
+				   break;
+			   }
+		   }
+	   }
+   }*/
+
    LIGHTMGR->setLightInfo(this, mMaterial, sgData, state, pass, shaderConsts);
 
    PROBEMGR->setProbeInfo(this, mMaterial, sgData, state, pass, shaderConsts);

+ 13 - 1
Engine/source/materials/processedShaderMaterial.h

@@ -29,6 +29,9 @@
 #ifndef _GFXSHADER_H_
 #include "gfx/gfxShader.h"
 #endif
+#ifndef CUSTOMSHADERBINDINGDATA_H
+#include "materials/customShaderBindingData.h"
+#endif
 
 class GenericConstBufferLayout;
 class ShaderData;
@@ -97,7 +100,15 @@ public:
 
    GFXShaderConstHandle* mNodeTransforms;
 
-   void init( GFXShader* shader, CustomMaterial* mat = NULL );
+   struct customHandleData
+   {
+	   StringTableEntry handleName;
+	   GFXShaderConstHandle* handle;
+   };
+   Vector<customHandleData> mCustomHandles;
+
+   void init( GFXShader* shader, Vector<CustomShaderFeatureData*> customFeatureData, CustomMaterial* mat = NULL);
+   
 };
 
 class ShaderRenderPassData : public RenderPassData
@@ -133,6 +144,7 @@ public:
    virtual void setTextureStages(SceneRenderState *, const SceneData &sgData, U32 pass );
    virtual void setTransforms(const MatrixSet &matrixSet, SceneRenderState *state, const U32 pass);
    virtual void setNodeTransforms(const MatrixF *address, const U32 numTransforms, const U32 pass);
+   virtual void setCustomShaderData(Vector<CustomShaderBindingData> &shaderData, const U32 pass);
    virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass);
    virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer); 
    virtual bool stepInstance();

+ 3 - 1
Engine/source/materials/sceneData.h

@@ -34,7 +34,7 @@
 
 class GFXTexHandle;
 class GFXCubemap;
-
+class CustomShaderBindingData;
 
 struct SceneData
 {
@@ -95,6 +95,8 @@ struct SceneData
    /// features.
    void *materialHint;
 
+   Vector<CustomShaderBindingData*> customShaderData;
+
    /// Constructor.
    SceneData() 
    { 

+ 28 - 20
Engine/source/renderInstance/renderBinManager.cpp

@@ -151,27 +151,35 @@ S32 FN_CDECL RenderBinManager::cmpKeyFunc(const void* p1, const void* p2)
    return ( test1 == 0 ) ? S32(mse1->key2) - S32(mse2->key2) : test1;
 }
 
-void RenderBinManager::setupSGData( MeshRenderInst *ri, SceneData &data )
+void RenderBinManager::setupSGData(MeshRenderInst *ri, SceneData &data)
 {
-   PROFILE_SCOPE( RenderBinManager_setupSGData );
-
-   // NOTE: We do not reset or clear the scene state 
-   // here as the caller has initialized non-RI members 
-   // himself and we must preserve them.
-   //
-   // It also saves a bunch of CPU as this is called for
-   // every MeshRenderInst in every pass. 
-
-   dMemcpy( data.lights, ri->lights, sizeof( data.lights ) );
-   data.objTrans     = ri->objectToWorld;
-   data.backBuffTex  = ri->backBuffTex;
-   data.cubemap      = ri->cubemap;
-   data.miscTex      = ri->miscTex;
-   data.reflectTex   = ri->reflectTex;
-   data.accuTex      = ri->accuTex;
-   data.lightmap     = ri->lightmap;
-   data.visibility   = ri->visibility;
-   data.materialHint = ri->materialHint;
+	PROFILE_SCOPE(RenderBinManager_setupSGData);
+
+	// NOTE: We do not reset or clear the scene state 
+	// here as the caller has initialized non-RI members 
+	// himself and we must preserve them.
+	//
+	// It also saves a bunch of CPU as this is called for
+	// every MeshRenderInst in every pass. 
+
+	dMemcpy(data.lights, ri->lights, sizeof(data.lights));
+	data.objTrans = ri->objectToWorld;
+	data.backBuffTex = ri->backBuffTex;
+	data.cubemap = ri->cubemap;
+	data.miscTex = ri->miscTex;
+	data.reflectTex = ri->reflectTex;
+	data.accuTex = ri->accuTex;
+	data.lightmap = ri->lightmap;
+	data.visibility = ri->visibility;
+	data.materialHint = ri->materialHint;
+
+	data.customShaderData.clear();
+	for (U32 i = 0; i < ri->mCustomShaderData.size(); i++)
+	{
+		data.customShaderData.push_back(&ri->mCustomShaderData[i]);
+	}
+
+    bool bl = true;
 }
 
 DefineEngineMethod( RenderBinManager, getBinType, const char*, (),,

+ 9 - 0
Engine/source/renderInstance/renderDeferredMgr.cpp

@@ -51,6 +51,8 @@
 #include "materials/shaderData.h"
 #include "gfx/sim/cubemapData.h"
 
+#include "materials/customShaderBindingData.h"
+
 const MatInstanceHookType DeferredMatInstanceHook::Type( "Deferred" );
 const String RenderDeferredMgr::BufferName("deferred");
 const RenderInstType RenderDeferredMgr::RIT_Deferred("Deferred");
@@ -422,6 +424,13 @@ void RenderDeferredMgr::render( SceneRenderState *state )
                mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
             }
 
+			//-JR
+			//push along any overriden fields that are instance-specific as well
+			if (passRI->mCustomShaderData.size() > 0)
+			{
+				mat->setCustomShaderData(passRI->mCustomShaderData);
+			}
+
             // If we're instanced then don't render yet.
             if ( mat->isInstanced() )
             {

+ 7 - 0
Engine/source/renderInstance/renderGlowMgr.cpp

@@ -251,6 +251,13 @@ void RenderGlowMgr::render( SceneRenderState *state )
                glowMat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
             }
 
+			//-JR
+			//push along any overriden fields that are instance-specific as well
+			if (passRI->mCustomShaderData.size() > 0)
+			{
+				mat->setCustomShaderData(passRI->mCustomShaderData);
+			}
+
             glowMat->setSceneInfo(state, sgData);
             glowMat->setBuffers(passRI->vertBuff, passRI->primBuff);
 

+ 7 - 0
Engine/source/renderInstance/renderMeshMgr.cpp

@@ -182,6 +182,13 @@ void RenderMeshMgr::render(SceneRenderState * state)
                mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
             }
 
+			//-JR
+			//push along any overriden fields that are instance-specific as well
+			if (passRI->mCustomShaderData.size() > 0)
+			{
+				mat->setCustomShaderData(passRI->mCustomShaderData);
+			}
+
             setupSGData( passRI, sgData );
             mat->setSceneInfo( state, sgData );
 

+ 5 - 0
Engine/source/renderInstance/renderPassManager.h

@@ -59,6 +59,8 @@ class MatrixSet;
 class GFXPrimitiveBufferHandle;
 class CubemapData;
 
+class CustomShaderBindingData;
+
 /// A RenderInstType hash value.
 typedef U32 RenderInstTypeHash;
 
@@ -393,6 +395,9 @@ struct MeshRenderInst : public RenderInst
    const char *objectName;
 #endif
 
+   //Custom Shader data
+   Vector<CustomShaderBindingData> mCustomShaderData;
+
    void clear();
 };
 

+ 7 - 0
Engine/source/renderInstance/renderTranslucentMgr.cpp

@@ -256,6 +256,13 @@ void RenderTranslucentMgr::render( SceneRenderState *state )
                   mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
                }
 
+			   //-JR
+			   //push along any overriden fields that are instance-specific as well
+			   if (passRI->mCustomShaderData.size() > 0)
+			   {
+				   mat->setCustomShaderData(passRI->mCustomShaderData);
+			   }
+
                // If we're instanced then don't render yet.
                if ( mat->isInstanced() )
                {

+ 3 - 0
Engine/source/scene/sceneObject.h

@@ -59,6 +59,9 @@
 #ifndef _GFXDEVICE_H_
 #include "gfx/gfxDevice.h"
 #endif
+#ifndef _TSRENDERDATA_H_
+#include "ts/tsRenderState.h"
+#endif
 
 #ifndef _COLLADA_UTILS_H_
 #include "ts/collada/colladaUtils.h"

+ 468 - 0
Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp

@@ -0,0 +1,468 @@
+//-----------------------------------------------------------------------------
+// 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 "customFeatureHLSL.h"
+#include "shaderGen/shaderFeature.h"
+#include "shaderGen/shaderOp.h"
+#include "shaderGen/featureMgr.h"
+//#include "materials/materialFeatureTypes.h"
+//#include "gfx/gfxDevice.h"
+//#include "materials/processedMaterial.h"
+
+//****************************************************************************
+// Accu Texture
+//****************************************************************************
+void CustomFeatureHLSL::processVert(Vector<ShaderComponent*> &componentList,
+	const MaterialFeatureData &fd)
+{
+	/*MultiLine *meta = new MultiLine;
+	getOutTexCoord(   "texCoord",
+	"float2",
+	false,
+	meta,
+	componentList );
+
+	getOutObjToTangentSpace( componentList, meta, fd );
+
+	output = meta;*/
+
+	meta = new MultiLine;
+
+	mFeatureData = fd;
+	mComponentList = componentList;
+
+	mOutputState = VertexOutput;
+
+	if (mOwner->isMethod("processVertHLSL"))
+		Con::executef(mOwner, "processVertHLSL");
+
+	output = meta;
+}
+
+void CustomFeatureHLSL::processPix(Vector<ShaderComponent*> &componentList,
+	const MaterialFeatureData &fd)
+{
+	meta = new MultiLine;
+
+	mFeatureData = fd;
+	mComponentList = componentList;
+
+	mOutputState = PixelOutput;
+	
+	/*MultiLine *meta = new MultiLine;
+
+	output = meta;
+
+	// OUT.col
+	Var *color = (Var*) LangElement::find( "col1" );
+	if (!color)
+	{
+	output = new GenOp("   //NULL COLOR!");
+	return;
+	}
+
+	// accu map
+	Var *accuMap = new Var;
+	accuMap->setType("SamplerState");
+
+	accuMap->setName( "accuMap" );
+	accuMap->uniform = true;
+	accuMap->sampler = true;
+	accuMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
+
+	// accuColor var
+	Var *accuColor = new Var;
+	accuColor->setType( "float4" );
+	accuColor->setName( "accuColor" );
+	LangElement *colorAccuDecl = new DecOp( accuColor );
+
+	// plc (placement)
+	Var *accuPlc = new Var;
+	accuPlc->setType( "float4" );
+	accuPlc->setName( "plc" );
+	LangElement *plcAccu = new DecOp( accuPlc );
+
+	// accu constants
+	Var *accuScale = (Var*)LangElement::find( "accuScale" );
+	if ( !accuScale )
+	{
+	accuScale = new Var;
+	accuScale->setType( "float" );
+	accuScale->setName( "accuScale" );
+	accuScale->uniform = true;
+	accuScale->sampler = false;
+	accuScale->constSortPos = cspPotentialPrimitive;
+	}
+	Var *accuDirection = (Var*)LangElement::find( "accuDirection" );
+	if ( !accuDirection )
+	{
+	accuDirection = new Var;
+	accuDirection->setType( "float" );
+	accuDirection->setName( "accuDirection" );
+	accuDirection->uniform = true;
+	accuDirection->sampler = false;
+	accuDirection->constSortPos = cspPotentialPrimitive;
+	}
+	Var *accuStrength = (Var*)LangElement::find( "accuStrength" );
+	if ( !accuStrength )
+	{
+	accuStrength = new Var;
+	accuStrength->setType( "float" );
+	accuStrength->setName( "accuStrength" );
+	accuStrength->uniform = true;
+	accuStrength->sampler = false;
+	accuStrength->constSortPos = cspPotentialPrimitive;
+	}
+	Var *accuCoverage = (Var*)LangElement::find( "accuCoverage" );
+	if ( !accuCoverage )
+	{
+	accuCoverage = new Var;
+	accuCoverage->setType( "float" );
+	accuCoverage->setName( "accuCoverage" );
+	accuCoverage->uniform = true;
+	accuCoverage->sampler = false;
+	accuCoverage->constSortPos = cspPotentialPrimitive;
+	}
+	Var *accuSpecular = (Var*)LangElement::find( "accuSpecular" );
+	if ( !accuSpecular )
+	{
+	accuSpecular = new Var;
+	accuSpecular->setType( "float" );
+	accuSpecular->setName( "accuSpecular" );
+	accuSpecular->uniform = true;
+	accuSpecular->sampler = false;
+	accuSpecular->constSortPos = cspPotentialPrimitive;
+	}
+
+	Var *inTex = getInTexCoord( "texCoord", "float2", componentList );
+	Var *accuVec = getInTexCoord( "accuVec", "float3", componentList );
+	Var *bumpNorm = (Var *)LangElement::find( "bumpSample" );
+	if( bumpNorm == NULL )
+	{
+	bumpNorm = (Var *)LangElement::find( "bumpNormal" );
+	if (!bumpNorm)
+	return;
+	}
+
+	// get the accu pixel color
+
+	Var *accuMapTex = new Var;
+	accuMapTex->setType("Texture2D");
+	accuMapTex->setName("accuMapTex");
+	accuMapTex->uniform = true;
+	accuMapTex->texture = true;
+	accuMapTex->constNum = accuMap->constNum;
+	meta->addStatement(new GenOp("   @ = @.Sample(@, @ * @);\r\n", colorAccuDecl, accuMapTex, accuMap, inTex, accuScale));
+
+	// scale up normals
+	meta->addStatement( new GenOp( "   @.xyz = @.xyz * 2.0 - 0.5;\r\n", bumpNorm, bumpNorm ) );
+
+	// assign direction
+	meta->addStatement( new GenOp( "   @.z *= @*2.0;\r\n", accuVec, accuDirection ) );
+
+	// saturate based on strength
+	meta->addStatement( new GenOp( "   @ = saturate( dot( @.xyz, @.xyz * pow(@, 5) ) );\r\n", plcAccu, bumpNorm, accuVec, accuStrength ) );
+
+	// add coverage
+	meta->addStatement( new GenOp( "   @.a += (2 * pow(@/2, 5)) - 0.5;\r\n", accuPlc, accuCoverage ) );
+
+	// clamp to a sensible value
+	meta->addStatement( new GenOp( "   @.a = clamp(@.a, 0, 1);\r\n", accuPlc, accuPlc ) );
+
+	// light
+	Var *lightColor = (Var*) LangElement::find( "d_lightcolor" );
+	if(lightColor != NULL)
+	meta->addStatement( new GenOp( "   @ *= float4(@, 1.0);\r\n\r\n", accuColor, lightColor ) );
+
+	// lerp with current pixel - use the accu alpha as well
+	meta->addStatement( new GenOp( "   @ = lerp( @, @, @.a * @.a);\r\n", color, color, accuColor, accuPlc, accuColor ) );
+
+	// the result should always be opaque
+	meta->addStatement( new GenOp( "   @.a = 1.0;\r\n", color ) );*/
+	if (mOwner->isMethod("processPixelHLSL"))
+		Con::executef(mOwner, "processPixelHLSL");
+
+	output = meta;
+}
+
+void CustomFeatureHLSL::setTexData(Material::StageData &stageDat,
+	const MaterialFeatureData &fd,
+	RenderPassData &passData,
+	U32 &texIndex)
+{
+	//GFXTextureObject *tex = stageDat.getTex( MFT_AccuMap );
+	//if ( tex )
+	//{
+	//passData.mSamplerNames[ texIndex ] = "AccuMap";
+	//passData.mTexType[ texIndex++ ] = Material::AccuMap;
+	//}
+
+	if (mOwner->isMethod("setTextureData"))
+		Con::executef(mOwner, "setTextureData");
+}
+
+void CustomFeatureHLSL::addUniform(String name, String type, String defaultValue, U32 arraySize)
+{
+	//do the var/arg fetching here
+	Var *newVar = (Var*)LangElement::find(name.c_str());
+	if (!newVar)
+	{
+		VarHolder newVarHolder(name, type, "");
+		newVarHolder.arraySize = arraySize;
+		newVarHolder.sampler = false;
+		newVarHolder.uniform = true;
+		newVarHolder.constSortPos = cspPotentialPrimitive;
+
+		mVars.push_back(newVarHolder);
+
+		mOwner->mAddedShaderConstants.push_back(StringTable->insert(name.c_str()));
+	}
+}
+
+void CustomFeatureHLSL::addSampler(String name, String type, U32 arraySize)
+{
+	//do the var/arg fetching here
+	Var *newVar = (Var*)LangElement::find(name.c_str());
+	if (!newVar)
+	{
+		//As far as I know, it's always SamplerState regardless of the texture's type
+		VarHolder newVarHolder(name, "SamplerState", "");
+		newVarHolder.arraySize = arraySize;
+		newVarHolder.sampler = true;
+		newVarHolder.uniform = true;
+		newVarHolder.constNum = Var::getTexUnitNum();     // used as texture unit num here
+
+		mVars.push_back(newVarHolder);
+
+		mOwner->mAddedShaderConstants.push_back(StringTable->insert(name.c_str()));
+	}
+}
+
+void CustomFeatureHLSL::addTexture(String name, String type, String samplerState, U32 arraySize)
+{
+	//do the var/arg fetching here
+	Var *newVar = (Var*)LangElement::find(name.c_str());
+	if (!newVar)
+	{
+		//go find our sampler state var
+		U32 constNum = 0;
+
+		Var *samplerStateVar = (Var*)LangElement::find(samplerState.c_str());
+		if (!samplerStateVar)
+		{
+			//check our holder vars
+			bool foundHolder = false;
+			for (U32 v = 0; v < mVars.size(); v++)
+			{
+				if (mVars[v].varName == samplerState)
+				{
+					constNum = mVars[v].constNum;
+					foundHolder = true;
+					break;
+				}
+			}
+
+			if (!foundHolder)
+			{
+				Con::errorf("CustomShaderFeature::addTexture: Unable to find texture's sampler state!");
+				return;
+			}
+		}
+		else
+		{
+			constNum = samplerStateVar->constNum;
+		}
+
+		VarHolder newVarHolder(name, type, "");
+		newVarHolder.arraySize = arraySize;
+		newVarHolder.texture = true;
+		newVarHolder.uniform = true;
+		newVarHolder.constNum = constNum;     // used as texture unit num here
+
+		mVars.push_back(newVarHolder);
+
+		mOwner->mAddedShaderConstants.push_back(StringTable->insert(name.c_str()));
+	}
+}
+
+void CustomFeatureHLSL::addVariable(String name, String type, String defaultValue)
+{
+	//do the var/arg fetching here
+	Var *newVar = (Var*)LangElement::find(name.c_str());
+	if (!newVar)
+	{
+		if (!defaultValue.isEmpty())
+		{
+			char declareStatement[128];
+			dSprintf(declareStatement, 128, "   @ = %s;\n", defaultValue.c_str());
+
+			newVar = new Var(name, type);
+			LangElement *newVarDecl = new DecOp(newVar);
+			meta->addStatement(new GenOp(declareStatement, newVarDecl));
+		}
+		else
+		{
+			VarHolder newVarHolder(name, type, defaultValue);
+
+			mVars.push_back(newVarHolder);
+		}
+	}
+}
+
+void CustomFeatureHLSL::addConnector(String name, String elementName, String type)
+{
+	// grab connector texcoord register
+	ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(mComponentList[C_CONNECTOR]);
+
+	//Get element
+	S32 element = -1;
+
+	if (elementName == String("RT_POSITION"))
+		element = RT_POSITION;
+	else if (elementName == String("RT_NORMAL"))
+		element = RT_NORMAL;
+	else if (elementName == String("RT_BINORMAL"))
+		element = RT_BINORMAL;
+	else if (elementName == String("RT_TANGENT"))
+		element = RT_TANGENT;
+	else if (elementName == String("RT_TANGENTW"))
+		element = RT_TANGENTW;
+	else if (elementName == String("RT_COLOR"))
+		element = RT_COLOR;
+	else if (elementName == String("RT_TEXCOORD"))
+		element = RT_TEXCOORD;
+	else if (elementName == String("RT_VPOS"))
+		element = RT_VPOS;
+	else if (elementName == String("RT_SVPOSITION"))
+		element = RT_SVPOSITION;
+	else if (elementName == String("RT_BLENDINDICES"))
+		element = RT_BLENDINDICES;
+	else if (elementName == String("RT_BLENDWEIGHT"))
+		element = RT_BLENDWEIGHT;
+
+	if (element == -1)
+	{
+		Con::errorf("CustomShaderFeatureHLSL::addConnector - Invalid element type %s", elementName.c_str());
+		return;
+	}
+
+	Var *connector = connectComp->getElement((RegisterType)element);
+	connector->setName(name);
+
+	if (mOutputState == VertexOutput)
+		connector->setStructName("OUT");
+	else if(mOutputState == PixelOutput)
+		connector->setStructName("IN");
+
+	connector->setType(type);
+}
+
+void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef *argv)
+{
+	//do the var/arg fetching here
+	Vector<Var*> varList;
+	bool declarationStatement = false;
+
+	for (U32 i = 0; i < argc; i++)
+	{
+		String varName = argv[i].getStringValue();
+		Var *newVar = (Var*)LangElement::find(varName.c_str());
+		if (!newVar)
+		{
+			//ok, check our existing var holders, see if we just haven't utilized it yet
+			for (U32 v = 0; v < mVars.size(); v++)
+			{
+				if (mVars[v].varName == varName)
+				{
+					Var* newDeclVar = new Var(mVars[v].varName, mVars[v].type);
+
+					newDeclVar->arraySize = mVars[v].arraySize;
+					newDeclVar->uniform = mVars[v].uniform;
+					newDeclVar->sampler = mVars[v].sampler;
+					newDeclVar->texture = mVars[v].texture;
+					newDeclVar->constNum = mVars[v].constNum;
+					newDeclVar->constSortPos = mVars[v].constSortPos;
+
+					if (!newDeclVar->uniform)
+					{
+						LangElement *newVarDecl = new DecOp(newDeclVar);
+						newVar = (Var*)newVarDecl;
+
+						declarationStatement = true;
+					}
+					else
+					{
+						newVar = newDeclVar;
+					}
+
+					mVars.erase(v);
+					break;
+				}
+			}
+
+			if (!newVar)
+			{
+				//couldn't find that variable, bail out
+				Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getStringValue());
+				return;
+			}
+		}
+
+		varList.push_back(newVar);
+	}
+
+	//not happy about it, but do a trampoline here to pass along the args
+
+	switch (varList.size())
+	{
+	case 0:
+		meta->addStatement(new GenOp(format + "\n"));
+		break;
+	case 1:
+		meta->addStatement(new GenOp(format + "\n", varList[0]));
+		break;
+	case 2:
+		meta->addStatement(new GenOp(format + "\n", varList[0], varList[1]));
+		break;
+	case 3:
+		meta->addStatement(new GenOp(format + "\n", varList[0], varList[1], varList[2]));
+		break;
+	case 4:
+		meta->addStatement(new GenOp(format + "\n", varList[0], varList[1], varList[2], varList[3]));
+		break;
+	case 5:
+		meta->addStatement(new GenOp(format + "\n", varList[0], varList[1], varList[2], varList[3], varList[4]));
+		break;
+	}
+}
+
+bool CustomFeatureHLSL::hasFeature(String name)
+{
+	for (U32 i = 0; i < mFeatureData.materialFeatures.getCount(); i++)
+	{
+		String featureName = mFeatureData.materialFeatures.getAt(i).getName();
+		if (name == featureName)
+			return true;
+	}
+
+	return false;
+}

+ 123 - 0
Engine/source/shaderGen/HLSL/customFeatureHLSL.h

@@ -0,0 +1,123 @@
+#ifndef _SHADERGEN_HLSL_SHADERFEATUREHLSL_H_
+#include "shaderGen/HLSL/shaderFeatureHLSL.h"
+#endif
+#ifndef _LANG_ELEMENT_H_
+#include "shaderGen/langElement.h"
+#endif
+#ifndef _GFXDEVICE_H_
+#include "gfx/gfxDevice.h"
+#endif
+#ifndef _FEATUREMGR_H_
+#include "shaderGen/featureMgr.h"
+#endif
+#ifndef _MATERIALFEATURETYPES_H_
+#include "materials/materialFeatureTypes.h"
+#endif
+#ifndef _MATERIALFEATUREDATA_H_
+#include "materials/materialFeatureData.h"
+#endif
+
+#ifndef CUSTOMSHADERFEATURE_H
+#include "shaderGen/customShaderFeature.h"
+#endif
+
+class CustomShaderFeatureData;
+
+class CustomFeatureHLSL : public ShaderFeatureHLSL
+{
+	friend class CustomShaderFeatureData;
+
+	struct VarHolder
+	{
+		String varName;
+		String defaultValue;
+		String type;
+		bool uniform;
+		bool sampler;
+		bool texture;
+		U32 constNum;
+		ConstantSortPosition constSortPos;
+		U32 arraySize;
+
+		VarHolder() :
+			varName(""),
+			type(""),
+			defaultValue(""),
+			uniform(false), 
+			sampler(false), 
+			texture(false),
+			constNum(0), 
+			arraySize(0),
+			constSortPos(cspUninit)
+		{
+		}
+
+		VarHolder(String _varName,String _type, String _defaultValue) :
+			uniform(false), sampler(false), texture(false), constNum(0), arraySize(0), constSortPos(cspUninit)
+		{
+			varName = _varName;
+			type = _type;
+			defaultValue = _defaultValue;
+		}
+	};
+
+	Vector<VarHolder> mVars;
+
+	enum outputState
+	{
+		NoOutput,
+		VertexOutput,
+		PixelOutput
+	};
+
+	outputState mOutputState;
+
+public:
+	CustomShaderFeatureData* mOwner;
+
+	Vector<ShaderComponent*> mComponentList;
+	MaterialFeatureData mFeatureData;
+
+protected:
+	MultiLine *meta;
+
+public:
+
+	//****************************************************************************
+	// Accu Texture
+	//****************************************************************************
+	virtual void processVert(Vector<ShaderComponent*> &componentList,
+		const MaterialFeatureData &fd);
+
+	virtual void processPix(Vector<ShaderComponent*> &componentList,
+		const MaterialFeatureData &fd);
+
+	virtual Material::BlendOp getBlendOp() { return Material::LerpAlpha; }
+
+	virtual Resources getResources(const MaterialFeatureData &fd)
+	{
+		Resources res;
+		res.numTex = 1;
+		res.numTexReg = 1;
+		return res;
+	}
+
+	virtual void setTexData(Material::StageData &stageDat,
+		const MaterialFeatureData &fd,
+		RenderPassData &passData,
+		U32 &texIndex);
+
+	virtual String getName()
+	{
+		return mOwner->getName();
+	}
+
+	bool hasFeature(String name);
+
+	void addUniform(String name, String type, String defaultValue, U32 arraySize = 0);
+	void addVariable(String name, String type, String defaultValue);
+	void addSampler(String name, String type, U32 arraySize = 0);
+	void addTexture(String name, String type, String samplerState, U32 arraySize);
+	void addConnector(String name, String elementName, String type);
+	void writeLine(String format, S32 argc, ConsoleValueRef *argv);
+};

+ 190 - 0
Engine/source/shaderGen/customShaderFeature.cpp

@@ -0,0 +1,190 @@
+//-----------------------------------------------------------------------------
+// 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 "shadergen/CustomShaderFeature.h"
+#include "shaderGen/HLSL/customFeatureHLSL.h"
+
+#include "math/mathIO.h"
+#include "scene/sceneRenderState.h"
+#include "core/stream/bitStream.h"
+#include "materials/sceneData.h"
+#include "gfx/gfxDebugEvent.h"
+#include "gfx/gfxTransformSaver.h"
+#include "renderInstance/renderPassManager.h"
+
+
+IMPLEMENT_CONOBJECT(CustomShaderFeatureData);
+
+ConsoleDocClass(CustomShaderFeatureData,
+	"@brief An example scene object which renders using a callback.\n\n"
+	"This class implements a basic SceneObject that can exist in the world at a "
+	"3D position and render itself. Note that CustomShaderFeatureData handles its own "
+	"rendering by submitting itself as an ObjectRenderInst (see "
+	"renderInstance\renderPassmanager.h) along with a delegate for its render() "
+	"function. However, the preffered rendering method in the engine is to submit "
+	"a MeshRenderInst along with a Material, vertex buffer, primitive buffer, and "
+	"transform and allow the RenderMeshMgr handle the actual rendering. You can "
+	"see this implemented in RenderMeshExample.\n\n"
+	"See the C++ code for implementation details.\n\n"
+	"@ingroup Examples\n");
+
+//-----------------------------------------------------------------------------
+// Object setup and teardown
+//-----------------------------------------------------------------------------
+CustomShaderFeatureData::CustomShaderFeatureData()
+{
+}
+
+CustomShaderFeatureData::~CustomShaderFeatureData()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Object Editing
+//-----------------------------------------------------------------------------
+void CustomShaderFeatureData::initPersistFields()
+{
+	// SceneObject already handles exposing the transform
+	Parent::initPersistFields();
+}
+
+bool CustomShaderFeatureData::onAdd()
+{
+	if (!Parent::onAdd())
+		return false;
+
+	mFeatureHLSL = new CustomFeatureHLSL();
+	mFeatureHLSL->mOwner = this;
+
+	return true;
+}
+
+void CustomShaderFeatureData::onRemove()
+{
+	Parent::onRemove();
+}
+
+//Shadergen setup functions
+void CustomShaderFeatureData::addVariable(String name, String type, String defaultValue)
+{
+	mFeatureHLSL->addVariable(name, type, defaultValue);
+}
+
+void CustomShaderFeatureData::addUniform(String name, String type, String defaultValue, U32 arraySize)
+{
+	mFeatureHLSL->addUniform(name, type, defaultValue, arraySize);
+}
+
+void CustomShaderFeatureData::addSampler(String name, String type, U32 arraySize)
+{
+	mFeatureHLSL->addSampler(name, type, arraySize);
+}
+
+void CustomShaderFeatureData::addTexture(String name, String type, String samplerState, U32 arraySize)
+{
+	mFeatureHLSL->addTexture(name, type, samplerState, arraySize);
+}
+
+void CustomShaderFeatureData::addConnector(String name, String elementName, String type)
+{
+	mFeatureHLSL->addConnector(name, elementName, type);
+}
+
+bool CustomShaderFeatureData::hasFeature(String name)
+{
+	return mFeatureHLSL->hasFeature(name);
+}
+
+void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValueRef *argv)
+{
+	/*mOnObject = onObject;
+	mArgc = argc;
+
+	mArgv = new ConsoleValueRef[argc];
+	for (int i = 0; i<argc; i++)
+	{
+		mArgv[i].value = new ConsoleValue();
+		mArgv[i].value->type = ConsoleValue::TypeInternalString;
+		mArgv[i].value->init();
+		if (argv)
+		{
+			mArgv[i].value->setStringValue((const char*)argv[i]);
+		}
+	}*/
+
+	mFeatureHLSL->writeLine(format, argc, argv);
+}
+
+/*//Actual shader processing
+void CustomShaderFeatureData::processVert(Vector<ShaderComponent*> &componentList,
+	const MaterialFeatureData &fd)
+{
+	mFeatureHLSL.processVert(componentList, fd);
+}
+
+void CustomShaderFeatureData::processPix(Vector<ShaderComponent*> &componentList,
+	const MaterialFeatureData &fd)
+{
+	mFeatureHLSL.processPix(componentList, fd);
+
+}
+
+void CustomShaderFeatureData::setTexData(Material::StageData &stageDat,
+	const MaterialFeatureData &fd,
+	RenderPassData &passData,
+	U32 &texIndex)
+{
+	mFeatureHLSL.setTexData(stageDat, fd, passData, texIndex);
+}*/
+
+DefineEngineMethod(CustomShaderFeatureData, addVariable, void, (String name, String type, String defaultValue), ("", "", ""),	"")
+{
+	object->addVariable(name, type, defaultValue);
+}
+
+DefineEngineMethod(CustomShaderFeatureData, addUniform, void, (String name, String type, String defaultValue, U32 arraySize), ("", "", "", 0), "")
+{
+	object->addUniform(name, type, defaultValue, arraySize);
+}
+
+DefineEngineMethod(CustomShaderFeatureData, addSampler, void, (String name, U32 arraySize), ("", 0), "")
+{
+	object->addSampler(name, "", arraySize);
+}
+
+DefineEngineMethod(CustomShaderFeatureData, addTexture, void, (String name, String type, String samplerState, U32 arraySize), ("", "", 0), "")
+{
+	object->addTexture(name, type, samplerState, arraySize);
+}
+
+ConsoleMethod(CustomShaderFeatureData, writeLine, void, 3, 0, "( string format, string args... ) Dynamically call a method on an object.\n"
+	"@param method Name of method to call.\n"
+	"@param args Zero or more arguments for the method.\n"
+	"@return The result of the method call.")
+{
+	object->writeLine(argv[2], argc - 3, argv + 3);
+}
+
+DefineEngineMethod(CustomShaderFeatureData, hasFeature, bool, (String name), (""), "")
+{
+	return object->hasFeature(name);
+}

+ 84 - 0
Engine/source/shaderGen/customShaderFeature.h

@@ -0,0 +1,84 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+#pragma once
+#ifndef CUSTOMSHADERFEATURE_H
+#define CUSTOMSHADERFEATURE_H
+
+#ifndef _SIMOBJECT_H_
+#include "console/simObject.h"
+#endif
+
+class CustomFeatureHLSL;
+
+class CustomShaderFeatureData : public SimObject
+{
+	typedef SimObject Parent;
+
+public:
+	CustomFeatureHLSL* mFeatureHLSL;
+
+	Vector<StringTableEntry> mAddedShaderConstants;
+
+public:
+	CustomShaderFeatureData();
+	virtual ~CustomShaderFeatureData();
+
+	// Declare this object as a ConsoleObject so that we can
+	// instantiate it into the world and network it
+	DECLARE_CONOBJECT(CustomShaderFeatureData);
+
+	//--------------------------------------------------------------------------
+	// Object Editing
+	// Since there is always a server and a client object in Torque and we
+	// actually edit the server object we need to implement some basic
+	// networking functions
+	//--------------------------------------------------------------------------
+	// Set up any fields that we want to be editable (like position)
+	static void initPersistFields();
+
+	// Handle when we are added to the scene and removed from the scene
+	bool onAdd();
+	void onRemove();
+
+	//shadergen setup
+	void addVariable(String name, String type, String defaultValue);
+	void addUniform(String name, String type, String defaultValue, U32 arraySize);
+	void addSampler(String name, String type, U32 arraySize);
+	void addTexture(String name, String type, String samplerState, U32 arraySize);
+	void addConnector(String name, String elementName, String type);
+
+	bool hasFeature(String name);
+
+	void writeLine(String format, S32 argc, ConsoleValueRef *argv);
+
+	//shader generation
+	/*void CustomShaderFeatureData::processVert(Vector<ShaderComponent*> &componentList,
+		const MaterialFeatureData &fd);
+	void CustomShaderFeatureData::processPix(Vector<ShaderComponent*> &componentList,
+		const MaterialFeatureData &fd);
+	void CustomShaderFeatureData::setTexData(Material::StageData &stageDat,
+		const MaterialFeatureData &fd,
+		RenderPassData &passData,
+		U32 &texIndex);*/
+};
+
+#endif

+ 1 - 0
Engine/source/shaderGen/langElement.cpp

@@ -112,6 +112,7 @@ Var::Var( const char *inName, const char *inType )
    sampler = false;
    texCoordNum = 0;
    constSortPos = cspUninit;
+   constNum = 0;
    arraySize = 1;
    texture = false;
    rank = 0;

+ 57 - 3
Engine/source/shaderGen/shaderGen.cpp

@@ -31,6 +31,7 @@
 #include "core/memVolume.h"
 #include "core/module.h"
 
+#include "shaderGen/HLSL/customFeatureHLSL.h"
 
 MODULE_BEGIN( ShaderGen )
 
@@ -135,13 +136,16 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData,
                                 F32 *pixVersion,
                                 const GFXVertexFormat *vertexFormat,
                                 const char* cacheName,
-                                Vector<GFXShaderMacro> &macros )
+                                Vector<GFXShaderMacro> &macros,
+								Vector<CustomShaderFeatureData*> &customFeatureData)
 {
    PROFILE_SCOPE( ShaderGen_GenerateShader );
 
    mFeatureData = featureData;
    mVertexFormat = vertexFormat;
 
+   mCustomFeaturesData = customFeatureData;
+
    _uninit();
    _init();
 
@@ -281,6 +285,31 @@ void ShaderGen::_processVertFeatures( Vector<GFXShaderMacro> &macros, bool macro
       }
    }
 
+   //Handle if we have any custom features
+   if (!mCustomFeaturesData.empty())
+   {
+	   for (U32 i = 0; i < mCustomFeaturesData.size(); ++i)
+	   {
+		   mCustomFeaturesData[i]->mFeatureHLSL->processVert(mComponents, mFeatureData);
+
+		   String line = String::ToString("   // %s\r\n", mCustomFeaturesData[i]->mFeatureHLSL->getName().c_str());
+		   mOutput->addStatement(new GenOp(line));
+
+		   if (mCustomFeaturesData[i]->mFeatureHLSL->getOutput())
+			   mOutput->addStatement(mCustomFeaturesData[i]->mFeatureHLSL->getOutput());
+		   //ShaderFeatureHLSL feature = mCustomFeaturesData[i]->mHLSLFeature;
+		   //feature->setProcessIndex(index);
+
+		   /*feature->processPixMacros(macros, mFeatureData);
+
+		   feature->setInstancingFormat(&mInstancingFormat);
+		   feature->processPix(mComponents, mFeatureData);*/
+
+		   mCustomFeaturesData[i]->mFeatureHLSL->reset();
+		   mOutput->addStatement(new GenOp("   \r\n"));
+	   }
+   }
+
    ShaderConnector *connect = dynamic_cast<ShaderConnector *>( mComponents[C_CONNECTOR] );
    connect->sortVars();
 }
@@ -320,6 +349,31 @@ void ShaderGen::_processPixFeatures( Vector<GFXShaderMacro> &macros, bool macros
          mOutput->addStatement( new GenOp( "   \r\n" ) );
       }
    }
+
+   //Handle if we have any custom features
+   if (!mCustomFeaturesData.empty())
+   {
+	   for (U32 i = 0; i < mCustomFeaturesData.size(); ++i)
+	   {
+		   mCustomFeaturesData[i]->mFeatureHLSL->processPix(mComponents, mFeatureData);
+
+		   String line = String::ToString("   // %s\r\n", mCustomFeaturesData[i]->mFeatureHLSL->getName().c_str());
+		   mOutput->addStatement(new GenOp(line));
+
+		   if (mCustomFeaturesData[i]->mFeatureHLSL->getOutput())
+			   mOutput->addStatement(mCustomFeaturesData[i]->mFeatureHLSL->getOutput());
+		   //ShaderFeatureHLSL feature = mCustomFeaturesData[i]->mHLSLFeature;
+		   //feature->setProcessIndex(index);
+
+		   /*feature->processPixMacros(macros, mFeatureData);
+
+		   feature->setInstancingFormat(&mInstancingFormat);
+		   feature->processPix(mComponents, mFeatureData);*/
+
+		   mCustomFeaturesData[i]->mFeatureHLSL->reset();
+		   mOutput->addStatement(new GenOp("   \r\n"));
+	   }
+   }
    
    ShaderConnector *connect = dynamic_cast<ShaderConnector *>( mComponents[C_CONNECTOR] );
    connect->sortVars();
@@ -443,7 +497,7 @@ void ShaderGen::_printPixShader( Stream &stream )
    mPrinter->printPixelShaderCloser(stream);
 }
 
-GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers )
+GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, Vector<CustomShaderFeatureData*> &customFeatureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers )
 {
    PROFILE_SCOPE( ShaderGen_GetShader );
 
@@ -483,7 +537,7 @@ GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const G
    shaderMacros.push_back( GFXShaderMacro( "TORQUE_SHADERGEN" ) );
    if ( macros )
       shaderMacros.merge( *macros );
-   generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros );
+   generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros, customFeatureData );
 
    GFXShader *shader = GFX->createShader();
    if (!shader->init(vertFile, pixFile, pixVersion, shaderMacros, samplers, &mInstancingFormat))

+ 9 - 2
Engine/source/shaderGen/shaderGen.h

@@ -47,6 +47,10 @@
 #include "materials/materialFeatureData.h"
 #endif
 
+#ifndef CUSTOMSHADERFEATURE_H
+#include "shadergen/customShaderFeature.h"
+#endif
+
 /// Base class used by shaderGen to be API agnostic.  Subclasses implement the various methods
 /// in an API specific way.
 class ShaderGenPrinter
@@ -151,10 +155,11 @@ public:
                         F32 *pixVersion,
                         const GFXVertexFormat *vertexFormat,
                         const char* cacheName,
-                        Vector<GFXShaderMacro> &macros );
+                        Vector<GFXShaderMacro> &macros,
+						Vector<CustomShaderFeatureData*> &customFeatureData);
 
    // Returns a shader that implements the features listed by dat.
-   GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers );
+   GFXShader* getShader( const MaterialFeatureData &dat, Vector<CustomShaderFeatureData*> &customFeatureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers );
 
    // This will delete all of the procedural shaders that we have.  Used to regenerate shaders when
    // the ShaderFeatures have changed (due to lighting system change, or new plugin)
@@ -176,6 +181,8 @@ protected:
    
    Vector< ShaderComponent *> mComponents;
 
+   Vector< CustomShaderFeatureData* > mCustomFeaturesData;
+
    AutoPtr<ShaderGenPrinter> mPrinter;
    AutoPtr<ShaderGenComponentFactory> mComponentFactory;
 

+ 3 - 1
Engine/source/terrain/terrCellMaterial.cpp

@@ -479,6 +479,8 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
       featureData.features = features;
       featureData.materialFeatures = features;
 
+	  Vector<CustomShaderFeatureData*> customFeatures;
+
       // Check to see how many vertex shader output 
       // registers we're gonna need.
       U32 numTex = 0;
@@ -521,7 +523,7 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
          const bool logErrors = true;// matCount == 1;
          GFXShader::setLogging( logErrors, true );
 
-         pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames );
+         pass->shader = SHADERGEN->getShader( featureData, customFeatures, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames );
       }
 
       // If we got a shader then we can continue.

+ 2 - 0
Engine/source/ts/tsMesh.cpp

@@ -207,6 +207,8 @@ void TSMesh::innerRender( TSMaterialList *materials, const TSRenderState &rdata,
 
    coreRI->materialHint = rdata.getMaterialHint();
 
+   coreRI->mCustomShaderData = rdata.getCustomShaderBinding();
+
    coreRI->visibility = meshVisibility;  
    coreRI->cubemap = rdata.getCubemap();
 

+ 2 - 1
Engine/source/ts/tsRenderState.cpp

@@ -52,6 +52,7 @@ TSRenderState::TSRenderState( const TSRenderState &state )
       mLightQuery( state.mLightQuery ),
       mAccuTex( state.mAccuTex ),
       mNodeTransforms( state.mNodeTransforms ),
-      mNodeTransformCount( state.mNodeTransformCount )
+      mNodeTransformCount( state.mNodeTransformCount ),
+	  mCustomShaderData( state.mCustomShaderData )
 {
 }

+ 16 - 3
Engine/source/ts/tsRenderState.h

@@ -31,6 +31,10 @@
 #include "gfx/gfxDevice.h"
 #endif
 
+#ifndef _BASEMATINSTANCE_H_
+#include "materials/baseMatInstance.h"
+#endif
+
 class SceneRenderState;
 class GFXCubemap;
 class Frustum;
@@ -115,10 +119,10 @@ protected:
    /// Count of matrices in the mNodeTransforms list
    U32 mNodeTransformCount;
 
-public:
-
-   
+   //Custom Shader data
+   Vector<CustomShaderBindingData> mCustomShaderData;
 
+public:
    TSRenderState();
    TSRenderState( const TSRenderState &state );
 
@@ -165,6 +169,15 @@ public:
    void setAccuTex( GFXTextureObject* query ) { mAccuTex = query; }
    GFXTextureObject* getAccuTex() const { return mAccuTex; }
 
+   void addCustomShaderBinding(CustomShaderBindingData data)
+   {
+	   mCustomShaderData.push_back(data);
+   }
+   Vector<CustomShaderBindingData> getCustomShaderBinding() const 
+   { 
+	   return mCustomShaderData; 
+   }
+
    ///@ see mNodeTransforms, mNodeTransformCount
    void setNodeTransforms(MatrixF *list, U32 count) { mNodeTransforms = list; mNodeTransformCount = count; }
    void getNodeTransforms(MatrixF **list, U32 *count) const { *list = mNodeTransforms; *count = mNodeTransformCount; }

TEMPAT SAMPAH
Templates/BaseGame/game/core/gui/scripts/fonts/Arial 12 (ansi).uft


TEMPAT SAMPAH
Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 16 (ansi).uft


TEMPAT SAMPAH
Templates/BaseGame/game/core/gui/scripts/fonts/Arial Bold 18 (ansi).uft


TEMPAT SAMPAH
Templates/BaseGame/game/core/gui/scripts/fonts/ArialItalic 14 (ansi).uft


+ 40 - 1
Templates/Full/game/art/shapes/cube/materials.cs

@@ -21,7 +21,13 @@
 //-----------------------------------------------------------------------------
 
 //--- cube.dae MATERIALS BEGIN ---
-singleton Material(cube_GridMaterial)
+singleton CustomShaderFeatureData(FlatColorFeature)
+{
+   
+
+};
+
+/*singleton Material(cube_GridMaterial)
 {
 	mapTo = "GridMaterial";
 
@@ -41,7 +47,40 @@ singleton Material(cube_GridMaterial)
    specularPower0 = "0.415939";
    pixelSpecular0 = "0";
    specular0 = "0.9 0.9 0.9 1";
+
+   mapTo = "GridMaterial";
+   
+   CustomShaderFeature[0] = FlatColorFeature;
+   CustomShaderFeatureUniforms[FlatColorFeature,0] = "TestFloat";
 };
 
+
 //--- cube.dae MATERIALS END ---
 
+//Voodoo!
+function FlatColorFeature::processVertHLSL(%this)
+{
+   
+}
+
+function FlatColorFeature::processPixelHLSL(%this)
+{
+   %this.addUniform("strudel", "float2");
+   %this.addSampler("strudelMap");
+   %this.addTexture("strudelTex", "Texture2D", "strudelMap");
+   
+   %this.addVariable("bobsyeruncle", "float", 15.915);
+   %this.addVariable("chimmychanga", "float");
+   
+   %this.writeLine("   @ = @ * 2;", "chimmychanga", "bobsyeruncle");
+   %this.writeLine("   @ *= @.x;", "bobsyeruncle", "strudel");
+   %this.writeLine("   @ *= @.y;", "chimmychanga", "strudel");
+   
+   %this.addVariable("sprangle", "float4");
+   %this.writeLine("   @ = @.Sample(@,@);", "sprangle", "strudelTex", "strudelMap", "strudel");
+}
+
+function FlatColorFeature::setTextureResources(%this)
+{
+   
+}