2
0
Эх сурвалжийг харах

Initial implementation of Custom Shader Features

Areloch 6 жил өмнө
parent
commit
529558f671
31 өөрчлөгдсөн 1772 нэмэгдсэн , 17 устгасан
  1. 10 0
      Engine/source/materials/baseMatInstance.h
  2. 97 0
      Engine/source/materials/customShaderBindingData.h
  3. 6 0
      Engine/source/materials/matInstance.cpp
  4. 1 0
      Engine/source/materials/matInstance.h
  5. 34 0
      Engine/source/materials/materialDefinition.cpp
  6. 9 1
      Engine/source/materials/materialDefinition.h
  7. 1 1
      Engine/source/materials/processedCustomMaterial.cpp
  8. 1 0
      Engine/source/materials/processedFFMaterial.h
  9. 9 0
      Engine/source/materials/processedMaterial.h
  10. 56 3
      Engine/source/materials/processedShaderMaterial.cpp
  11. 13 1
      Engine/source/materials/processedShaderMaterial.h
  12. 3 1
      Engine/source/materials/sceneData.h
  13. 5 0
      Engine/source/renderInstance/renderBinManager.cpp
  14. 8 0
      Engine/source/renderInstance/renderDeferredMgr.cpp
  15. 6 0
      Engine/source/renderInstance/renderGlowMgr.cpp
  16. 6 0
      Engine/source/renderInstance/renderMeshMgr.cpp
  17. 4 0
      Engine/source/renderInstance/renderPassManager.h
  18. 6 0
      Engine/source/renderInstance/renderTranslucentMgr.cpp
  19. 350 0
      Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp
  20. 132 0
      Engine/source/shaderGen/GLSL/customFeatureGLSL.h
  21. 497 0
      Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp
  22. 132 0
      Engine/source/shaderGen/HLSL/customFeatureHLSL.h
  23. 201 0
      Engine/source/shaderGen/customShaderFeature.cpp
  24. 76 0
      Engine/source/shaderGen/customShaderFeature.h
  25. 1 0
      Engine/source/shaderGen/langElement.cpp
  26. 76 3
      Engine/source/shaderGen/shaderGen.cpp
  27. 9 2
      Engine/source/shaderGen/shaderGen.h
  28. 3 1
      Engine/source/terrain/terrCellMaterial.cpp
  29. 2 0
      Engine/source/ts/tsMesh.cpp
  30. 2 1
      Engine/source/ts/tsRenderState.cpp
  31. 16 3
      Engine/source/ts/tsRenderState.h

+ 10 - 0
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;
@@ -155,6 +162,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

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

@@ -0,0 +1,97 @@
+#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; }
+
+   void setTexture2D(StringTableEntry shaderConstName, GFXTexHandle f)
+   {
+      targetedUniformName = shaderConstName;
+      texture = f;
+      type = Texture2D;
+   }
+   GFXTexHandle getTexture2D() { return texture; }
+
+	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);

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

@@ -483,6 +483,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();
 }
 
@@ -500,6 +505,35 @@ 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);
+
+	if (index != NULL)
+	{
+		char featureName[256] = { 0 };
+		U32 id = 0;
+		dSscanf(index, "%s_%i", featureName, id);
+
+		String uniformName = data;
+	}
+
+	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
@@ -343,6 +346,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
@@ -380,6 +385,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

@@ -245,7 +245,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) {;}
 
    virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass);
 

+ 9 - 0
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;
@@ -81,6 +85,8 @@ public:
 
    MaterialFeatureData mFeatureData;
 
+   Vector<CustomShaderFeatureData*> mCustomShaderFeatureData;
+
    bool mGlow;
 
    Material::BlendOp mBlendOp;
@@ -144,6 +150,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;

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

@@ -50,7 +50,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);
@@ -116,6 +116,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);
+       }
+   }
 }
 
 ///
@@ -654,10 +667,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 )
@@ -1260,6 +1273,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 );

+ 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;
@@ -96,7 +99,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
@@ -132,6 +143,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() 
    { 

+ 5 - 0
Engine/source/renderInstance/renderBinManager.cpp

@@ -172,6 +172,11 @@ void RenderBinManager::setupSGData( MeshRenderInst *ri, SceneData &data )
    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]);
+   }
 }
 
 DefineEngineMethod( RenderBinManager, getBinType, const char*, (),,

+ 8 - 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");
@@ -431,6 +433,12 @@ void RenderDeferredMgr::render( SceneRenderState *state )
                mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
             }
 
+			   //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() )
             {

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

@@ -251,6 +251,12 @@ void RenderGlowMgr::render( SceneRenderState *state )
                glowMat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
             }
 
+			//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);
 

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

@@ -182,6 +182,12 @@ void RenderMeshMgr::render(SceneRenderState * state)
                mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
             }
 
+			//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 );
 

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

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

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

@@ -249,6 +249,12 @@ void RenderTranslucentMgr::render( SceneRenderState *state )
                   mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);
                }
 
+			   //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() )
                {

+ 350 - 0
Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp

@@ -0,0 +1,350 @@
+//-----------------------------------------------------------------------------
+// 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 "customFeatureGLSL.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 CustomFeatureGLSL::processVert(Vector<ShaderComponent*>& componentList,
+   const MaterialFeatureData& fd)
+{
+   meta = new MultiLine;
+
+   mFeatureData = fd;
+   mComponentList = componentList;
+
+   mOutputState = VertexOutput;
+
+   if (mOwner->isMethod("processVertGLSL"))
+      Con::executef(mOwner, "processVertGLSL");
+
+   output = meta;
+}
+
+void CustomFeatureGLSL::processPix(Vector<ShaderComponent*>& componentList,
+   const MaterialFeatureData& fd)
+{
+   meta = new MultiLine;
+
+   mFeatureData = fd;
+   mComponentList = componentList;
+
+   mOutputState = PixelOutput;
+
+   if (mOwner->isMethod("processPixelGLSL"))
+      Con::executef(mOwner, "processPixelGLSL");
+
+   output = meta;
+}
+
+void CustomFeatureGLSL::setTexData(Material::StageData& stageDat,
+   const MaterialFeatureData& fd,
+   RenderPassData& passData,
+   U32& texIndex)
+{
+
+   if (mOwner->isMethod("setTextureData"))
+      Con::executef(mOwner, "setTextureData");
+}
+
+void CustomFeatureGLSL::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 CustomFeatureGLSL::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 CustomFeatureGLSL::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 CustomFeatureGLSL::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 CustomFeatureGLSL::addConnector(String name, String type, String elementName)
+{
+   // 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;
+   }
+
+   VarHolder newVarHolder(name, type, "");
+
+   newVarHolder.elementId = element;
+
+   if (mOutputState == VertexOutput)
+      newVarHolder.structName = "OUT";
+   else if (mOutputState == PixelOutput)
+      newVarHolder.structName = "IN";
+
+   mVars.push_back(newVarHolder);
+}
+
+void CustomFeatureGLSL::addVertTexCoord(String name)
+{
+   VarHolder newVarHolder(name, "", "");
+   newVarHolder.texCoord = true;
+
+   mVars.push_back(newVarHolder);
+}
+
+void CustomFeatureGLSL::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)
+            {
+               if (!mVars[v].texCoord)
+               {
+                  if (mVars[v].elementId != -1)
+                  {
+                     ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(mComponentList[C_CONNECTOR]);
+                     Var* newDeclVar = connectComp->getElement((RegisterType)mVars[v].elementId);
+                     newDeclVar->setName(mVars[v].varName);
+                     newDeclVar->setStructName(mVars[v].structName);
+                     newDeclVar->setType(mVars[v].type);
+
+                     newVar = newDeclVar;
+                  }
+                  else
+                  {
+                     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;
+                     }
+                  }
+               }
+               else
+               {
+                  newVar = getVertTexCoord(mVars[v].varName);
+               }
+
+               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 CustomFeatureGLSL::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;
+}

+ 132 - 0
Engine/source/shaderGen/GLSL/customFeatureGLSL.h

@@ -0,0 +1,132 @@
+#ifndef _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_
+#include "shaderGen/GLSL/shaderFeatureGLSL.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 CustomFeatureGLSL : public ShaderFeatureGLSL
+{
+   friend class CustomShaderFeatureData;
+
+   struct VarHolder
+   {
+      String varName;
+      String type;
+      String defaultValue;
+      S32 elementId;
+      bool uniform;
+      bool sampler;
+      bool texture;
+      bool texCoord;
+      U32 constNum;
+      U32 arraySize;
+      String structName;
+      ConstantSortPosition constSortPos;
+
+      VarHolder() :
+         varName(""),
+         type(""),
+         defaultValue(""),
+         elementId(-1),
+         uniform(false),
+         sampler(false),
+         texture(false),
+         texCoord(false),
+         constNum(0),
+         arraySize(0),
+         structName(""),
+         constSortPos(cspUninit)
+      {
+      }
+
+      VarHolder(String _varName, String _type, String _defaultValue) :
+         elementId(-1), uniform(false), sampler(false), texture(false), texCoord(false), constNum(0), arraySize(0), structName(""), constSortPos(cspUninit)
+      {
+         varName = _varName;
+         type = _type;
+         defaultValue = _defaultValue;
+      }
+   };
+
+   Vector<VarHolder> mVars;
+
+   Vector<VarHolder> mConnectorVars;
+
+   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 type, String elementName);
+   void addVertTexCoord(String name);
+   void writeLine(String format, S32 argc, ConsoleValueRef* argv);
+};

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

@@ -0,0 +1,497 @@
+//-----------------------------------------------------------------------------
+// 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 type, String elementName)
+{
+   // 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;
+   }
+
+   VarHolder newVarHolder(name, type, "");
+
+   newVarHolder.elementId = element;
+
+   if (mOutputState == VertexOutput)
+      newVarHolder.structName = "OUT";
+   else if (mOutputState == PixelOutput)
+      newVarHolder.structName = "IN";
+
+   mVars.push_back(newVarHolder);
+}
+
+void CustomFeatureHLSL::addVertTexCoord(String name)
+{
+   VarHolder newVarHolder(name, "", "");
+   newVarHolder.texCoord = true;
+
+   mVars.push_back(newVarHolder);
+}
+
+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)
+            {
+               if (!mVars[v].texCoord)
+               {
+                  if (mVars[v].elementId != -1)
+                  {
+                     ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(mComponentList[C_CONNECTOR]);
+                     Var* newDeclVar = connectComp->getElement((RegisterType)mVars[v].elementId);
+                     newDeclVar->setName(mVars[v].varName);
+                     newDeclVar->setStructName(mVars[v].structName);
+                     newDeclVar->setType(mVars[v].type);
+
+                     newVar = newDeclVar;
+                  }
+                  else
+                  {
+                     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;
+                     }
+                  }
+               }
+               else
+               {
+                  newVar = getVertTexCoord(mVars[v].varName);
+               }
+
+               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;
+}

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

@@ -0,0 +1,132 @@
+#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 type;
+      String defaultValue;
+      S32 elementId;
+      bool uniform;
+      bool sampler;
+      bool texture;
+      bool texCoord;
+      U32 constNum;
+      U32 arraySize;
+      String structName;
+      ConstantSortPosition constSortPos;
+
+      VarHolder() :
+         varName(""),
+         type(""),
+         defaultValue(""),
+         elementId(-1),
+         uniform(false),
+         sampler(false),
+         texture(false),
+         texCoord(false),
+         constNum(0),
+         arraySize(0),
+         structName(""),
+         constSortPos(cspUninit)
+      {
+      }
+
+      VarHolder(String _varName, String _type, String _defaultValue) :
+         elementId(-1), uniform(false), sampler(false), texture(false), texCoord(false), constNum(0), arraySize(0), structName(""), constSortPos(cspUninit)
+      {
+         varName = _varName;
+         type = _type;
+         defaultValue = _defaultValue;
+      }
+   };
+
+   Vector<VarHolder> mVars;
+
+   Vector<VarHolder> mConnectorVars;
+
+   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 type, String elementName);
+   void addVertTexCoord(String name);
+   void writeLine(String format, S32 argc, ConsoleValueRef* argv);
+};

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

@@ -0,0 +1,201 @@
+//-----------------------------------------------------------------------------
+// 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 "shaderGen/GLSL/customFeatureGLSL.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;
+
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+   {
+      mFeatureHLSL = new CustomFeatureHLSL();
+      mFeatureHLSL->mOwner = this;
+   }
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+   {
+      mFeatureGLSL = new CustomFeatureGLSL();
+      mFeatureGLSL->mOwner = this;
+   }
+
+   return true;
+}
+
+void CustomShaderFeatureData::onRemove()
+{
+   Parent::onRemove();
+}
+
+//Shadergen setup functions
+void CustomShaderFeatureData::addVariable(String name, String type, String defaultValue)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->addVariable(name, type, defaultValue);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->addVariable(name, type, defaultValue);
+}
+
+void CustomShaderFeatureData::addUniform(String name, String type, String defaultValue, U32 arraySize)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->addUniform(name, type, defaultValue, arraySize);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->addUniform(name, type, defaultValue, arraySize);
+}
+
+void CustomShaderFeatureData::addSampler(String name, String type, U32 arraySize)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->addSampler(name, type, arraySize);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->addSampler(name, type, arraySize);
+}
+
+void CustomShaderFeatureData::addTexture(String name, String type, String samplerState, U32 arraySize)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->addTexture(name, type, samplerState, arraySize);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->addTexture(name, type, samplerState, arraySize);
+}
+
+void CustomShaderFeatureData::addConnector(String name, String type, String elementName)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->addConnector(name, type, elementName);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->addConnector(name, type, elementName);
+}
+
+void CustomShaderFeatureData::addVertTexCoord(String name)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->addVertTexCoord(name);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->addVertTexCoord(name);
+}
+
+bool CustomShaderFeatureData::hasFeature(String name)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      return mFeatureHLSL->hasFeature(name);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      return mFeatureGLSL->hasFeature(name);
+}
+
+void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValueRef* argv)
+{
+   if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+      mFeatureHLSL->writeLine(format, argc, argv);
+   else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+      mFeatureGLSL->writeLine(format, argc, argv);
+}
+
+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);
+}
+
+DefineEngineMethod(CustomShaderFeatureData, addConnector, void, (String name, String type, String elementName), ("", "", ""), "")
+{
+   object->addConnector(name, type, elementName);
+}
+
+DefineEngineMethod(CustomShaderFeatureData, addVertTexCoord, void, (String name), (""), "")
+{
+   object->addVertTexCoord(name);
+}
+
+DefineEngineStringlyVariadicMethod(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);
+}

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

@@ -0,0 +1,76 @@
+//-----------------------------------------------------------------------------
+// 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 CustomFeatureGLSL;
+
+class CustomShaderFeatureData : public SimObject
+{
+	typedef SimObject Parent;
+
+public:
+	CustomFeatureHLSL* mFeatureHLSL;
+   CustomFeatureGLSL* mFeatureGLSL;
+
+	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 type, String elementName);
+   void addVertTexCoord(String name);
+	bool hasFeature(String name);
+
+	void writeLine(String format, S32 argc, ConsoleValueRef *argv);
+};
+
+#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;

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

@@ -31,6 +31,8 @@
 #include "core/memVolume.h"
 #include "core/module.h"
 
+#include "shaderGen/HLSL/customFeatureHLSL.h"
+#include "shaderGen/GLSL/customFeatureGLSL.h"
 
 MODULE_BEGIN( ShaderGen )
 
@@ -135,13 +137,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 +286,40 @@ 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)
+	   {
+         if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+         {
+            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());
+
+            mCustomFeaturesData[i]->mFeatureHLSL->reset();
+            mOutput->addStatement(new GenOp("   \r\n"));
+         }
+         else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+         {
+            mCustomFeaturesData[i]->mFeatureGLSL->processVert(mComponents, mFeatureData);
+
+            String line = String::ToString("   // %s\r\n", mCustomFeaturesData[i]->mFeatureGLSL->getName().c_str());
+            mOutput->addStatement(new GenOp(line));
+
+            if (mCustomFeaturesData[i]->mFeatureGLSL->getOutput())
+               mOutput->addStatement(mCustomFeaturesData[i]->mFeatureGLSL->getOutput());
+
+            mCustomFeaturesData[i]->mFeatureGLSL->reset();
+            mOutput->addStatement(new GenOp("   \r\n"));
+         }
+	   }
+   }
+
    ShaderConnector *connect = dynamic_cast<ShaderConnector *>( mComponents[C_CONNECTOR] );
    connect->sortVars();
 }
@@ -320,6 +359,40 @@ 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)
+	   {
+         if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
+         {
+            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());
+
+            mCustomFeaturesData[i]->mFeatureHLSL->reset();
+            mOutput->addStatement(new GenOp("   \r\n"));
+         }
+         else if (GFX->getAdapterType() == GFXAdapterType::OpenGL)
+         {
+            mCustomFeaturesData[i]->mFeatureGLSL->processPix(mComponents, mFeatureData);
+
+            String line = String::ToString("   // %s\r\n", mCustomFeaturesData[i]->mFeatureGLSL->getName().c_str());
+            mOutput->addStatement(new GenOp(line));
+
+            if (mCustomFeaturesData[i]->mFeatureGLSL->getOutput())
+               mOutput->addStatement(mCustomFeaturesData[i]->mFeatureGLSL->getOutput());
+
+            mCustomFeaturesData[i]->mFeatureGLSL->reset();
+            mOutput->addStatement(new GenOp("   \r\n"));
+         }
+	   }
+   }
    
    ShaderConnector *connect = dynamic_cast<ShaderConnector *>( mComponents[C_CONNECTOR] );
    connect->sortVars();
@@ -443,7 +516,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 +556,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

@@ -460,6 +460,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;
@@ -502,7 +504,7 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
          const bool logErrors = 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; }