diff --git a/Engine/source/gfx/gfxShader.cpp b/Engine/source/gfx/gfxShader.cpp index 1fc35a995..62f6aff96 100644 --- a/Engine/source/gfx/gfxShader.cpp +++ b/Engine/source/gfx/gfxShader.cpp @@ -49,9 +49,9 @@ GFXShader::~GFXShader() } #ifndef TORQUE_OPENGL -bool GFXShader::init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, +bool GFXShader::init( const Torque::Path &vertFile, + const Torque::Path &pixFile, + F32 pixVersion, const Vector ¯os ) { Vector samplerNames; @@ -59,13 +59,18 @@ bool GFXShader::init( const Torque::Path &vertFile, } #endif -bool GFXShader::init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, +bool GFXShader::init( F32 pixVersion, const Vector ¯os, const Vector &samplerNames, GFXVertexFormat *instanceFormat) { + // early out. + if (mVertexFile.isEmpty() && mPixelFile.isEmpty() && mGeometryFile.isEmpty()) + { + Con::errorf("Shader files empty, please call setShaderStageFile from shaderData"); + return false; + } + // Take care of instancing if (instanceFormat) { @@ -74,8 +79,6 @@ bool GFXShader::init( const Torque::Path &vertFile, } // Store the inputs for use in reloading. - mVertexFile = vertFile; - mPixelFile = pixFile; mPixVersion = pixVersion; mMacros = macros; mSamplerNamesOrdered = samplerNames; @@ -91,8 +94,12 @@ bool GFXShader::init( const Torque::Path &vertFile, _updateDesc(); // Add file change notifications for reloads. - Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged ); - Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged ); + if(!mVertexFile.isEmpty()) + Torque::FS::AddChangeNotification( mVertexFile, this, &GFXShader::_onFileChanged ); + if(!mPixelFile.isEmpty()) + Torque::FS::AddChangeNotification( mPixelFile, this, &GFXShader::_onFileChanged ); + if(!mGeometryFile.isEmpty()) + Torque::FS::AddChangeNotification( mGeometryFile, this, &GFXShader::_onFileChanged); return true; } @@ -119,11 +126,11 @@ bool GFXShader::reload() void GFXShader::_updateDesc() { - mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ", + mDescription = String::ToString( "Files: %s, %s Pix Version: %0.2f\nMacros: ", mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), mPixVersion ); GFXShaderMacro::stringize( smGlobalMacros, &mDescription ); - GFXShaderMacro::stringize( mMacros, &mDescription ); + GFXShaderMacro::stringize( mMacros, &mDescription ); } void GFXShader::addGlobalMacro( const String &name, const String &value ) @@ -161,8 +168,26 @@ bool GFXShader::removeGlobalMacro( const String &name ) return false; } +void GFXShader::setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath) +{ + switch (stage) + { + case GFXShaderStage::VERTEX_SHADER: + mVertexFile = filePath; + break; + case GFXShaderStage::PIXEL_SHADER: + mPixelFile = filePath; + break; + case GFXShaderStage::GEOMETRY_SHADER: + mGeometryFile = filePath; + break; + default: + break; + } +} + void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf ) -{ +{ Vector::iterator iter = mActiveBuffers.begin(); for ( ; iter != mActiveBuffers.end(); iter++ ) { @@ -177,7 +202,7 @@ void GFXShader::_unlinkBuffer( GFXShaderConstBuffer *buf ) } -DefineEngineFunction( addGlobalShaderMacro, void, +DefineEngineFunction( addGlobalShaderMacro, void, ( const char *name, const char *value ), ( nullAsType() ), "Adds a global shader macro which will be merged with the script defined " "macros on every shader. The macro will replace the value of an existing " @@ -189,7 +214,7 @@ DefineEngineFunction( addGlobalShaderMacro, void, GFXShader::addGlobalMacro( name, value ); } -DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),, +DefineEngineFunction( removeGlobalShaderMacro, void, ( const char *name ),, "Removes an existing global macro by name.\n" "@see addGlobalShaderMacro\n" "@ingroup Rendering\n" ) diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 4a880135d..abc45e9fe 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -76,7 +76,7 @@ enum GFXShaderStage }; /// Instances of this struct are returned GFXShaderConstBuffer -struct GFXShaderConstDesc +struct GFXShaderConstDesc { public: String name; @@ -92,7 +92,7 @@ public: /// This is an opaque handle used by GFXShaderConstBuffer clients to set individual shader constants. /// Derived classes can put whatever info they need into here, these handles are owned by the shader constant buffer /// (or shader). Client code should not free these. -class GFXShaderConstHandle +class GFXShaderConstHandle { public: @@ -101,8 +101,8 @@ public: /// Returns true if this constant is valid and can /// be set on the shader. - bool isValid() const { return mValid; } - + bool isValid() const { return mValid; } + /// Returns the name of the constant handle. virtual const String& getName() const = 0; @@ -110,7 +110,7 @@ public: virtual GFXShaderConstType getType() const = 0; virtual U32 getArraySize() const = 0; - + /// Returns -1 if this handle does not point to a Sampler. virtual S32 getSamplerRegister() const = 0; @@ -119,7 +119,7 @@ protected: /// The state of the constant which is /// set from the derived class. bool mValid; - + }; @@ -143,7 +143,7 @@ protected: /// @see wasLost bool mWasLost; - GFXShaderConstBuffer() + GFXShaderConstBuffer() : mWasLost( true ), mInstPtr( NULL ) { @@ -155,16 +155,16 @@ public: virtual GFXShader* getShader() = 0; /// The content of the buffer is in the lost state when - /// first created or when the shader is reloaded. When + /// first created or when the shader is reloaded. When /// the content is lost you must refill the buffer /// with all the constants used by your shader. /// - /// Use this property to avoid setting constants which do + /// Use this property to avoid setting constants which do /// not changefrom one frame to the next. /// bool wasLost() const { return mWasLost; } - /// An inline helper which ensures the handle is valid + /// An inline helper which ensures the handle is valid /// before the virtual set method is called. /// /// You should prefer using this method unless your sure the @@ -183,7 +183,7 @@ public: /// /// Perfer using setSafe unless you can check the handle /// validity yourself and skip a significat amount of work. - /// + /// /// @see GFXShaderConstHandle::isValid() /// virtual void set(GFXShaderConstHandle* handle, const F32 f) = 0; @@ -204,19 +204,19 @@ public: virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv) = 0; virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv) = 0; virtual void set(GFXShaderConstHandle* handle, const AlignedArray& fv) = 0; - - /// Set a variable sized matrix shader constant. - virtual void set( GFXShaderConstHandle* handle, - const MatrixF& mat, + + /// Set a variable sized matrix shader constant. + virtual void set( GFXShaderConstHandle* handle, + const MatrixF& mat, const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0; - + /// Set a variable sized matrix shader constant from - /// an array of matricies. - virtual void set( GFXShaderConstHandle* handle, - const MatrixF* mat, - const U32 arraySize, + /// an array of matricies. + virtual void set( GFXShaderConstHandle* handle, + const MatrixF* mat, + const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4 ) = 0; - + // TODO: Make this protected and put a real API around it. U8 *mInstPtr; }; @@ -232,8 +232,8 @@ class GFXShader : public StrongRefBase, public GFXResource friend class GFXShaderConstBuffer; protected: - - /// These are system wide shader macros which are + + /// These are system wide shader macros which are /// merged with shader specific macros at creation. static Vector smGlobalMacros; @@ -244,19 +244,22 @@ protected: static bool smLogWarnings; /// The vertex shader file. - Torque::Path mVertexFile; + Torque::Path mVertexFile; /// The pixel shader file. - Torque::Path mPixelFile; + Torque::Path mPixelFile; - /// The macros to be passed to the shader. + // the geometry shader file. + Torque::Path mGeometryFile; + + /// The macros to be passed to the shader. Vector mMacros; /// Ordered SamplerNames /// We need to store a list of sampler for allow OpenGL to /// assign correct location for each sampler. /// GLSL 150 not allow explicit uniform location. - /// Only used on OpenGL + /// Only used on OpenGL Vector mSamplerNamesOrdered; /// The pixel version this is compiled for. @@ -271,7 +274,7 @@ protected: Signal mReloadSignal; /// Vector of buffers that reference this shader. - /// It is the responsibility of the derived shader class to populate this + /// It is the responsibility of the derived shader class to populate this /// vector and to notify them when this shader is reloaded. Classes /// derived from GFXShaderConstBuffer should call _unlinkBuffer from /// their destructor. @@ -282,7 +285,7 @@ protected: /// A protected constructor so it cannot be instantiated. GFXShader(); -public: +public: /// Adds a global shader macro which will be merged with /// the script defined macros on every shader reload. @@ -303,9 +306,9 @@ public: /// Toggle logging for shader errors. static void setLogging( bool logErrors, - bool logWarning ) + bool logWarning ) { - smLogErrors = logErrors; + smLogErrors = logErrors; smLogWarnings = logWarning; } @@ -315,16 +318,14 @@ public: /// /// Deprecated. Remove on T3D 4.0 #ifndef TORQUE_OPENGL - bool init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, + bool init( const Torque::Path &vertFile, + const Torque::Path &pixFile, + F32 pixVersion, const Vector ¯os ); #endif /// - bool init( const Torque::Path &vertFile, - const Torque::Path &pixFile, - F32 pixVersion, + bool init( F32 pixVersion, const Vector ¯os, const Vector &samplerNames, GFXVertexFormat *instanceFormat = NULL ); @@ -335,23 +336,23 @@ public: Signal getReloadSignal() { return mReloadSignal; } /// Allocate a constant buffer - virtual GFXShaderConstBufferRef allocConstBuffer() = 0; + virtual GFXShaderConstBufferRef allocConstBuffer() = 0; /// Returns our list of shader constants, the material can get this and just set the constants it knows about virtual const Vector& getShaderConstDesc() const = 0; /// Returns a shader constant handle for the name constant. /// - /// Since shaders can reload and later have handles that didn't + /// Since shaders can reload and later have handles that didn't /// exist originally this will return a handle in an invalid state /// if the constant doesn't exist at this time. - virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; + virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; /// Returns a shader constant handle for the name constant, if the variable doesn't exist NULL is returned. virtual GFXShaderConstHandle* findShaderConstHandle( const String& name ) = 0; /// Returns the alignment value for constType - virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0; + virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0; /// Returns the required vertex format for this shader. /// Returns the pixel shader version. @@ -364,6 +365,8 @@ public: /// the shader disassembly. virtual bool getDisassembly( String &outStr ) const { return false; } + void setShaderStageFile(const GFXShaderStage stage, const Torque::Path& filePath); + /// Returns the vertex shader file path. const String& getVertexShaderFile() const { return mVertexFile.getFullPath(); } diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp index 03cd40ec4..334ffe720 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.cpp +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.cpp @@ -134,7 +134,7 @@ void GuiShaderEditor::onPreRender() setUpdate(); } -void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness = 2, ColorI col1 = ColorI(255, 255, 255), ColorI col2 = ColorI(255, 255, 255)) +void GuiShaderEditor::drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2) { Point2F dir = Point2F(pt2.x - pt1.x, pt2.y - pt1.y); if (dir == Point2F::Zero) @@ -292,7 +292,7 @@ void GuiShaderEditor::renderConnections(Point2I offset, const RectI& updateRect) start += Point2I(mNodeSize / 2, mNodeSize / 2); end += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, end); + drawThickLine(start, end, mNodeSize/3); } // Restore the clip rect to what it was at the start @@ -328,7 +328,7 @@ void GuiShaderEditor::onRender(Point2I offset, const RectI& updateRect) RectI sockActive(start, Point2I(mNodeSize, mNodeSize)); start += Point2I(mNodeSize / 2, mNodeSize / 2); - drawThickLine(start, mLastMousePos + offset); + drawThickLine(start, mLastMousePos + offset, mNodeSize/3); // draw socket overlay over the top of the line. sockActive.inset(1, 1); diff --git a/Engine/source/gui/shaderEditor/guiShaderEditor.h b/Engine/source/gui/shaderEditor/guiShaderEditor.h index 0305882a6..0a8f6ccff 100644 --- a/Engine/source/gui/shaderEditor/guiShaderEditor.h +++ b/Engine/source/gui/shaderEditor/guiShaderEditor.h @@ -117,7 +117,7 @@ public: virtual void onRemove() override; virtual void onPreRender() override; - void drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness, ColorI col1, ColorI col2); + void drawThickLine(const Point2I& pt1, const Point2I& pt2, U32 thickness = 2, ColorI col1 = ColorI(255, 255, 255), ColorI col2 = ColorI(255, 255, 255)); virtual void onRender(Point2I offset, const RectI& updateRect) override; // interaction diff --git a/Engine/source/materials/shaderData.cpp b/Engine/source/materials/shaderData.cpp index 8d8e8d103..34eab775d 100644 --- a/Engine/source/materials/shaderData.cpp +++ b/Engine/source/materials/shaderData.cpp @@ -48,10 +48,12 @@ ConsoleDocClass( ShaderData, "// Used for the procedural clould system\n" "singleton ShaderData( CloudLayerShader )\n" "{\n" - " DXVertexShaderFile = $Core::CommonShaderPath @ \"/cloudLayerV.hlsl\";\n" - " DXPixelShaderFile = $Core::CommonShaderPath @ \"/cloudLayerP.hlsl\";\n" - " OGLVertexShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerV.glsl\";\n" - " OGLPixelShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerP.glsl\";\n" + " DXVertexShaderFile = $Core::CommonShaderPath @ \"/cloudLayerV.hlsl\";\n" + " DXPixelShaderFile = $Core::CommonShaderPath @ \"/cloudLayerP.hlsl\";\n" + " DXGeometryShaderFile = $Core::CommonShaderPath @ \"/cloudLayerG.hlsl\";\n" + " OGLVertexShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerV.glsl\";\n" + " OGLPixelShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerP.glsl\";\n" + " OGLGeometryShaderFile = $Core::CommonShaderPath @ \"/gl/cloudLayerG.glsl\";\n" " pixVersion = 2.0;\n" "};\n" "@endtsexample\n\n" @@ -67,70 +69,87 @@ ShaderData::ShaderData() for( int i = 0; i < NumTextures; ++i) mRTParams[i] = false; + + mDXVertexShaderName = StringTable->EmptyString(); + mDXPixelShaderName = StringTable->EmptyString(); + mDXGeometryShaderName = StringTable->EmptyString(); + + mOGLVertexShaderName = StringTable->EmptyString(); + mOGLPixelShaderName = StringTable->EmptyString(); + mOGLGeometryShaderName = StringTable->EmptyString(); } void ShaderData::initPersistFields() { docsURL; - addField("DXVertexShaderFile", TypeStringFilename, Offset(mDXVertexShaderName, ShaderData), - "@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n" - "It must contain only one program and no pixel shader, just the vertex shader." - "It can be either an HLSL or assembly level shader. HLSL's must have a " - "filename extension of .hlsl, otherwise its assumed to be an assembly file."); + addField("DXVertexShaderFile", TypeStringFilename, Offset(mDXVertexShaderName, ShaderData), + "@brief %Path to the DirectX vertex shader file to use for this ShaderData.\n\n" + "It must contain only one program and no pixel shader, just the vertex shader." + "It can be either an HLSL or assembly level shader. HLSL's must have a " + "filename extension of .hlsl, otherwise its assumed to be an assembly file."); - addField("DXPixelShaderFile", TypeStringFilename, Offset(mDXPixelShaderName, ShaderData), - "@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n" - "It must contain only one program and no vertex shader, just the pixel " - "shader. It can be either an HLSL or assembly level shader. HLSL's " - "must have a filename extension of .hlsl, otherwise its assumed to be an assembly file."); + addField("DXPixelShaderFile", TypeStringFilename, Offset(mDXPixelShaderName, ShaderData), + "@brief %Path to the DirectX pixel shader file to use for this ShaderData.\n\n" + "It must contain only one program and no vertex shader, just the pixel " + "shader. It can be either an HLSL or assembly level shader. HLSL's " + "must have a filename extension of .hlsl, otherwise its assumed to be an assembly file."); - addField("OGLVertexShaderFile", TypeStringFilename, Offset(mOGLVertexShaderName, ShaderData), - "@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n" - "It must contain only one program and no pixel shader, just the vertex shader."); + addField("DXGeometryShaderFile", TypeStringFilename, Offset(mDXGeometryShaderName, ShaderData), + "@brief %Path to the DirectX geometry shader file to use for this ShaderData.\n\n" + "It can be either an HLSL or assembly level shader. HLSL's must have a " + "filename extension of .hlsl, otherwise its assumed to be an assembly file."); - addField("OGLPixelShaderFile", TypeStringFilename, Offset(mOGLPixelShaderName, ShaderData), - "@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n" - "It must contain only one program and no vertex shader, just the pixel " - "shader."); + addField("OGLVertexShaderFile", TypeStringFilename, Offset(mOGLVertexShaderName, ShaderData), + "@brief %Path to an OpenGL vertex shader file to use for this ShaderData.\n\n" + "It must contain only one program and no pixel shader, just the vertex shader."); - addField("useDevicePixVersion", TypeBool, Offset(mUseDevicePixVersion, ShaderData), - "@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n" - "Otherwise, the script-defined pixel shader version will be used.\n\n"); + addField("OGLPixelShaderFile", TypeStringFilename, Offset(mOGLPixelShaderName, ShaderData), + "@brief %Path to an OpenGL pixel shader file to use for this ShaderData.\n\n" + "It must contain only one program and no vertex shader, just the pixel " + "shader."); - addField("pixVersion", TypeF32, Offset(mPixVersion, ShaderData), - "@brief Indicates target level the shader should be compiled.\n\n" - "Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. " - "The shader will not run properly if the hardware does not support the " - "level of shader compiled."); - - addField("defines", TypeRealString, Offset(mDefines, ShaderData), - "@brief String of case-sensitive defines passed to the shader compiler.\n\n" + addField("OGLGeometryShaderFile", TypeStringFilename, Offset(mOGLGeometryShaderName, ShaderData), + "@brief %Path to the OpenGL Geometry shader file to use for this ShaderData.\n\n"); + + addField("useDevicePixVersion", TypeBool, Offset(mUseDevicePixVersion, ShaderData), + "@brief If true, the maximum pixel shader version offered by the graphics card will be used.\n\n" + "Otherwise, the script-defined pixel shader version will be used.\n\n"); + + addField("pixVersion", TypeF32, Offset(mPixVersion, ShaderData), + "@brief Indicates target level the shader should be compiled.\n\n" + "Valid numbers at the time of this writing are 1.1, 1.4, 2.0, and 3.0. " + "The shader will not run properly if the hardware does not support the " + "level of shader compiled."); + + addField("defines", TypeRealString, Offset(mDefines, ShaderData), + "@brief String of case-sensitive defines passed to the shader compiler.\n\n" "The string should be delimited by a semicolon, tab, or newline character." - + "@tsexample\n" - "singleton ShaderData( FlashShader )\n" - "{\n" - "DXVertexShaderFile = $shaderGen::cachePath @ \"/postFx/flashV.hlsl\";\n" - "DXPixelShaderFile = $shaderGen::cachePath @ \"/postFx/flashP.hlsl\";\n\n" - " //Define setting the color of WHITE_COLOR.\n" - "defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n" - "pixVersion = 2.0\n" - "}\n" + "singleton ShaderData( FlashShader )\n" + "{\n" + "DXVertexShaderFile = $shaderGen::cachePath @ \"/postFx/flashV.hlsl\";\n" + "DXPixelShaderFile = $shaderGen::cachePath @ \"/postFx/flashP.hlsl\";\n\n" + "DXGeometryShaderFile = $shaderGen::cachePath @ \"/postFx/flashG.hlsl\";\n\n" + " //Define setting the color of WHITE_COLOR.\n" + "defines = \"WHITE_COLOR=float4(1.0,1.0,1.0,0.0)\";\n\n" + "pixVersion = 2.0\n" + "}\n" "@endtsexample\n\n" - ); + ); - addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures, + addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures, "@brief Indicates names of samplers present in shader. Order is important.\n\n" - "Order of sampler names are used to assert correct sampler register/location" + "Order of sampler names are used to assert correct sampler register/location" "Other objects (GFXStateBlockData, PostEffect...) use index number to link samplers." - ); + ); - addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, ""); + addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, ""); Parent::initPersistFields(); // Make sure we get activation signals. - LightManager::smActivateSignal.notify( &ShaderData::_onLMActivate ); + LightManager::smActivateSignal.notify(&ShaderData::_onLMActivate); } bool ShaderData::onAdd() @@ -147,8 +166,8 @@ bool ShaderData::onAdd() for(int i = 0; i < NumTextures; ++i) { - if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") ) - mSamplerNames[i].insert(0, "$"); + if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") ) + mSamplerNames[i].insert(0, "$"); } return true; @@ -164,12 +183,12 @@ void ShaderData::onRemove() const Vector& ShaderData::_getMacros() { - // If they have already been processed then + // If they have already been processed then // return the cached result. if ( mShaderMacros.size() != 0 || mDefines.isEmpty() ) return mShaderMacros; - mShaderMacros.clear(); + mShaderMacros.clear(); GFXShaderMacro macro; const U32 defineCount = StringUnit::getUnitCount( mDefines, ";\n\t" ); for ( U32 i=0; i < defineCount; i++ ) @@ -195,7 +214,7 @@ GFXShader* ShaderData::getShader( const Vector ¯os ) // Convert the final macro list to a string. String cacheKey; - GFXShaderMacro::stringize( macros, &cacheKey ); + GFXShaderMacro::stringize( macros, &cacheKey ); // Lookup the shader for this instance. ShaderCache::Iterator iter = mShaders.find( cacheKey ); @@ -237,9 +256,13 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) { case Direct3D11: { - success = shader->init( mDXVertexShaderName, - mDXPixelShaderName, - pixver, + if (mDXVertexShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mDXVertexShaderName); + if (mDXPixelShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mDXPixelShaderName); + if (mDXGeometryShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mDXGeometryShaderName); + success = shader->init( pixver, macros, samplers); break; @@ -247,14 +270,19 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) case OpenGL: { - success = shader->init( mOGLVertexShaderName, - mOGLPixelShaderName, - pixver, + if(mOGLVertexShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mOGLVertexShaderName); + if (mOGLPixelShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mOGLPixelShaderName); + if (mOGLGeometryShaderName != String::EmptyString) + shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mOGLGeometryShaderName); + + success = shader->init( pixver, macros, samplers); break; } - + default: // Other device types are assumed to not support shaders. success = false; @@ -268,7 +296,7 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) { if(descs[i].constType != GFXSCT_Sampler && descs[i].constType != GFXSCT_SamplerCube) continue; - + GFXShaderConstHandle *handle = shader->findShaderConstHandle(descs[i].name); if(!handle || !handle->isValid()) continue; @@ -321,7 +349,7 @@ void ShaderData::_onLMActivate( const char *lm, bool activate ) bool ShaderData::hasSamplerDef(const String &_samplerName, int &pos) const { - String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName; + String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName; for(int i = 0; i < NumTextures; ++i) { if( mSamplerNames[i].equal(samplerName, String::NoCase ) ) @@ -342,9 +370,9 @@ bool ShaderData::_checkDefinition(GFXShader *shader) samplers.reserve(NumTextures); bool rtParams[NumTextures]; for(int i = 0; i < NumTextures; ++i) - rtParams[i] = false; + rtParams[i] = false; - const Vector &shaderConstDesc = shader->getShaderConstDesc(); + const Vector &shaderConstDesc = shader->getShaderConstDesc(); for(int i = 0; i < shaderConstDesc.size(); ++i) { @@ -352,7 +380,7 @@ bool ShaderData::_checkDefinition(GFXShader *shader) if(desc.constType == GFXSCT_Sampler) { samplers.push_back(desc.name ); - } + } } for(int i = 0; i < samplers.size(); ++i) @@ -361,14 +389,14 @@ bool ShaderData::_checkDefinition(GFXShader *shader) bool find = hasSamplerDef(samplers[i], pos); if(find && pos >= 0 && mRTParams[pos]) - { + { if( !shader->findShaderConstHandle( String::ToString("$rtParams%d", pos)) ) { String errStr = String::ToString("ShaderData(%s) sampler[%d] used but rtParams%d not used in shader compilation. Possible error", shader->getPixelShaderFile().c_str(), pos, pos); Con::errorf(errStr); error = true; } - } + } if(!find) { @@ -377,7 +405,7 @@ bool ShaderData::_checkDefinition(GFXShader *shader) GFXAssertFatal(0, errStr); error = true; } - } + } return !error; } diff --git a/Engine/source/materials/shaderData.h b/Engine/source/materials/shaderData.h index 4bef16679..e07f513cf 100644 --- a/Engine/source/materials/shaderData.h +++ b/Engine/source/materials/shaderData.h @@ -47,7 +47,7 @@ protected: /// static Vector smAllShaderData; - typedef HashTable ShaderCache; + typedef HashTable ShaderCache; ShaderCache mShaders; @@ -56,12 +56,12 @@ protected: F32 mPixVersion; StringTableEntry mDXVertexShaderName; - StringTableEntry mDXPixelShaderName; + StringTableEntry mDXGeometryShaderName; StringTableEntry mOGLVertexShaderName; - StringTableEntry mOGLPixelShaderName; + StringTableEntry mOGLGeometryShaderName; /// A semicolon, tab, or newline delimited string of case /// sensitive defines that are passed to the shader compiler. @@ -80,40 +80,40 @@ protected: /// them if the content has changed. const Vector& _getMacros(); - /// Helper for converting an array of macros + /// Helper for converting an array of macros /// into a formatted string. - void _stringizeMacros( const Vector ¯os, - String *outString ); + void _stringizeMacros(const Vector& macros, + String* outString); /// Creates a new shader returning NULL on error. - GFXShader* _createShader( const Vector ¯os ); + GFXShader* _createShader(const Vector& macros); /// @see LightManager::smActivateSignal - static void _onLMActivate( const char *lm, bool activate ); + static void _onLMActivate(const char* lm, bool activate); enum { NumTextures = 16 }; - String mSamplerNames[NumTextures]; + String mSamplerNames[NumTextures]; bool mRTParams[NumTextures]; - bool _checkDefinition(GFXShader *shader); + bool _checkDefinition(GFXShader* shader); public: - void setSamplerName(const String &name, int idx) { mSamplerNames[idx] = name; } + void setSamplerName(const String& name, int idx) { mSamplerNames[idx] = name; } String getSamplerName(int idx) const { return mSamplerNames[idx]; } - bool hasSamplerDef(const String &samplerName, int &pos) const; + bool hasSamplerDef(const String& samplerName, int& pos) const; bool hasRTParamsDef(const int pos) const { return mRTParams[pos]; } ShaderData(); - /// Returns an initialized shader instance or NULL + /// Returns an initialized shader instance or NULL /// if the shader failed to be created. - GFXShader* getShader( const Vector ¯os = Vector() ); + GFXShader* getShader(const Vector& macros = Vector()); /// Forces a reinitialization of all the instanced shaders. void reloadShaders(); @@ -124,7 +124,7 @@ public: /// Returns the required pixel shader version for this shader. F32 getPixVersion() const { return mPixVersion; } - + // SimObject virtual bool onAdd(); virtual void onRemove(); diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index 9ae35d474..54b297772 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -47,7 +47,7 @@ MODULE_BEGIN( ShaderGen ) { ManagedSingleton< ShaderGen >::createSingleton(); } - + MODULE_SHUTDOWN { ManagedSingleton< ShaderGen >::deleteSingleton(); @@ -94,7 +94,7 @@ bool ShaderGen::_handleGFXEvent(GFXDevice::GFXDeviceEventType event) } void ShaderGen::initShaderGen() -{ +{ if (mInit) return; @@ -125,7 +125,7 @@ void ShaderGen::initShaderGen() { // If we didn't get a path then we're gonna cache the shaders to // a virtualized memory file system. - mMemFS = new Torque::Mem::MemFileSystem( "shadergen:/" ); + mMemFS = new Torque::Mem::MemFileSystem( "shadergen:/" ); Torque::FS::Mount( "shadergen", mMemFS ); } else @@ -136,8 +136,8 @@ void ShaderGen::initShaderGen() } void ShaderGen::generateShader( const MaterialFeatureData &featureData, - char *vertFile, - char *pixFile, + char *vertFile, + char *pixFile, F32 *pixVersion, const GFXVertexFormat *vertexFormat, const char* cacheName, @@ -155,23 +155,23 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, char pixShaderName[256]; // Note: We use a postfix of _V/_P here so that it sorts the matching - // vert and pixel shaders together when listed alphabetically. + // vert and pixel shaders together when listed alphabetically. dSprintf( vertShaderName, sizeof(vertShaderName), "shadergen:/%s_V.%s", cacheName, mFileEnding.c_str() ); dSprintf( pixShaderName, sizeof(pixShaderName), "shadergen:/%s_P.%s", cacheName, mFileEnding.c_str() ); - + dStrcpy( vertFile, vertShaderName, 256 ); dStrcpy( pixFile, pixShaderName, 256 ); - + // this needs to change - need to optimize down to ps v.1.1 *pixVersion = GFX->getPixelShaderVersion(); - + if ( !Con::getBoolVariable( "ShaderGen::GenNewShaders", true ) ) { // If we are not regenerating the shader we will return here. // But we must fill in the shader macros first! _processVertFeatures( macros, true ); - _processPixFeatures( macros, true ); + _processPixFeatures( macros, true ); return; } @@ -190,7 +190,7 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, _processVertFeatures(macros); _printVertShader( *s ); delete s; - + ((ShaderConnector*)mComponents[C_CONNECTOR])->reset(); LangElement::deleteElements(); @@ -202,7 +202,7 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData, AssertFatal(false, "Failed to open Shader Stream" ); delete s; return; - } + } mOutput = new MultiLine; _processPixFeatures(macros); @@ -284,7 +284,7 @@ void ShaderGen::_processVertFeatures( Vector ¯os, bool macro mOutput->addStatement( feature->getOutput() ); feature->reset(); - mOutput->addStatement( new GenOp( " \r\n" ) ); + mOutput->addStatement( new GenOp( " \r\n" ) ); } } @@ -327,7 +327,7 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros mOutput->addStatement( new GenOp( " \r\n" ) ); } } - + ShaderConnector *connect = dynamic_cast( mComponents[C_CONNECTOR] ); connect->sortVars(); } @@ -335,7 +335,7 @@ void ShaderGen::_processPixFeatures( Vector ¯os, bool macros void ShaderGen::_printFeatureList(Stream &stream) { mPrinter->printLine(stream, "// Features:"); - + const FeatureSet &features = mFeatureData.features; for( U32 i=0; i < features.getCount(); i++ ) @@ -376,7 +376,7 @@ void ShaderGen::_printDependencies(Stream &stream) for( U32 j=0; j < dependencies.size(); j++ ) { - if ( j != i && + if ( j != i && *dependencies[i] == *dependencies[j] ) { dup = true; @@ -386,7 +386,7 @@ void ShaderGen::_printDependencies(Stream &stream) if ( dup ) dependencies.erase( i ); - else + else i++; } @@ -493,7 +493,10 @@ GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const G generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros ); GFXShader *shader = GFX->createShader(); - if (!shader->init(vertFile, pixFile, pixVersion, shaderMacros, samplers, &mInstancingFormat)) + shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, vertFile); + shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, pixFile); + + if (!shader->init(pixVersion, shaderMacros, samplers, &mInstancingFormat)) { delete shader; return NULL; @@ -508,5 +511,5 @@ void ShaderGen::flushProceduralShaders() { // The shaders are reference counted, so we // just need to clear the map. - mProcShaders.clear(); + mProcShaders.clear(); }