From 9a63761627174f4fec62c08b04232bccfa063f2b Mon Sep 17 00:00:00 2001 From: Areloch Date: Fri, 17 May 2019 01:20:19 -0500 Subject: [PATCH 1/3] Initial implementation of Custom Shader Features --- Engine/source/materials/baseMatInstance.h | 10 + .../materials/customShaderBindingData.h | 97 ++++ Engine/source/materials/matInstance.cpp | 6 + Engine/source/materials/matInstance.h | 1 + .../source/materials/materialDefinition.cpp | 34 ++ Engine/source/materials/materialDefinition.h | 10 +- .../materials/processedCustomMaterial.cpp | 2 +- Engine/source/materials/processedFFMaterial.h | 1 + Engine/source/materials/processedMaterial.h | 9 + .../materials/processedShaderMaterial.cpp | 59 ++- .../materials/processedShaderMaterial.h | 14 +- Engine/source/materials/sceneData.h | 4 +- .../renderInstance/renderBinManager.cpp | 5 + .../renderInstance/renderDeferredMgr.cpp | 8 + .../source/renderInstance/renderGlowMgr.cpp | 6 + .../source/renderInstance/renderMeshMgr.cpp | 6 + .../source/renderInstance/renderPassManager.h | 4 + .../renderInstance/renderTranslucentMgr.cpp | 6 + .../shaderGen/GLSL/customFeatureGLSL.cpp | 350 ++++++++++++ .../source/shaderGen/GLSL/customFeatureGLSL.h | 132 +++++ .../shaderGen/HLSL/customFeatureHLSL.cpp | 497 ++++++++++++++++++ .../source/shaderGen/HLSL/customFeatureHLSL.h | 132 +++++ .../source/shaderGen/customShaderFeature.cpp | 201 +++++++ Engine/source/shaderGen/customShaderFeature.h | 76 +++ Engine/source/shaderGen/langElement.cpp | 1 + Engine/source/shaderGen/shaderGen.cpp | 79 ++- Engine/source/shaderGen/shaderGen.h | 11 +- Engine/source/terrain/terrCellMaterial.cpp | 4 +- Engine/source/ts/tsMesh.cpp | 2 + Engine/source/ts/tsRenderState.cpp | 3 +- Engine/source/ts/tsRenderState.h | 19 +- 31 files changed, 1772 insertions(+), 17 deletions(-) create mode 100644 Engine/source/materials/customShaderBindingData.h create mode 100644 Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp create mode 100644 Engine/source/shaderGen/GLSL/customFeatureGLSL.h create mode 100644 Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp create mode 100644 Engine/source/shaderGen/HLSL/customFeatureHLSL.h create mode 100644 Engine/source/shaderGen/customShaderFeature.cpp create mode 100644 Engine/source/shaderGen/customShaderFeature.h diff --git a/Engine/source/materials/baseMatInstance.h b/Engine/source/materials/baseMatInstance.h index bca878dc27..3fa9ed0056 100644 --- a/Engine/source/materials/baseMatInstance.h +++ b/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 @@ class BaseMatInstance /// 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 &shaderData) = 0; + /// This initializes various material scene state settings and /// should be called after setupPass() within the pass loop. /// @see setupPass diff --git a/Engine/source/materials/customShaderBindingData.h b/Engine/source/materials/customShaderBindingData.h new file mode 100644 index 0000000000..29271d33f2 --- /dev/null +++ b/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 diff --git a/Engine/source/materials/matInstance.cpp b/Engine/source/materials/matInstance.cpp index e242a2059e..59674d7e62 100644 --- a/Engine/source/materials/matInstance.cpp +++ b/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 &shaderData) +{ + PROFILE_SCOPE(MatInstance_setCustomShaderData); + mProcessedMaterial->setCustomShaderData(shaderData, getCurPass()); +} + void MatInstance::setSceneInfo(SceneRenderState * state, const SceneData& sgData) { PROFILE_SCOPE(MatInstance_setSceneInfo); diff --git a/Engine/source/materials/matInstance.h b/Engine/source/materials/matInstance.h index 11178a42c0..a89445243d 100644 --- a/Engine/source/materials/matInstance.h +++ b/Engine/source/materials/matInstance.h @@ -66,6 +66,7 @@ class MatInstance : public BaseMatInstance 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 &shaderData); virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData); virtual void setTextureStages(SceneRenderState * state, const SceneData &sgData ); virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer); diff --git a/Engine/source/materials/materialDefinition.cpp b/Engine/source/materials/materialDefinition.cpp index 9fd3f857a1..1f08ae180a 100644 --- a/Engine/source/materials/materialDefinition.cpp +++ b/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) diff --git a/Engine/source/materials/materialDefinition.h b/Engine/source/materials/materialDefinition.h index be0e2ae711..3b993cb0a2 100644 --- a/Engine/source/materials/materialDefinition.h +++ b/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 @@ class Material : public BaseMaterialDefinition F32 mDirectSoundOcclusion; ///< Amount of volume occlusion on direct sounds. F32 mReverbSoundOcclusion; ///< Amount of volume occlusion on reverb sounds. + Vector mCustomShaderFeatures; + ///@} String mMapTo; // map Material to this texture name @@ -380,6 +385,9 @@ class Material : public BaseMaterialDefinition 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 // diff --git a/Engine/source/materials/processedCustomMaterial.cpp b/Engine/source/materials/processedCustomMaterial.cpp index 365676d445..38a5740993 100644 --- a/Engine/source/materials/processedCustomMaterial.cpp +++ b/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 ); diff --git a/Engine/source/materials/processedFFMaterial.h b/Engine/source/materials/processedFFMaterial.h index c65175381c..9af49a29ad 100644 --- a/Engine/source/materials/processedFFMaterial.h +++ b/Engine/source/materials/processedFFMaterial.h @@ -54,6 +54,7 @@ class ProcessedFFMaterial : public ProcessedMaterial 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 &shaderData, const U32 pass) {;} virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass); diff --git a/Engine/source/materials/processedMaterial.h b/Engine/source/materials/processedMaterial.h index 3c3f97a884..72233c1442 100644 --- a/Engine/source/materials/processedMaterial.h +++ b/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 @@ struct RenderPassData MaterialFeatureData mFeatureData; + Vector mCustomShaderFeatureData; + bool mGlow; Material::BlendOp mBlendOp; @@ -144,6 +150,9 @@ class ProcessedMaterial /// 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 &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; diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index e433a354cd..bb1a04960e 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -50,7 +50,7 @@ /// /// ShaderConstHandles /// -void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/ ) +void ShaderConstHandles::init( GFXShader *shader, Vector 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 &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 ); diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index ee0781b959..8a45ddfc7c 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/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 @@ class ShaderConstHandles GFXShaderConstHandle* mNodeTransforms; - void init( GFXShader* shader, CustomMaterial* mat = NULL ); + struct customHandleData + { + StringTableEntry handleName; + GFXShaderConstHandle* handle; + }; + Vector mCustomHandles; + + void init( GFXShader* shader, Vector customFeatureData, CustomMaterial* mat = NULL); + }; class ShaderRenderPassData : public RenderPassData @@ -132,6 +143,7 @@ class ProcessedShaderMaterial : public ProcessedMaterial 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 &shaderData, const U32 pass); virtual void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass); virtual void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer); virtual bool stepInstance(); diff --git a/Engine/source/materials/sceneData.h b/Engine/source/materials/sceneData.h index fd8b01633a..a67c9a2734 100644 --- a/Engine/source/materials/sceneData.h +++ b/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 customShaderData; + /// Constructor. SceneData() { diff --git a/Engine/source/renderInstance/renderBinManager.cpp b/Engine/source/renderInstance/renderBinManager.cpp index 16f559d5aa..79c5336eae 100644 --- a/Engine/source/renderInstance/renderBinManager.cpp +++ b/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*, (),, diff --git a/Engine/source/renderInstance/renderDeferredMgr.cpp b/Engine/source/renderInstance/renderDeferredMgr.cpp index 434fd585ac..eb2f0da3d1 100644 --- a/Engine/source/renderInstance/renderDeferredMgr.cpp +++ b/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() ) { diff --git a/Engine/source/renderInstance/renderGlowMgr.cpp b/Engine/source/renderInstance/renderGlowMgr.cpp index 1ce49149d0..17ae78c607 100644 --- a/Engine/source/renderInstance/renderGlowMgr.cpp +++ b/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); diff --git a/Engine/source/renderInstance/renderMeshMgr.cpp b/Engine/source/renderInstance/renderMeshMgr.cpp index c9de7c2296..ddf1e4508e 100644 --- a/Engine/source/renderInstance/renderMeshMgr.cpp +++ b/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 ); diff --git a/Engine/source/renderInstance/renderPassManager.h b/Engine/source/renderInstance/renderPassManager.h index 98080365b6..baf53ce463 100644 --- a/Engine/source/renderInstance/renderPassManager.h +++ b/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 mCustomShaderData; + void clear(); }; diff --git a/Engine/source/renderInstance/renderTranslucentMgr.cpp b/Engine/source/renderInstance/renderTranslucentMgr.cpp index e0c3e6bb4e..7413cd24d9 100644 --- a/Engine/source/renderInstance/renderTranslucentMgr.cpp +++ b/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() ) { diff --git a/Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp b/Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp new file mode 100644 index 0000000000..3b04670626 --- /dev/null +++ b/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& 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& 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(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 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(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; +} diff --git a/Engine/source/shaderGen/GLSL/customFeatureGLSL.h b/Engine/source/shaderGen/GLSL/customFeatureGLSL.h new file mode 100644 index 0000000000..c2d0191cc2 --- /dev/null +++ b/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 mVars; + + Vector mConnectorVars; + + enum outputState + { + NoOutput, + VertexOutput, + PixelOutput + }; + + outputState mOutputState; + +public: + CustomShaderFeatureData* mOwner; + + Vector mComponentList; + MaterialFeatureData mFeatureData; + +protected: + MultiLine* meta; + +public: + + //**************************************************************************** + // Accu Texture + //**************************************************************************** + virtual void processVert(Vector& componentList, + const MaterialFeatureData& fd); + + virtual void processPix(Vector& 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); +}; diff --git a/Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp new file mode 100644 index 0000000000..fa0a3934e4 --- /dev/null +++ b/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& 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& 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(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 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(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; +} diff --git a/Engine/source/shaderGen/HLSL/customFeatureHLSL.h b/Engine/source/shaderGen/HLSL/customFeatureHLSL.h new file mode 100644 index 0000000000..dd1ad0a09e --- /dev/null +++ b/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 mVars; + + Vector mConnectorVars; + + enum outputState + { + NoOutput, + VertexOutput, + PixelOutput + }; + + outputState mOutputState; + +public: + CustomShaderFeatureData* mOwner; + + Vector mComponentList; + MaterialFeatureData mFeatureData; + +protected: + MultiLine* meta; + +public: + + //**************************************************************************** + // Accu Texture + //**************************************************************************** + virtual void processVert(Vector& componentList, + const MaterialFeatureData& fd); + + virtual void processPix(Vector& 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); +}; diff --git a/Engine/source/shaderGen/customShaderFeature.cpp b/Engine/source/shaderGen/customShaderFeature.cpp new file mode 100644 index 0000000000..fc5cbf35a6 --- /dev/null +++ b/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); +} diff --git a/Engine/source/shaderGen/customShaderFeature.h b/Engine/source/shaderGen/customShaderFeature.h new file mode 100644 index 0000000000..77bc50068e --- /dev/null +++ b/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 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 diff --git a/Engine/source/shaderGen/langElement.cpp b/Engine/source/shaderGen/langElement.cpp index e4870bb14e..ec94c30eec 100644 --- a/Engine/source/shaderGen/langElement.cpp +++ b/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; diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index 6b19ba0f5a..7d681e81b5 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/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 ¯os ) + Vector ¯os, + Vector &customFeatureData) { PROFILE_SCOPE( ShaderGen_GenerateShader ); mFeatureData = featureData; mVertexFormat = vertexFormat; + mCustomFeaturesData = customFeatureData; + _uninit(); _init(); @@ -281,6 +286,40 @@ void ShaderGen::_processVertFeatures( Vector ¯os, 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( mComponents[C_CONNECTOR] ); connect->sortVars(); } @@ -320,6 +359,40 @@ void ShaderGen::_processPixFeatures( Vector ¯os, 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( 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 *macros, const Vector &samplers ) +GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, Vector &customFeatureData, const GFXVertexFormat *vertexFormat, const Vector *macros, const Vector &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)) diff --git a/Engine/source/shaderGen/shaderGen.h b/Engine/source/shaderGen/shaderGen.h index 2ebcda4c26..8294876026 100644 --- a/Engine/source/shaderGen/shaderGen.h +++ b/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 @@ class ShaderGen F32 *pixVersion, const GFXVertexFormat *vertexFormat, const char* cacheName, - Vector ¯os ); + Vector ¯os, + Vector &customFeatureData); // Returns a shader that implements the features listed by dat. - GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector *macros, const Vector &samplers ); + GFXShader* getShader( const MaterialFeatureData &dat, Vector &customFeatureData, const GFXVertexFormat *vertexFormat, const Vector *macros, const Vector &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 @@ class ShaderGen Vector< ShaderComponent *> mComponents; + Vector< CustomShaderFeatureData* > mCustomFeaturesData; + AutoPtr mPrinter; AutoPtr mComponentFactory; diff --git a/Engine/source/terrain/terrCellMaterial.cpp b/Engine/source/terrain/terrCellMaterial.cpp index de0be345ee..ad45b57c25 100644 --- a/Engine/source/terrain/terrCellMaterial.cpp +++ b/Engine/source/terrain/terrCellMaterial.cpp @@ -460,6 +460,8 @@ bool TerrainCellMaterial::_createPass( Vector *materials, featureData.features = features; featureData.materialFeatures = features; + Vector 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 *materials, const bool logErrors = matCount == 1; GFXShader::setLogging( logErrors, true ); - pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat(), NULL, mSamplerNames ); + pass->shader = SHADERGEN->getShader( featureData, customFeatures, getGFXVertexFormat(), NULL, mSamplerNames ); } // If we got a shader then we can continue. diff --git a/Engine/source/ts/tsMesh.cpp b/Engine/source/ts/tsMesh.cpp index 5e767bd667..ddf81bfbd5 100644 --- a/Engine/source/ts/tsMesh.cpp +++ b/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(); diff --git a/Engine/source/ts/tsRenderState.cpp b/Engine/source/ts/tsRenderState.cpp index 0c3458af74..4c0ce6b931 100644 --- a/Engine/source/ts/tsRenderState.cpp +++ b/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 ) { } diff --git a/Engine/source/ts/tsRenderState.h b/Engine/source/ts/tsRenderState.h index fcb7651854..eda8d5b3a6 100644 --- a/Engine/source/ts/tsRenderState.h +++ b/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 @@ class TSRenderState /// Count of matrices in the mNodeTransforms list U32 mNodeTransformCount; -public: - - + //Custom Shader data + Vector mCustomShaderData; +public: TSRenderState(); TSRenderState( const TSRenderState &state ); @@ -165,6 +169,15 @@ class TSRenderState void setAccuTex( GFXTextureObject* query ) { mAccuTex = query; } GFXTextureObject* getAccuTex() const { return mAccuTex; } + void addCustomShaderBinding(CustomShaderBindingData data) + { + mCustomShaderData.push_back(data); + } + Vector 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; } From 1259e5245b32719026fbe5a588b07886baa60f4d Mon Sep 17 00:00:00 2001 From: Areloch Date: Wed, 22 May 2019 21:44:07 -0500 Subject: [PATCH 2/3] Proper splitting of D3D and OpenGL sides of the CSF. --- .../source/shaderGen/customShaderFeature.cpp | 80 ++++++++++++++----- Engine/source/shaderGen/customShaderFeature.h | 8 ++ Tools/CMake/torque3d.cmake | 3 +- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/Engine/source/shaderGen/customShaderFeature.cpp b/Engine/source/shaderGen/customShaderFeature.cpp index fc5cbf35a6..33c40dd468 100644 --- a/Engine/source/shaderGen/customShaderFeature.cpp +++ b/Engine/source/shaderGen/customShaderFeature.cpp @@ -21,8 +21,13 @@ //----------------------------------------------------------------------------- #include "shadergen/CustomShaderFeature.h" + +#ifdef TORQUE_D3D11 #include "shaderGen/HLSL/customFeatureHLSL.h" +#endif +#ifdef TORQUE_OPENGL #include "shaderGen/GLSL/customFeatureGLSL.h" +#endif #include "math/mathIO.h" #include "scene/sceneRenderState.h" @@ -36,16 +41,10 @@ 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" + "@brief A Shader Feature with custom definitions.\n\n" + "This class allows for the creation and implementation of a ShaderGen ShaderFeature " + "Implemented either engine side or script, and facilitates passing along of per-instance " + "ShaderData. " "@ingroup Examples\n"); //----------------------------------------------------------------------------- @@ -53,6 +52,12 @@ ConsoleDocClass(CustomShaderFeatureData, //----------------------------------------------------------------------------- CustomShaderFeatureData::CustomShaderFeatureData() { +#ifdef TORQUE_D3D11 + mFeatureHLSL = nullptr; +#endif +#ifdef TORQUE_OPENGL + mFeatureGLSL = nullptr; +#endif } CustomShaderFeatureData::~CustomShaderFeatureData() @@ -73,16 +78,21 @@ bool CustomShaderFeatureData::onAdd() if (!Parent::onAdd()) return false; +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) { mFeatureHLSL = new CustomFeatureHLSL(); mFeatureHLSL->mOwner = this; } - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif + +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) { mFeatureGLSL = new CustomFeatureGLSL(); mFeatureGLSL->mOwner = this; } +#endif return true; } @@ -95,66 +105,98 @@ void CustomShaderFeatureData::onRemove() //Shadergen setup functions void CustomShaderFeatureData::addVariable(String name, String type, String defaultValue) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->addVariable(name, type, defaultValue); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->addVariable(name, type, defaultValue); +#endif } void CustomShaderFeatureData::addUniform(String name, String type, String defaultValue, U32 arraySize) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->addUniform(name, type, defaultValue, arraySize); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->addUniform(name, type, defaultValue, arraySize); +#endif } void CustomShaderFeatureData::addSampler(String name, String type, U32 arraySize) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->addSampler(name, type, arraySize); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->addSampler(name, type, arraySize); +#endif } void CustomShaderFeatureData::addTexture(String name, String type, String samplerState, U32 arraySize) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->addTexture(name, type, samplerState, arraySize); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->addTexture(name, type, samplerState, arraySize); +#endif } void CustomShaderFeatureData::addConnector(String name, String type, String elementName) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->addConnector(name, type, elementName); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->addConnector(name, type, elementName); +#endif } void CustomShaderFeatureData::addVertTexCoord(String name) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->addVertTexCoord(name); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->addVertTexCoord(name); +#endif } bool CustomShaderFeatureData::hasFeature(String name) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) return mFeatureHLSL->hasFeature(name); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) return mFeatureGLSL->hasFeature(name); +#endif } void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValueRef* argv) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) mFeatureHLSL->writeLine(format, argc, argv); - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) mFeatureGLSL->writeLine(format, argc, argv); +#endif } DefineEngineMethod(CustomShaderFeatureData, addVariable, void, (String name, String type, String defaultValue), ("", "", ""), "") diff --git a/Engine/source/shaderGen/customShaderFeature.h b/Engine/source/shaderGen/customShaderFeature.h index 77bc50068e..b6789f3e7a 100644 --- a/Engine/source/shaderGen/customShaderFeature.h +++ b/Engine/source/shaderGen/customShaderFeature.h @@ -27,16 +27,24 @@ #include "console/simObject.h" #endif +#ifdef TORQUE_D3D11 class CustomFeatureHLSL; +#endif +#ifdef TORQUE_OPENGL class CustomFeatureGLSL; +#endif class CustomShaderFeatureData : public SimObject { typedef SimObject Parent; public: +#ifdef TORQUE_D3D11 CustomFeatureHLSL* mFeatureHLSL; +#endif +#ifdef TORQUE_OPENGL CustomFeatureGLSL* mFeatureGLSL; +#endif Vector mAddedShaderConstants; diff --git a/Tools/CMake/torque3d.cmake b/Tools/CMake/torque3d.cmake index d827663f52..b57fb1f255 100644 --- a/Tools/CMake/torque3d.cmake +++ b/Tools/CMake/torque3d.cmake @@ -149,6 +149,8 @@ endif() if(WIN32) option(TORQUE_D3D11 "Allow Direct3D 11 render" ON) + + addDef(TORQUE_D3D11) endif() option(TORQUE_DEDICATED "Torque dedicated" OFF) @@ -313,7 +315,6 @@ addPath("${srcDir}/scene") addPath("${srcDir}/scene/culling") addPath("${srcDir}/scene/zones") addPath("${srcDir}/scene/mixin") -addPath("${srcDir}/shaderGen") addPath("${srcDir}/terrain") addPath("${srcDir}/environment") addPath("${srcDir}/forest") From 0a0e3980e06bb1b088248369ea550c454c985e44 Mon Sep 17 00:00:00 2001 From: Areloch Date: Wed, 22 May 2019 23:20:29 -0500 Subject: [PATCH 3/3] Proper bracketing for shaderGen.cpp --- Engine/source/shaderGen/shaderGen.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index 7d681e81b5..282ead1389 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -31,8 +31,12 @@ #include "core/memVolume.h" #include "core/module.h" +#ifdef TORQUE_D3D11 #include "shaderGen/HLSL/customFeatureHLSL.h" +#endif +#ifdef TORQUE_OPENGL #include "shaderGen/GLSL/customFeatureGLSL.h" +#endif MODULE_BEGIN( ShaderGen ) @@ -291,6 +295,7 @@ void ShaderGen::_processVertFeatures( Vector ¯os, bool macro { for (U32 i = 0; i < mCustomFeaturesData.size(); ++i) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) { mCustomFeaturesData[i]->mFeatureHLSL->processVert(mComponents, mFeatureData); @@ -304,7 +309,9 @@ void ShaderGen::_processVertFeatures( Vector ¯os, bool macro mCustomFeaturesData[i]->mFeatureHLSL->reset(); mOutput->addStatement(new GenOp(" \r\n")); } - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) { mCustomFeaturesData[i]->mFeatureGLSL->processVert(mComponents, mFeatureData); @@ -317,6 +324,7 @@ void ShaderGen::_processVertFeatures( Vector ¯os, bool macro mCustomFeaturesData[i]->mFeatureGLSL->reset(); mOutput->addStatement(new GenOp(" \r\n")); } +#endif } } @@ -365,6 +373,7 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros { for (U32 i = 0; i < mCustomFeaturesData.size(); ++i) { +#ifdef TORQUE_D3D11 if (GFX->getAdapterType() == GFXAdapterType::Direct3D11) { mCustomFeaturesData[i]->mFeatureHLSL->processPix(mComponents, mFeatureData); @@ -378,7 +387,9 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros mCustomFeaturesData[i]->mFeatureHLSL->reset(); mOutput->addStatement(new GenOp(" \r\n")); } - else if (GFX->getAdapterType() == GFXAdapterType::OpenGL) +#endif +#ifdef TORQUE_OPENGL + if (GFX->getAdapterType() == GFXAdapterType::OpenGL) { mCustomFeaturesData[i]->mFeatureGLSL->processPix(mComponents, mFeatureData); @@ -391,6 +402,7 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros mCustomFeaturesData[i]->mFeatureGLSL->reset(); mOutput->addStatement(new GenOp(" \r\n")); } +#endif } }