Przeglądaj źródła

Initial implementation of Custom Shader Features.

Areloch 8 lat temu
rodzic
commit
dc5e502dec

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

@@ -483,6 +483,9 @@ void Material::initPersistFields()
 
    endGroup( "Behavioral" );
 
+   addProtectedField("customShaderFeature", TypeRealString, NULL, &protectedSetCustomShaderFeature, &defaultProtectedGetFn,
+	   "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors);
+
    Parent::initPersistFields();
 }
 
@@ -500,6 +503,19 @@ 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::onAdd()
 {
    if (Parent::onAdd() == false)

+ 8 - 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,8 @@ public:
    virtual void inspectPostApply();
    virtual bool writeField( StringTableEntry fieldname, const char *value );
 
+   static bool protectedSetCustomShaderFeature(void *object, const char *index, const char *data);
+
    //
    // ConsoleObject interface
    //

+ 2 - 0
Engine/source/materials/processedMaterial.h

@@ -81,6 +81,8 @@ public:
 
    MaterialFeatureData mFeatureData;
 
+   Vector<CustomShaderFeatureData*> mCustomShaderFeatureData;
+
    bool mGlow;
 
    Material::BlendOp mBlendOp;

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

@@ -654,7 +654,7 @@ 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 );   

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

@@ -0,0 +1,213 @@
+//-----------------------------------------------------------------------------
+// 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;*/
+
+	if (mOwner->isMethod("processVertHLSL"))
+		Con::executef(mOwner, "processVertHLSL");
+}
+
+void CustomFeatureHLSL::processPix(Vector<ShaderComponent*> &componentList,
+	const MaterialFeatureData &fd)
+{
+	meta = new MultiLine;
+	
+	/*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::writeLine(String format, S32 argc, ConsoleValueRef *argv)
+{
+	//do the var/arg fetching here
+	meta->addStatement(new GenOp(format + "\n"/*, colorAccuDecl, accuMapTex, accuMap, inTex, accuScale*/));
+}

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

@@ -0,0 +1,68 @@
+#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;
+
+public:
+	CustomShaderFeatureData* mOwner;
+
+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();
+	}
+
+	void writeLine(String format, S32 argc, ConsoleValueRef *argv);
+};

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

@@ -0,0 +1,141 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "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::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, newVar, void, (String name, String type), ("", ""),	"")
+{
+	object->newVar(name, type);
+}*/
+
+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.")
+{
+	argv[1] = argv[2];
+	object->writeLine(argv[1], argc - 1, argv + 1);
+}

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

@@ -0,0 +1,74 @@
+//-----------------------------------------------------------------------------
+// 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;
+
+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 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

+ 32 - 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();
 
@@ -320,6 +324,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 +472,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 +512,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.

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

@@ -21,7 +21,7 @@
 //-----------------------------------------------------------------------------
 
 //--- cube.dae MATERIALS BEGIN ---
-singleton Material(cube_GridMaterial)
+/*singleton Material(cube_GridMaterial)
 {
 	mapTo = "GridMaterial";
 
@@ -38,7 +38,34 @@ singleton Material(cube_GridMaterial)
 	doubleSided = false;
 	translucent = false;
 	translucentBlendOp = "None";
+};*/
+
+singleton CustomShaderFeatureData(FlatColorFeature)
+{
+   
+};
+
+singleton Material(cube_GridMaterial)
+{
+   mapTo = "GridMaterial";
+   
+   CustomShaderFeature[0] = FlatColorFeature;
 };
 
 //--- cube.dae MATERIALS END ---
 
+//Voodoo!
+function FlatColorFeature::processVert(%this)
+{
+   
+}
+
+function FlatColorFeature::processPixelHLSL(%this)
+{
+   %this.writeLine("    float bobsyeruncle = 15.915;");
+}
+
+function FlatColorFeature::setTextureResources(%this)
+{
+   
+}