mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-11 14:44:36 +00:00
Merge 1fd1b8e857 into 8407fa360c
This commit is contained in:
commit
c07234eb15
30 changed files with 2031 additions and 270 deletions
|
|
@ -22,15 +22,68 @@
|
|||
|
||||
#include "platform/platform.h"
|
||||
#include "core/stream/fileStream.h"
|
||||
|
||||
#include "platform/threads/threadPool.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FileStream methods...
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
FileStream::FileStream()
|
||||
static void writeBufferToFile(
|
||||
Torque::FS::FileRef& file,
|
||||
U32 buffHead,
|
||||
U32 buffTail,
|
||||
const U8* buffer)
|
||||
{
|
||||
if (!file || buffHead == FileStream::BUFFER_INVALID)
|
||||
return;
|
||||
|
||||
// match FileStream::flush logic
|
||||
if (buffHead != file->getPosition())
|
||||
file->setPosition(buffHead, Torque::FS::File::Begin);
|
||||
|
||||
U32 blockHead;
|
||||
FileStream::calcBlockHead(buffHead, &blockHead);
|
||||
|
||||
file->write((char*)buffer + (buffHead - blockHead), buffTail - buffHead + 1);
|
||||
}
|
||||
|
||||
struct FileCloseWorkItem : public ThreadPool::WorkItem
|
||||
{
|
||||
Torque::FS::FileRef mFile;
|
||||
|
||||
public:
|
||||
FileCloseWorkItem(Torque::FS::FileRef file)
|
||||
: mFile(file)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void execute() override
|
||||
{
|
||||
if (!mFile)
|
||||
return;
|
||||
|
||||
// When platforms free a file they
|
||||
// remove the handle which causes the stall
|
||||
// as they write metadata.
|
||||
mFile->close();
|
||||
}
|
||||
};
|
||||
|
||||
void FileStream::dispatchAsyncClose()
|
||||
{
|
||||
if (!mFile)
|
||||
return;
|
||||
|
||||
FileCloseWorkItem* job = new FileCloseWorkItem(mFile);
|
||||
|
||||
ThreadPool::GLOBAL().queueWorkItem(job);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
FileStream::FileStream(AsyncMode flushMode)
|
||||
{
|
||||
mAsyncMode = flushMode;
|
||||
dMemset(mBuffer, 0, sizeof(mBuffer));
|
||||
// initialize the file stream
|
||||
init();
|
||||
|
|
@ -190,10 +243,13 @@ void FileStream::close()
|
|||
if (mDirty)
|
||||
flush();
|
||||
|
||||
// and close the file
|
||||
mFile->close();
|
||||
|
||||
AssertFatal(mFile->getStatus() == Torque::FS::FileNode::Closed, "FileStream::close: close failed");
|
||||
if (mAsyncMode == Background)
|
||||
dispatchAsyncClose();
|
||||
else
|
||||
{
|
||||
mFile->close();
|
||||
AssertFatal(mFile->getStatus() == Torque::FS::FileNode::Closed, "FileStream::close: close failed");
|
||||
}
|
||||
|
||||
mFile = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,17 @@ public:
|
|||
BUFFER_INVALID = 0xffffffff // file offsets must all be less than this
|
||||
};
|
||||
|
||||
enum AsyncMode
|
||||
{
|
||||
Blocking, // current behavior
|
||||
Background // write-behind
|
||||
};
|
||||
|
||||
typedef char Ch; //!< Character type. Only support char.
|
||||
public:
|
||||
FileStream(); // default constructor
|
||||
AsyncMode mAsyncMode;
|
||||
void dispatchAsyncClose();
|
||||
FileStream(AsyncMode flushMode = Blocking); // default constructor
|
||||
virtual ~FileStream(); // destructor
|
||||
|
||||
// This function will allocate a new FileStream and open it.
|
||||
|
|
@ -64,7 +72,7 @@ public:
|
|||
//rjson compatibility
|
||||
bool Flush() { return flush(); }
|
||||
FileStream* clone() const override;
|
||||
|
||||
static void calcBlockHead(const U32 i_position, U32* o_blockHead);
|
||||
protected:
|
||||
// more mandatory methods from Stream base class...
|
||||
bool _read(const U32 i_numBytes, void *o_pBuffer) override;
|
||||
|
|
@ -73,7 +81,7 @@ protected:
|
|||
void init();
|
||||
bool fillBuffer(const U32 i_startPosition);
|
||||
void clearBuffer();
|
||||
static void calcBlockHead(const U32 i_position, U32 *o_blockHead);
|
||||
|
||||
static void calcBlockBounds(const U32 i_position, U32 *o_blockHead, U32 *o_blockTail);
|
||||
void setStatus();
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "core/util/hashFunction.h"
|
||||
|
||||
#include "core/util/endian.h"
|
||||
|
||||
namespace Torque
|
||||
{
|
||||
|
||||
|
|
@ -268,4 +270,21 @@ U64 hash64( const U8 *k, U32 length, U64 initval )
|
|||
return c;
|
||||
}
|
||||
|
||||
// Generate a single 64bit hash from the input string.
|
||||
//
|
||||
// Don't get paranoid! This has 1 in 18446744073709551616
|
||||
// chance for collision... it won't happen in this lifetime.
|
||||
//
|
||||
String getStringHash64(const String& in)
|
||||
{
|
||||
String cacheKey = in;
|
||||
cacheKey.replace("\n", " ");
|
||||
U64 hash = hash64((const U8*)cacheKey.c_str(), cacheKey.length(), 0);
|
||||
hash = convertHostToLEndian(hash);
|
||||
U32 high = (U32)(hash >> 32);
|
||||
U32 low = (U32)(hash & 0x00000000FFFFFFFF);
|
||||
cacheKey = String::ToString("%x%x", high, low);
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ extern U32 hash(const U8 *k, U32 length, U32 initval);
|
|||
|
||||
extern U64 hash64(const U8 *k, U32 length, U64 initval);
|
||||
|
||||
extern String getStringHash64(const String& in);
|
||||
|
||||
}
|
||||
|
||||
#endif // _HASHFUNCTION_H_
|
||||
|
|
|
|||
|
|
@ -681,6 +681,24 @@ bool GFXD3D11Shader::_init()
|
|||
return true;
|
||||
}
|
||||
|
||||
static String buildMacroHash(const D3D_SHADER_MACRO* defines)
|
||||
{
|
||||
String combined;
|
||||
|
||||
if (!defines)
|
||||
return "";
|
||||
|
||||
for (const D3D_SHADER_MACRO* m = defines; m->Name != nullptr; ++m)
|
||||
{
|
||||
combined += m->Name;
|
||||
combined += "=";
|
||||
combined += m->Definition ? m->Definition : "";
|
||||
combined += ";";
|
||||
}
|
||||
|
||||
return Torque::getStringHash64(combined);
|
||||
}
|
||||
|
||||
bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath,
|
||||
GFXShaderStage shaderStage,
|
||||
const D3D_SHADER_MACRO *defines)
|
||||
|
|
@ -706,8 +724,40 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath,
|
|||
Con::printf( "Compiling Shader: '%s'", filePath.getFullPath().c_str() );
|
||||
#endif
|
||||
|
||||
String macroHash = buildMacroHash(defines);
|
||||
|
||||
Torque::Path cachePath = filePath;
|
||||
cachePath.setExtension("tso");
|
||||
cachePath.setFileName(cachePath.getFileName() + "_" + macroHash);
|
||||
|
||||
if (Torque::FS::IsFile(cachePath))
|
||||
{
|
||||
Torque::FS::FileNodeRef rawFile = Torque::FS::GetFileNode(filePath);
|
||||
Torque::FS::FileNodeRef cachedFile = Torque::FS::GetFileNode(cachePath);
|
||||
|
||||
if (rawFile != NULL && cachedFile != NULL)
|
||||
{
|
||||
if (cachedFile->getModifiedTime() >= rawFile->getModifiedTime())
|
||||
{
|
||||
|
||||
FileStream fs;
|
||||
if (fs.open(cachePath, Torque::FS::File::Read))
|
||||
{
|
||||
U32 size = fs.getStreamSize();
|
||||
|
||||
D3DCreateBlob(size, &code);
|
||||
fs.read(size, code->GetBufferPointer());
|
||||
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool loadedFromCache = (code != NULL);
|
||||
|
||||
// Is it an HLSL shader?
|
||||
if(filePath.getExtension().equal("hlsl", String::NoCase))
|
||||
if(filePath.getExtension().equal("hlsl", String::NoCase) && !loadedFromCache)
|
||||
{
|
||||
// Set this so that the D3DInclude::Open will have this
|
||||
// information for relative paths.
|
||||
|
|
@ -788,6 +838,20 @@ bool GFXD3D11Shader::_compileShader( const Torque::Path &filePath,
|
|||
|
||||
AssertISV(SUCCEEDED(res), "Unable to compile shader!");
|
||||
|
||||
// succeeded write out a cache
|
||||
if (!loadedFromCache)
|
||||
{
|
||||
if (SUCCEEDED(res) && code)
|
||||
{
|
||||
// Save cache
|
||||
FileStream out(FileStream::AsyncMode::Background);
|
||||
if (out.open(cachePath, Torque::FS::File::Write))
|
||||
{
|
||||
out.write(code->GetBufferSize(), code->GetBufferPointer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(code != NULL)
|
||||
{
|
||||
switch (shaderStage)
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ ShaderData::ShaderData()
|
|||
mOGLVertexShaderName = StringTable->EmptyString();
|
||||
mOGLPixelShaderName = StringTable->EmptyString();
|
||||
mOGLGeometryShaderName = StringTable->EmptyString();
|
||||
|
||||
mInstancingFormat = NULL;
|
||||
}
|
||||
|
||||
void ShaderData::initPersistFields()
|
||||
|
|
@ -204,7 +206,7 @@ const Vector<GFXShaderMacro>& ShaderData::_getMacros()
|
|||
return mShaderMacros;
|
||||
}
|
||||
|
||||
GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> ¯os )
|
||||
GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> ¯os)
|
||||
{
|
||||
PROFILE_SCOPE( ShaderData_GetShader );
|
||||
|
||||
|
|
@ -217,6 +219,8 @@ GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> ¯os )
|
|||
String cacheKey;
|
||||
GFXShaderMacro::stringize( macros, &cacheKey );
|
||||
|
||||
cacheKey = Torque::getStringHash64(cacheKey);
|
||||
|
||||
// Lookup the shader for this instance.
|
||||
ShaderCache::Iterator iter = mShaders.find( cacheKey );
|
||||
if ( iter != mShaders.end() )
|
||||
|
|
@ -224,7 +228,7 @@ GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> ¯os )
|
|||
|
||||
// Create the shader instance... if it fails then
|
||||
// bail out and return nothing to the caller.
|
||||
GFXShader *shader = _createShader( finalMacros );
|
||||
GFXShader *shader = _createShader( finalMacros);
|
||||
if ( !shader )
|
||||
return NULL;
|
||||
|
||||
|
|
@ -235,7 +239,7 @@ GFXShader* ShaderData::getShader( const Vector<GFXShaderMacro> ¯os )
|
|||
return shader;
|
||||
}
|
||||
|
||||
GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os )
|
||||
GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os)
|
||||
{
|
||||
F32 pixver = mPixVersion;
|
||||
if ( mUseDevicePixVersion )
|
||||
|
|
@ -257,30 +261,32 @@ GFXShader* ShaderData::_createShader( const Vector<GFXShaderMacro> ¯os )
|
|||
{
|
||||
case Direct3D11:
|
||||
{
|
||||
if (mDXVertexShaderName != String::EmptyString)
|
||||
if (mDXVertexShaderName != StringTable->EmptyString())
|
||||
shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mDXVertexShaderName);
|
||||
if (mDXPixelShaderName != String::EmptyString)
|
||||
if (mDXPixelShaderName != StringTable->EmptyString())
|
||||
shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mDXPixelShaderName);
|
||||
if (mDXGeometryShaderName != String::EmptyString)
|
||||
if (mDXGeometryShaderName != StringTable->EmptyString())
|
||||
shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mDXGeometryShaderName);
|
||||
success = shader->init( pixver,
|
||||
macros,
|
||||
samplers);
|
||||
samplers,
|
||||
mInstancingFormat);
|
||||
break;
|
||||
}
|
||||
|
||||
case OpenGL:
|
||||
{
|
||||
if(mOGLVertexShaderName != String::EmptyString)
|
||||
if(mOGLVertexShaderName != StringTable->EmptyString())
|
||||
shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, mOGLVertexShaderName);
|
||||
if (mOGLPixelShaderName != String::EmptyString)
|
||||
if (mOGLPixelShaderName != StringTable->EmptyString())
|
||||
shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, mOGLPixelShaderName);
|
||||
if (mOGLGeometryShaderName != String::EmptyString)
|
||||
if (mOGLGeometryShaderName != StringTable->EmptyString())
|
||||
shader->setShaderStageFile(GFXShaderStage::GEOMETRY_SHADER, mOGLGeometryShaderName);
|
||||
|
||||
success = shader->init( pixver,
|
||||
macros,
|
||||
samplers);
|
||||
samplers,
|
||||
mInstancingFormat);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -348,6 +354,33 @@ void ShaderData::_onLMActivate( const char *lm, bool activate )
|
|||
reloadAllShaders();
|
||||
}
|
||||
|
||||
void ShaderData::setShaderStageFile(GFXShaderStage stage, String fileName)
|
||||
{
|
||||
const bool isGL = GFX->getAdapterType() == GFXAdapterType::OpenGL;
|
||||
switch (stage)
|
||||
{
|
||||
case VERTEX_SHADER:
|
||||
isGL ? mOGLVertexShaderName = StringTable->insert(fileName) : mDXVertexShaderName = StringTable->insert(fileName);
|
||||
break;
|
||||
case PIXEL_SHADER:
|
||||
isGL ? mOGLPixelShaderName = StringTable->insert(fileName) : mDXPixelShaderName = StringTable->insert(fileName);
|
||||
break;
|
||||
case GEOMETRY_SHADER:
|
||||
isGL ? mOGLGeometryShaderName = StringTable->insert(fileName) : mDXGeometryShaderName = StringTable->insert(fileName);
|
||||
break;
|
||||
case DOMAIN_SHADER:
|
||||
break;
|
||||
case HULL_SHADER:
|
||||
break;
|
||||
case COMPUTE_SHADER:
|
||||
break;
|
||||
case ALL_STAGES:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderData::hasSamplerDef(const String &_samplerName, int &pos) const
|
||||
{
|
||||
String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName;
|
||||
|
|
|
|||
|
|
@ -80,10 +80,8 @@ protected:
|
|||
/// them if the content has changed.
|
||||
const Vector<GFXShaderMacro>& _getMacros();
|
||||
|
||||
/// Helper for converting an array of macros
|
||||
/// into a formatted string.
|
||||
void _stringizeMacros(const Vector<GFXShaderMacro>& macros,
|
||||
String* outString);
|
||||
// the instancing format.
|
||||
GFXVertexFormat* mInstancingFormat;
|
||||
|
||||
/// Creates a new shader returning NULL on error.
|
||||
GFXShader* _createShader(const Vector<GFXShaderMacro>& macros);
|
||||
|
|
@ -106,8 +104,11 @@ public:
|
|||
void setSamplerName(const String& name, int idx) { mSamplerNames[idx] = name; }
|
||||
String getSamplerName(int idx) const { return mSamplerNames[idx]; }
|
||||
|
||||
void setShaderStageFile(GFXShaderStage stage, String fileName);
|
||||
|
||||
bool hasSamplerDef(const String& samplerName, int& pos) const;
|
||||
bool hasRTParamsDef(const int pos) const { return mRTParams[pos]; }
|
||||
void setInstancingFormat(GFXVertexFormat* instancingFormat) { mInstancingFormat = instancingFormat; }
|
||||
|
||||
ShaderData();
|
||||
|
||||
|
|
@ -122,6 +123,7 @@ public:
|
|||
/// all loaded ShaderData objects in the system.
|
||||
static void reloadAllShaders();
|
||||
|
||||
void setPixVersion(F32 pixVersion) { mPixVersion = pixVersion; }
|
||||
/// Returns the required pixel shader version for this shader.
|
||||
F32 getPixVersion() const { return mPixVersion; }
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override { return "Accu Scale"; }
|
||||
};
|
||||
|
||||
|
|
@ -118,6 +120,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override { return "Accu Direction"; }
|
||||
};
|
||||
|
||||
|
|
@ -138,6 +142,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override { return "Accu Strength"; }
|
||||
};
|
||||
|
||||
|
|
@ -158,6 +164,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override { return "Accu Coverage"; }
|
||||
};
|
||||
|
||||
|
|
@ -179,7 +187,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override { return "Accu Specular"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,5 +37,7 @@ public:
|
|||
void processPix(Vector<ShaderComponent*>& componentList,
|
||||
const MaterialFeatureData& fd) override;
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override { return "Debug Viz"; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ public:
|
|||
|
||||
void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
U32 getOutputTargets( const MaterialFeatureData &fd ) const override { return mOutputTargetMask; }
|
||||
};
|
||||
|
|
@ -306,6 +308,7 @@ class DiffuseFeatureHLSL : public ShaderFeatureHLSL
|
|||
public:
|
||||
void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
Material::BlendOp getBlendOp() override{ return Material::None; }
|
||||
|
||||
|
|
@ -540,6 +543,8 @@ public:
|
|||
void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
Material::BlendOp getBlendOp() override { return Material::None; }
|
||||
|
||||
String getName() override
|
||||
|
|
@ -558,6 +563,9 @@ public:
|
|||
|
||||
void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
|
||||
U32 getShaderStages() override { return ( GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
String getName() override
|
||||
{
|
||||
return "Glow Mask";
|
||||
|
|
@ -582,6 +590,8 @@ public:
|
|||
void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
Material::BlendOp getBlendOp() override { return Material::None; }
|
||||
|
||||
String getName() override { return "HDR Output"; }
|
||||
|
|
@ -626,6 +636,8 @@ public:
|
|||
void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::VERTEX_SHADER); }
|
||||
|
||||
String getName() override
|
||||
{
|
||||
return "Particle Normal Generation Feature";
|
||||
|
|
@ -672,6 +684,8 @@ public:
|
|||
void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd ) override;
|
||||
|
||||
U32 getShaderStages() override { return (GFXShaderStage::VERTEX_SHADER); }
|
||||
|
||||
String getName() override { return "Hardware Skinning"; }
|
||||
};
|
||||
|
||||
|
|
|
|||
533
Engine/source/shaderGen/NODE/shaderGenNodes.cpp
Normal file
533
Engine/source/shaderGen/NODE/shaderGenNodes.cpp
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
#include "platform/platform.h"
|
||||
#include "shaderGen/shaderGen.h"
|
||||
|
||||
#include "shaderGen/NODE/shaderGenNodes.h"
|
||||
#include "shaderGen/langElement.h"
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#include "shaderGen/shaderGenVars.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "materials/matInstance.h"
|
||||
#include "materials/processedMaterial.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
#include "core/util/autoPtr.h"
|
||||
|
||||
#include "core/module.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
|
||||
|
||||
ImplementFeatureType(SNF_VertexPosition, U32(-1), -1, false);
|
||||
ImplementFeatureType(SNF_DefaultTexCoord, U32(-1), -1, false);
|
||||
ImplementFeatureType(SNF_TextureFeature, U32(-1), -1, false);
|
||||
ImplementFeatureType(SNF_NormalMapFeature, U32(-1), -1, false);
|
||||
|
||||
ImplementEnumType(ShaderNodeFeature_enum, "Shader node features. Each of thes relates to a specific node for generating a shader.\n\n")
|
||||
{ ShaderNodeFeature_enum::eSNF_VertexPosition, "SNF_VertexPosition", "Setup vertex position." },
|
||||
{ ShaderNodeFeature_enum::eSNF_DefaultTexCoord, "SNF_DefaultTexCoord", "Setup the default texcoord." },
|
||||
{ ShaderNodeFeature_enum::eSNF_TextureFeature, "SNF_TextureFeature", "Sample a Texture - Params: (string,string,GFXSamplerStateData,bool)." },
|
||||
{ ShaderNodeFeature_enum::eSNF_NormalMapFeature,"SNF_NormalMapFeature", "Convert a texture to a normalmap - Params: (string,float,bool,bool)." },
|
||||
EndImplementEnumType;
|
||||
|
||||
namespace
|
||||
{
|
||||
void register_node_features(GFXAdapterType type)
|
||||
{
|
||||
FEATUREMGR->registerFeature(SNF_VertexPosition, new NodeVertexPositionFeature);
|
||||
FEATUREMGR->registerFeature(SNF_DefaultTexCoord, new DefaultTexcoordFeature);
|
||||
FEATUREMGR->registerFeature(SNF_TextureFeature, new TextureFeature, TextureFeature::createFunction);
|
||||
FEATUREMGR->registerFeature(SNF_NormalMapFeature, new NormalMapFeature, NormalMapFeature::createFunction);
|
||||
|
||||
REGISTER_FEATURE_PARAMS(SNF_TextureFeature, TextureFeatureParams);
|
||||
REGISTER_FEATURE_PARAMS(SNF_NormalMapFeature, NormalMapFeatureParams);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MODULE_BEGIN(ShaderGenNodes)
|
||||
|
||||
MODULE_INIT_AFTER(ShaderGen)
|
||||
MODULE_INIT_AFTER(ShaderGenFeatureMgr)
|
||||
|
||||
MODULE_INIT
|
||||
{
|
||||
SHADERGEN->getFeatureInitSignal().notify(®ister_node_features);
|
||||
}
|
||||
|
||||
MODULE_END;
|
||||
|
||||
Var* ShaderFeatureNode::getObjTrans(Vector<ShaderComponent*>& componentList,
|
||||
bool useInstancing,
|
||||
MultiLine* meta)
|
||||
{
|
||||
Var* objTrans = (Var*)LangElement::find("objTrans");
|
||||
if (objTrans)
|
||||
return objTrans;
|
||||
|
||||
if (useInstancing)
|
||||
{
|
||||
ShaderConnector* vertStruct = dynamic_cast<ShaderConnector*>(componentList[C_VERT_STRUCT]);
|
||||
Var* instObjTrans = vertStruct->getElement(RT_TEXCOORD, 4, 4);
|
||||
instObjTrans->setStructName("IN");
|
||||
instObjTrans->setName("inst_objectTrans");
|
||||
|
||||
mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 0);
|
||||
mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 1);
|
||||
mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 2);
|
||||
mInstancingFormat->addElement("objTrans", GFXDeclType_Float4, instObjTrans->constNum + 3);
|
||||
|
||||
objTrans = new Var;
|
||||
objTrans->setType(GFXSCT_Float4x4);
|
||||
objTrans->setName("objTrans");
|
||||
|
||||
Vector<LangElement*> matrixVars;
|
||||
matrixVars.push_back(instObjTrans);
|
||||
meta->addStatement(new GenOp(" @ = @;", new DecOp(objTrans), new MatrixInitializeOp(objTrans, matrixVars)));
|
||||
}
|
||||
else
|
||||
{
|
||||
objTrans = new Var;
|
||||
objTrans->setType(GFXSCT_Float4x4);
|
||||
objTrans->setName("objTrans");
|
||||
objTrans->uniform = true;
|
||||
objTrans->constSortPos = cspPrimitive;
|
||||
}
|
||||
|
||||
return objTrans;
|
||||
}
|
||||
|
||||
Var* ShaderFeatureNode::getModelView( Vector<ShaderComponent*>& componentList,
|
||||
bool useInstancing,
|
||||
MultiLine* meta)
|
||||
{
|
||||
Var* modelview = (Var*)LangElement::find("modelview");
|
||||
if (modelview)
|
||||
return modelview;
|
||||
|
||||
if (useInstancing)
|
||||
{
|
||||
Var* objTrans = getObjTrans(componentList, useInstancing, meta);
|
||||
|
||||
Var* viewProj = (Var*)LangElement::find("viewProj");
|
||||
if (!viewProj)
|
||||
{
|
||||
viewProj = new Var;
|
||||
viewProj->setType(GFXSCT_Float4x4);
|
||||
viewProj->setName("viewProj");
|
||||
viewProj->uniform = true;
|
||||
viewProj->constSortPos = cspPass;
|
||||
}
|
||||
|
||||
modelview = new Var;
|
||||
modelview->setType(GFXSCT_Float4x4);
|
||||
modelview->setName("modelview");
|
||||
meta->addStatement(new GenOp(" @ = @; // Instancing!\r\n", new DecOp(modelview), new MatrixMultiplyOp(viewProj, objTrans)));
|
||||
}
|
||||
else
|
||||
{
|
||||
modelview = new Var;
|
||||
modelview->setType(GFXSCT_Float4x4);
|
||||
modelview->setName("modelview");
|
||||
modelview->uniform = true;
|
||||
modelview->constSortPos = cspPrimitive;
|
||||
}
|
||||
|
||||
return modelview;
|
||||
}
|
||||
|
||||
Var* ShaderFeatureNode::getWorldView( Vector<ShaderComponent*>& componentList,
|
||||
bool useInstancing,
|
||||
MultiLine* meta)
|
||||
{
|
||||
Var* worldView = (Var*)LangElement::find("worldViewOnly");
|
||||
if (worldView)
|
||||
return worldView;
|
||||
|
||||
if (useInstancing)
|
||||
{
|
||||
Var* objTrans = getObjTrans(componentList, useInstancing, meta);
|
||||
|
||||
Var* worldToCamera = (Var*)LangElement::find("worldToCamera");
|
||||
if (!worldToCamera)
|
||||
{
|
||||
worldToCamera = new Var;
|
||||
worldToCamera->setType(GFXSCT_Float4x4);
|
||||
worldToCamera->setName("worldToCamera");
|
||||
worldToCamera->uniform = true;
|
||||
worldToCamera->constSortPos = cspPass;
|
||||
}
|
||||
|
||||
worldView = new Var;
|
||||
worldView->setType(GFXSCT_Float4x4);
|
||||
worldView->setName("worldViewOnly");
|
||||
|
||||
meta->addStatement(new GenOp(" @ = @; // Instancing!\r\n", new DecOp(worldView), new MatrixMultiplyOp(worldToCamera, objTrans) ));
|
||||
}
|
||||
else
|
||||
{
|
||||
worldView = new Var;
|
||||
worldView->setType(GFXSCT_Float4x4);
|
||||
worldView->setName("worldViewOnly");
|
||||
worldView->uniform = true;
|
||||
worldView->constSortPos = cspPrimitive;
|
||||
}
|
||||
|
||||
return worldView;
|
||||
}
|
||||
|
||||
void ShaderFeatureNode::setupTextureSample( const String& samplerName,
|
||||
GFXShaderConstType samplerType,
|
||||
Vector<ShaderComponent*>& componentList,
|
||||
MultiLine* meta,
|
||||
LangElement* texCoord,
|
||||
LangElement* compareValue,
|
||||
bool useGather)
|
||||
{
|
||||
const bool isGL = (GFX->getAdapterType() == OpenGL);
|
||||
const bool isComparison = (compareValue != NULL);
|
||||
|
||||
// ---- Create or find texture/sampler vars ----
|
||||
String texVarName = samplerName + "_tex";
|
||||
String sampVarName = samplerName;
|
||||
String resultVarName = samplerName + "_col";
|
||||
|
||||
|
||||
Var* samplerVar = dynamic_cast<Var*>(LangElement::find(sampVarName));
|
||||
Var* textureVar = NULL;
|
||||
|
||||
// The sampled color variable (e.g. "samplerName_col") should always be new but just in case
|
||||
Var* sampledColor = (Var*)LangElement::find(resultVarName);
|
||||
if (!sampledColor)
|
||||
{
|
||||
sampledColor->setType(GFXSCT_Float4);
|
||||
sampledColor->setName(resultVarName); // The result var will be named like the sampler
|
||||
meta->addStatement(new GenOp(" @", new DecOp(sampledColor)));
|
||||
}
|
||||
else
|
||||
{
|
||||
meta->addStatement(new GenOp(" @",sampledColor));
|
||||
}
|
||||
|
||||
if (isGL)
|
||||
{
|
||||
// ---------------- GLSL Sampling ----------------
|
||||
if (!samplerVar)
|
||||
{
|
||||
samplerVar = new Var;
|
||||
samplerVar->setType(LangElement::constTypeToString(samplerType, true));
|
||||
samplerVar->setName(sampVarName);
|
||||
samplerVar->uniform = true;
|
||||
samplerVar->sampler = true;
|
||||
samplerVar->constNum = Var::getTexUnitNum();
|
||||
}
|
||||
|
||||
if (isComparison)
|
||||
{
|
||||
if (useGather)
|
||||
meta->addStatement(new GenOp(
|
||||
" = textureGather(@, @, @);\r\n",
|
||||
samplerVar, texCoord, compareValue));
|
||||
else
|
||||
meta->addStatement(new GenOp(
|
||||
" = texture(@, @, @);\r\n",
|
||||
samplerVar, texCoord, compareValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (useGather)
|
||||
meta->addStatement(new GenOp(
|
||||
" = textureGather(@, @);\r\n",
|
||||
samplerVar, texCoord));
|
||||
else
|
||||
meta->addStatement(new GenOp(
|
||||
" = texture(@, @);\r\n",
|
||||
samplerVar, texCoord));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ---------------- HLSL Sampling ----------------
|
||||
if (!samplerVar)
|
||||
{
|
||||
samplerVar = new Var;
|
||||
samplerVar->setType(isComparison ? "SamplerComparisonState" : "SamplerState");
|
||||
samplerVar->setName(sampVarName);
|
||||
samplerVar->uniform = true;
|
||||
samplerVar->sampler = true;
|
||||
samplerVar->constNum = Var::getTexUnitNum();
|
||||
}
|
||||
|
||||
textureVar = dynamic_cast<Var*>(LangElement::find(texVarName));
|
||||
if (!textureVar)
|
||||
{
|
||||
textureVar = new Var;
|
||||
textureVar->setType(LangElement::constTypeToString(samplerType, true)); // Texture2D, TextureCube, etc.
|
||||
textureVar->setName(texVarName);
|
||||
textureVar->uniform = true;
|
||||
textureVar->texture = true;
|
||||
textureVar->constNum = samplerVar->constNum;
|
||||
}
|
||||
|
||||
if (isComparison)
|
||||
{
|
||||
if (useGather)
|
||||
meta->addStatement(new GenOp(
|
||||
" = @.SampleCmpGather(@, @, @);\r\n",
|
||||
textureVar, samplerVar, texCoord, compareValue));
|
||||
else
|
||||
meta->addStatement(new GenOp(
|
||||
" = @.SampleCmp(@, @, @);\r\n",
|
||||
textureVar, samplerVar, texCoord, compareValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (useGather)
|
||||
meta->addStatement(new GenOp(
|
||||
" = @.Gather(@, @);\r\n",
|
||||
textureVar, samplerVar, texCoord));
|
||||
else
|
||||
meta->addStatement(new GenOp(
|
||||
" = @.Sample(@, @);\r\n",
|
||||
textureVar, samplerVar, texCoord));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Var* ShaderFeatureNode::getOutTexCoord(const char* name, GFXShaderConstType type, bool useTexAnim, MultiLine* meta, Vector<ShaderComponent*>& componentList)
|
||||
{
|
||||
String outTexName = String::ToString("out_%s", name);
|
||||
Var* texCoord = (Var*)LangElement::find(outTexName);
|
||||
if (!texCoord)
|
||||
{
|
||||
Var* inTex = getVertTexCoord(name);
|
||||
AssertFatal(inTex, "ShaderFeatureNode::getOutTexCoord - Unknown vertex input coord!");
|
||||
|
||||
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
|
||||
|
||||
texCoord = connectComp->getElement(RT_TEXCOORD);
|
||||
texCoord->setName(outTexName);
|
||||
texCoord->setStructName("OUT");
|
||||
texCoord->setType(type);
|
||||
|
||||
// Statement allows for casting of different types which
|
||||
// eliminates vector truncation problems.
|
||||
meta->addStatement(new GenOp(" @ = (@)@;\r\n", texCoord, new TypeOp(type), inTex));
|
||||
|
||||
}
|
||||
|
||||
return texCoord;
|
||||
}
|
||||
|
||||
LangElement* ShaderFeatureNode::setupTexSpaceMat(Vector<ShaderComponent*>& componentList, Var** texSpaceMat)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LangElement* ShaderFeatureNode::assignColor(LangElement* elem, Material::BlendOp blend, LangElement* lerpElem, ShaderFeature::OutputTarget outputTarget)
|
||||
{
|
||||
// search for color var
|
||||
Var* color = (Var*)LangElement::find(getOutputTargetVarName(outputTarget));
|
||||
|
||||
if (!color)
|
||||
{
|
||||
// create color var
|
||||
color = new Var;
|
||||
color->setType("fragout");
|
||||
color->setName(getOutputTargetVarName(outputTarget));
|
||||
color->setStructName("OUT");
|
||||
|
||||
return new GenOp("@ = @", color, elem);
|
||||
}
|
||||
|
||||
switch (blend)
|
||||
{
|
||||
case Material::Add:
|
||||
return new GenOp("@ += @", color, elem);
|
||||
break;
|
||||
|
||||
case Material::Sub:
|
||||
return new GenOp("@ -= @", color, elem);
|
||||
break;
|
||||
|
||||
case Material::Mul:
|
||||
return new GenOp("@ *= @", color, elem);
|
||||
break;
|
||||
|
||||
case Material::PreMul:
|
||||
return new GenOp("@.rgb = @.rgb + (@.rgb*(1.0-@.a))", color, elem, color, elem);
|
||||
break;
|
||||
|
||||
case Material::AddAlpha:
|
||||
return new GenOp("@ += @ * @.a", color, elem, elem);
|
||||
break;
|
||||
|
||||
case Material::LerpAlpha:
|
||||
if (!lerpElem)
|
||||
lerpElem = elem;
|
||||
return new GenOp("@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem);
|
||||
break;
|
||||
|
||||
case Material::ToneMap:
|
||||
return new GenOp("@ = 1.0 - exp(-1.0 * @ * @)", color, color, elem);
|
||||
break;
|
||||
|
||||
case Material::None:
|
||||
return new GenOp("@ = @", color, elem);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Unrecognized color blendOp");
|
||||
// Fallthru
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Vertex position.
|
||||
//--------------------------------------------------------
|
||||
|
||||
void NodeVertexPositionFeature::processVert(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
|
||||
{
|
||||
// First check for an input position from a previous feature
|
||||
// then look for the default vertex position.
|
||||
Var* inPosition = (Var*)LangElement::find("inPosition");
|
||||
if (!inPosition)
|
||||
inPosition = (Var*)LangElement::find("position");
|
||||
|
||||
const bool glsl = (GFX->getAdapterType() == OpenGL);
|
||||
|
||||
// grab connector position
|
||||
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
|
||||
Var* outPosition = connectComp->getElement( glsl ? RT_POSITION : RT_SVPOSITION);
|
||||
|
||||
if (glsl)
|
||||
{
|
||||
outPosition->setName("gl_Position");
|
||||
}
|
||||
else
|
||||
{
|
||||
outPosition->setName("hpos");
|
||||
outPosition->setStructName("OUT");
|
||||
}
|
||||
|
||||
MultiLine* meta = new MultiLine;
|
||||
|
||||
Var* modelview = getModelView(componentList, fd.features[MFT_UseInstancing], meta);
|
||||
|
||||
meta->addStatement(new GenOp(" @ = @;\r\n", outPosition, new MatrixMultiplyOp( modelview, new CastOp(inPosition, GFXSCT_Float4, "x;y;z"))));
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
void NodeVertexPositionFeature::processPix(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
|
||||
{
|
||||
const bool glsl = (GFX->getAdapterType() == OpenGL);
|
||||
|
||||
if (!glsl)
|
||||
{
|
||||
// grab connector position
|
||||
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
|
||||
Var* outPosition = connectComp->getElement(RT_SVPOSITION);
|
||||
outPosition->setName("vpos");
|
||||
outPosition->setStructName("IN");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// Setup the default texcoord
|
||||
//--------------------------------------------------------
|
||||
|
||||
void DefaultTexcoordFeature::processVert(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
|
||||
{
|
||||
MultiLine* meta = new MultiLine;
|
||||
getOutTexCoord("texCoord",
|
||||
GFXSCT_Float2,
|
||||
fd.features[MFT_TexAnim],
|
||||
meta,
|
||||
componentList);
|
||||
output = meta;
|
||||
}
|
||||
|
||||
void DefaultTexcoordFeature::processPix(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
|
||||
{
|
||||
// grab connector texcoord register
|
||||
Var* inTex = getInTexCoord("texCoord", GFXSCT_Float2, componentList);
|
||||
if (!inTex)
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// TEXTURE SAMPLER FEATURE
|
||||
//--------------------------------------------------------
|
||||
|
||||
void TextureFeature::processPix(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
|
||||
{
|
||||
// find the uv var.
|
||||
Var* inTex = getInTexCoord(params->uvName, GFXSCT_Float2, componentList);
|
||||
if (!inTex)
|
||||
return;
|
||||
|
||||
MultiLine* meta = new MultiLine;
|
||||
|
||||
// Sample texture
|
||||
setupTextureSample(
|
||||
params->samplerName, // name of the output variable.
|
||||
params->samplerType, // or GFXSCT_SamplerCube, etc.
|
||||
componentList,
|
||||
meta,
|
||||
inTex,
|
||||
NULL, // compareValue (for SampleCmp)
|
||||
params->useGather // enable gather if desired
|
||||
);
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources TextureFeature::getResources(const MaterialFeatureData& fd)
|
||||
{
|
||||
Resources res;
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
// NORMAL MAPPING FEATURE
|
||||
//--------------------------------------------------------
|
||||
|
||||
void NormalMapFeature::processPix(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd)
|
||||
{
|
||||
String colorVarName = params->inputName;
|
||||
Var* sampledColor = (Var*)LangElement::find(colorVarName);
|
||||
|
||||
if (!sampledColor)
|
||||
{
|
||||
Con::warnf("NormalMapFeature: sampler %s not sampled yet!", params->inputName.c_str());
|
||||
return; // TextureFeature must run first
|
||||
}
|
||||
|
||||
|
||||
MultiLine* meta = new MultiLine;
|
||||
|
||||
// TEMP float4 for base decoded normal
|
||||
Var* tempNorm = new Var;
|
||||
tempNorm->setName(params->inputName + "_normTemp");
|
||||
tempNorm->setType(GFXSCT_Float4);
|
||||
LangElement* tempNormDecl = new DecOp(tempNorm);
|
||||
|
||||
// sampledColor is the result of the textureFeature.
|
||||
meta->addStatement(expandNormalMap(sampledColor, tempNormDecl, tempNorm, fd));
|
||||
|
||||
meta->addStatement(
|
||||
new GenOp(" @.xy *= @(@, @);\r\n", tempNorm, new TypeOp(GFXSCT_Float2), params->flipX ? -1.0f : 1.0f, params->flipY ? -1.0f : 1.0f));
|
||||
|
||||
meta->addStatement(new GenOp(" @.xyz = normalize( @( @.xy * @, @.z ) );\r\n",
|
||||
tempNorm, new TypeOp(GFXSCT_Float3), tempNorm, params->strength, tempNorm));
|
||||
|
||||
// write back into our known variable.
|
||||
meta->addStatement(new GenOp(" @ = @;\r\n", sampledColor, tempNorm));
|
||||
|
||||
output = meta;
|
||||
|
||||
}
|
||||
|
||||
241
Engine/source/shaderGen/NODE/shaderGenNodes.h
Normal file
241
Engine/source/shaderGen/NODE/shaderGenNodes.h
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef _SHADERFEATURE_H_
|
||||
#include "shaderGen/shaderFeature.h"
|
||||
#endif
|
||||
|
||||
#ifndef _FEATUREMGR_H_
|
||||
#include "shaderGen/featureMgr.h"
|
||||
#endif
|
||||
|
||||
#ifndef _FEATURETYPE_H_
|
||||
#include "shaderGen/featureType.h"
|
||||
#endif
|
||||
|
||||
#ifndef __GFXSTATEBLOCKDATA_H_
|
||||
#include "gfx/sim/gfxStateBlockData.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXAPI_H_
|
||||
#include "gfx/gfxAPI.h"
|
||||
#endif
|
||||
|
||||
DeclareFeatureType(SNF_VertexPosition);
|
||||
DeclareFeatureType(SNF_DefaultTexCoord);
|
||||
DeclareFeatureType(SNF_TextureFeature);
|
||||
DeclareFeatureType(SNF_NormalMapFeature);
|
||||
|
||||
/// <summary>
|
||||
/// This enum is so we can map to nodes in script.
|
||||
/// </summary>
|
||||
enum ShaderNodeFeature_enum
|
||||
{
|
||||
eSNF_VertexPosition,
|
||||
eSNF_DefaultTexCoord,
|
||||
eSNF_TextureFeature,
|
||||
eSNF_NormalMapFeature,
|
||||
};
|
||||
|
||||
DefineEnumType(ShaderNodeFeature_enum);
|
||||
|
||||
class ShaderFeatureNode : public ShaderFeature
|
||||
{
|
||||
public:
|
||||
|
||||
///
|
||||
Var* getObjTrans( Vector<ShaderComponent*>& componentList,
|
||||
bool useInstancing,
|
||||
MultiLine* meta);
|
||||
|
||||
Var* getModelView(Vector<ShaderComponent*>& componentList,
|
||||
bool useInstancing,
|
||||
MultiLine* meta);
|
||||
|
||||
Var* getWorldView(Vector<ShaderComponent*>& componentList, bool useInstancing, MultiLine* meta);
|
||||
|
||||
void setupTextureSample(const String& samplerName,
|
||||
GFXShaderConstType samplerType,
|
||||
Vector<ShaderComponent*>& componentList,
|
||||
MultiLine* meta,
|
||||
LangElement* texCoord,
|
||||
LangElement* compareValue,
|
||||
bool useGather);
|
||||
|
||||
Var* getOutTexCoord( const char* name,
|
||||
GFXShaderConstType type,
|
||||
bool useTexAnim,
|
||||
MultiLine* meta,
|
||||
Vector<ShaderComponent*>& componentList);
|
||||
|
||||
LangElement* setupTexSpaceMat(Vector<ShaderComponent*>& componentList, Var** texSpaceMat) override;
|
||||
|
||||
LangElement* assignColor(LangElement* elem, Material::BlendOp blend, LangElement* lerpElem = NULL, ShaderFeature::OutputTarget outputTarget = ShaderFeature::DefaultTarget) override;
|
||||
};
|
||||
|
||||
class NodeVertexPositionFeature : public ShaderFeatureNode
|
||||
{
|
||||
void processVert(Vector<ShaderComponent*>& componentList,
|
||||
const MaterialFeatureData& fd) override;
|
||||
|
||||
void processPix(Vector<ShaderComponent*>& componentList,
|
||||
const MaterialFeatureData& fd) override;
|
||||
|
||||
String getName() override
|
||||
{
|
||||
return "NodeVertexPositionFeature";
|
||||
}
|
||||
};
|
||||
|
||||
class DefaultTexcoordFeature : public ShaderFeatureNode
|
||||
{
|
||||
void processVert(Vector<ShaderComponent*>& componentList,
|
||||
const MaterialFeatureData& fd) override;
|
||||
|
||||
void processPix(Vector<ShaderComponent*>& componentList,
|
||||
const MaterialFeatureData& fd) override;
|
||||
|
||||
String getName() override
|
||||
{
|
||||
return "DefaultTexCoord";
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------
|
||||
// TEXTURE SAMPLER FEATURE
|
||||
//--------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for the TextureFeature
|
||||
/// </summary>
|
||||
struct TextureFeatureParams : public FeatureParamsBase
|
||||
{
|
||||
String samplerName;
|
||||
GFXShaderConstType samplerType;
|
||||
GFXSamplerStateData samplerState;
|
||||
String uvName;
|
||||
bool useGather;
|
||||
|
||||
TextureFeatureParams()
|
||||
{
|
||||
samplerName = "defaultSampler";
|
||||
samplerType = GFXSCT_Sampler;
|
||||
uvName = "texCoord";
|
||||
useGather = false;
|
||||
|
||||
}
|
||||
|
||||
const char* getFeatureParamTypeName() const override { return "TextureFeatureParams"; }
|
||||
|
||||
/// <summary>
|
||||
/// Texture features output variable is samplerName + "_col"
|
||||
/// </summary>
|
||||
/// <returns>The output variable for a texture feature.</returns>
|
||||
const char* getOutputVar() const override { return samplerName + "_col"; }
|
||||
|
||||
static void persistedFields(Vector<FeatureParamField>& fields)
|
||||
{
|
||||
addParam(fields, "sampler", Offset(samplerName, TextureFeatureParams), TypeString);
|
||||
addParam(fields, "samplerType", Offset(samplerType, TextureFeatureParams), TypeGFXShaderConstType);
|
||||
addParam(fields, "samplerState", Offset(samplerState, TextureFeatureParams), TYPEID<GFXSamplerStateData>());
|
||||
addParam(fields, "uvName", Offset(uvName, TextureFeatureParams), TypeString);
|
||||
addParam(fields, "useGather", Offset(useGather, TextureFeatureParams), TypeBool);
|
||||
}
|
||||
};
|
||||
|
||||
class TextureFeature : public ShaderFeatureNode
|
||||
{
|
||||
private:
|
||||
/// Parameters that this feature can use to change the shadergen output.
|
||||
TextureFeatureParams* params;
|
||||
public:
|
||||
/// default constructor
|
||||
TextureFeature()
|
||||
{
|
||||
params = new TextureFeatureParams();
|
||||
}
|
||||
/// Constructor that takes params as an argument
|
||||
TextureFeature(TextureFeatureParams* inParams)
|
||||
{
|
||||
params = inParams;
|
||||
}
|
||||
|
||||
void processPix(Vector<ShaderComponent*>& componentList,
|
||||
const MaterialFeatureData& fd) override;
|
||||
|
||||
ShaderFeature::Resources getResources(const MaterialFeatureData& fd) override;
|
||||
|
||||
// create a static function on the feature class
|
||||
static ShaderFeature* createFunction(FeatureParamsBase* args)
|
||||
{
|
||||
TextureFeatureParams* params = static_cast<TextureFeatureParams*>(args);
|
||||
return new TextureFeature(params);
|
||||
}
|
||||
|
||||
String getName() override
|
||||
{
|
||||
return "TextureSampler_" + params->samplerName + "_" + params->uvName;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------
|
||||
// NORMAL MAPPING FEATURE
|
||||
//--------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for the NormalMapFeature
|
||||
/// </summary>
|
||||
struct NormalMapFeatureParams : public FeatureParamsBase
|
||||
{
|
||||
String inputName; // name of the sampled normal texture (Var* from TextureFeature)
|
||||
F32 strength; // normal strength multiplier
|
||||
bool flipX;
|
||||
bool flipY;
|
||||
|
||||
NormalMapFeatureParams()
|
||||
{
|
||||
inputName = "normalSampler";
|
||||
strength = 1.0f;
|
||||
flipX = false;
|
||||
flipY = false;
|
||||
}
|
||||
|
||||
const char* getFeatureParamTypeName() const override { return "NormalMapFeatureParams"; }
|
||||
|
||||
/// <summary>
|
||||
/// Normal map feature writes the result into the input name
|
||||
/// </summary>
|
||||
/// <returns>The output variable for a normal map feature.</returns>
|
||||
const char* getOutputVar() const override { return inputName; }
|
||||
|
||||
static void persistedFields(Vector<FeatureParamField>& fields)
|
||||
{
|
||||
addParam(fields, "input", Offset(inputName, NormalMapFeatureParams), TypeString);
|
||||
addParam(fields, "strength", Offset(strength, NormalMapFeatureParams), TypeF32);
|
||||
addParam(fields, "flipX", Offset(flipX, NormalMapFeatureParams), TypeBool);
|
||||
addParam(fields, "flipY", Offset(flipY, NormalMapFeatureParams), TypeBool);
|
||||
}
|
||||
};
|
||||
|
||||
class NormalMapFeature : public ShaderFeatureNode
|
||||
{
|
||||
private:
|
||||
NormalMapFeatureParams* params;
|
||||
|
||||
public:
|
||||
NormalMapFeature() { params = new NormalMapFeatureParams(); }
|
||||
NormalMapFeature(NormalMapFeatureParams* p) { params = p; }
|
||||
|
||||
void processPix(Vector<ShaderComponent*>& componentList, const MaterialFeatureData& fd) override;
|
||||
|
||||
// normal map feature does not need any resources as these were created from the texture feature.
|
||||
|
||||
static ShaderFeature* createFunction(FeatureParamsBase* args)
|
||||
{
|
||||
return new NormalMapFeature(static_cast<NormalMapFeatureParams*>(args));
|
||||
}
|
||||
|
||||
String getName() override
|
||||
{
|
||||
return "NormalMap_" + params->inputName;
|
||||
}
|
||||
};
|
||||
|
|
@ -227,7 +227,7 @@ void ConditionerFeature::printFooterComment( MethodType methodType, const String
|
|||
meta->addStatement( new GenOp( "\r\n\r\n" ) );
|
||||
}
|
||||
|
||||
void ConditionerMethodDependency::print( Stream &s ) const
|
||||
void ConditionerMethodDependency::print( Stream &s, GFXShaderStage stage) const
|
||||
{
|
||||
mConditioner->_printMethod(mMethodType, mConditioner->getShaderMethodName(mMethodType), s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,9 +126,11 @@ protected:
|
|||
|
||||
public:
|
||||
ConditionerMethodDependency( ConditionerFeature *conditioner, const ConditionerFeature::MethodType methodType ) :
|
||||
mConditioner(conditioner), mMethodType(methodType) {}
|
||||
mConditioner(conditioner), mMethodType(methodType) {
|
||||
stages = (GFXShaderStage::VERTEX_SHADER | GFXShaderStage::PIXEL_SHADER);
|
||||
}
|
||||
|
||||
void print( Stream &s ) const override;
|
||||
void print( Stream &s, GFXShaderStage stage ) const override;
|
||||
|
||||
// Auto insert information into a macro
|
||||
virtual void createMethodMacro( const String &methodName, Vector<GFXShaderMacro> ¯os );
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ FeatureMgr::FeatureMgr()
|
|||
: mNeedsSort( false )
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION( mFeatures );
|
||||
VECTOR_SET_ASSOCIATION( mParamInfos );
|
||||
}
|
||||
|
||||
FeatureMgr::~FeatureMgr()
|
||||
|
|
@ -96,7 +97,7 @@ ShaderFeature* FeatureMgr::getByType( const FeatureType &type )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ShaderFeature* FeatureMgr::createFeature(const FeatureType& type, void* argStruct)
|
||||
ShaderFeature* FeatureMgr::createFeature(const FeatureType& type, FeatureParamsBase* argStruct)
|
||||
{
|
||||
FeatureInfoVector::iterator iter = mFeatures.begin();
|
||||
|
||||
|
|
@ -114,6 +115,64 @@ ShaderFeature* FeatureMgr::createFeature(const FeatureType& type, void* argStruc
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void FeatureMgr::registerFeatureParams(const FeatureType& type, const FeatureParamField* fields, U32 fieldCount, CreateFeatureParams createFn)
|
||||
{
|
||||
// Replace if already exists
|
||||
for (U32 i = 0; i < mParamInfos.size(); ++i)
|
||||
{
|
||||
if (*mParamInfos[i].type == type)
|
||||
{
|
||||
mParamInfos.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mParamInfos.increment();
|
||||
mParamInfos.last().type = &type;
|
||||
mParamInfos.last().fields = fields;
|
||||
mParamInfos.last().fieldCount = fieldCount;
|
||||
mParamInfos.last().createFn = createFn;
|
||||
|
||||
}
|
||||
|
||||
FeatureParamsBase* FeatureMgr::createFeatureParams(const FeatureType& type) const
|
||||
{
|
||||
for (U32 i = 0; i < mParamInfos.size(); ++i)
|
||||
{
|
||||
if (*mParamInfos[i].type == type)
|
||||
return mParamInfos[i].createFn();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FeatureMgr::applyFeatureParams(const FeatureType& type,
|
||||
FeatureParamsBase* params,
|
||||
const Vector<String>& args) const
|
||||
{
|
||||
const FeatureParamInfo* info = nullptr;
|
||||
for (U32 i = 0; i < mParamInfos.size(); ++i)
|
||||
{
|
||||
if (*mParamInfos[i].type == type)
|
||||
{
|
||||
info = &mParamInfos[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!info || !params)
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < info->fieldCount; ++i)
|
||||
{
|
||||
const FeatureParamField& f = info->fields[i];
|
||||
const char* val = args[i].c_str();
|
||||
|
||||
void* fieldPtr = (U8*)params + f.offset;
|
||||
// no array support yet.
|
||||
Con::setData(f.type, fieldPtr, 0, 1, &val);
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureMgr::registerFeature( const FeatureType &type,
|
||||
ShaderFeature *feature,
|
||||
CreateShaderFeatureDelegate featureDelegate)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,49 @@
|
|||
class FeatureType;
|
||||
class ShaderFeature;
|
||||
|
||||
typedef Delegate<ShaderFeature* (void*)> CreateShaderFeatureDelegate;
|
||||
struct FeatureParamField
|
||||
{
|
||||
StringTableEntry paramName;
|
||||
S32 offset;
|
||||
S32 type;
|
||||
U32 arraySize;
|
||||
};
|
||||
|
||||
inline void addParam(Vector<FeatureParamField>& list,
|
||||
const char* name,
|
||||
S32 offset,
|
||||
S32 consoleType,
|
||||
U32 arraySize = 1)
|
||||
{
|
||||
FeatureParamField f = { name, offset, consoleType, arraySize };
|
||||
list.push_back(f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all shader feature parameter structs.
|
||||
/// </summary>
|
||||
class FeatureParamsBase
|
||||
{
|
||||
public:
|
||||
virtual ~FeatureParamsBase() {}
|
||||
|
||||
virtual const char* getOutputVar() const { return "default"; }
|
||||
// For debug or script reflection, you can override to serialize/print parameters
|
||||
virtual const char* getFeatureParamTypeName() const { return "FeatureParamsBase"; }
|
||||
};
|
||||
|
||||
typedef Delegate<FeatureParamsBase* ()> CreateFeatureParams;
|
||||
|
||||
/// Metadata for a parameter struct type.
|
||||
struct FeatureParamInfo
|
||||
{
|
||||
const FeatureType* type; // Matches feature
|
||||
const FeatureParamField* fields;
|
||||
U32 fieldCount;
|
||||
CreateFeatureParams createFn; // makes a new param struct
|
||||
};
|
||||
|
||||
typedef Delegate<ShaderFeature* (FeatureParamsBase*)> CreateShaderFeatureDelegate;
|
||||
|
||||
/// <summary>
|
||||
/// Used by the feature manager.
|
||||
|
|
@ -60,9 +102,11 @@ protected:
|
|||
bool mNeedsSort;
|
||||
|
||||
typedef Vector<FeatureInfo> FeatureInfoVector;
|
||||
|
||||
FeatureInfoVector mFeatures;
|
||||
|
||||
typedef Vector<FeatureParamInfo> FeatureParamInfoVector;
|
||||
FeatureParamInfoVector mParamInfos;
|
||||
|
||||
static S32 QSORT_CALLBACK _featureInfoCompare( const FeatureInfo *a, const FeatureInfo *b );
|
||||
|
||||
public:
|
||||
|
|
@ -87,7 +131,13 @@ public:
|
|||
/// <returns>An instance of the shader feature using its static createFunction taking in the
|
||||
/// argument struct.
|
||||
/// </returns>
|
||||
ShaderFeature* createFeature(const FeatureType& type, void* argStruct);
|
||||
ShaderFeature* createFeature(const FeatureType& type, FeatureParamsBase* argStruct);
|
||||
|
||||
void registerFeatureParams(const FeatureType& type, const FeatureParamField* fields, U32 fieldCount, CreateFeatureParams createFn);
|
||||
|
||||
FeatureParamsBase* createFeatureParams(const FeatureType& type) const;
|
||||
|
||||
void applyFeatureParams(const FeatureType& type, FeatureParamsBase* params, const Vector<String>& args) const;
|
||||
|
||||
/// <summary>
|
||||
/// Allows other systems to add features. index is
|
||||
|
|
@ -114,4 +164,20 @@ public:
|
|||
// Helper for accessing the feature manager singleton.
|
||||
#define FEATUREMGR ManagedSingleton<FeatureMgr>::instance()
|
||||
|
||||
#define REGISTER_FEATURE_PARAMS(TYPE, STRUCT_TYPE) \
|
||||
struct STRUCT_TYPE##_AutoRegister \
|
||||
{ \
|
||||
STRUCT_TYPE##_AutoRegister() \
|
||||
{ \
|
||||
Vector<FeatureParamField> fieldList; \
|
||||
STRUCT_TYPE::persistedFields(fieldList); \
|
||||
FEATUREMGR->registerFeatureParams( \
|
||||
TYPE, \
|
||||
fieldList.address(), \
|
||||
fieldList.size(), \
|
||||
Delegate<FeatureParamsBase*()>([]() -> FeatureParamsBase* { return new STRUCT_TYPE(); })\
|
||||
); \
|
||||
} \
|
||||
} STRUCT_TYPE##_AutoRegisterInstance;
|
||||
|
||||
#endif // FEATUREMGR
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ const FeatureType& FeatureSet::getAt( U32 index, S32 *outIndex ) const
|
|||
return *mFeatures[index].type;
|
||||
}
|
||||
|
||||
void* FeatureSet::getArguments(U32 index) const
|
||||
FeatureParamsBase* FeatureSet::getArguments(U32 index) const
|
||||
{
|
||||
if (mFeatures[index].argStruct)
|
||||
return mFeatures[index].argStruct;
|
||||
|
|
@ -146,7 +146,7 @@ void FeatureSet::setFeature( const FeatureType &type, bool set, S32 index )
|
|||
mDescription.clear();
|
||||
}
|
||||
|
||||
void FeatureSet::addFeature( const FeatureType &type, S32 index, void* argStruct )
|
||||
void FeatureSet::addFeature( const FeatureType &type, S32 index, FeatureParamsBase* argStruct )
|
||||
{
|
||||
if (!argStruct)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
#ifndef _FEATUREMGR_H_
|
||||
#include "shaderGen/featureMgr.h"
|
||||
#endif
|
||||
|
||||
class FeatureType;
|
||||
|
||||
|
|
@ -42,7 +45,7 @@ protected:
|
|||
{
|
||||
const FeatureType* type;
|
||||
S32 index;
|
||||
void* argStruct;
|
||||
FeatureParamsBase* argStruct;
|
||||
};
|
||||
|
||||
/// The list of featurs.
|
||||
|
|
@ -94,7 +97,7 @@ public:
|
|||
/// the feature index when it was added.
|
||||
const FeatureType& getAt( U32 index, S32 *outIndex = NULL ) const;
|
||||
|
||||
void* getArguments(U32 index) const;
|
||||
FeatureParamsBase* getArguments(U32 index) const;
|
||||
|
||||
/// Returns true if this handle has this feature.
|
||||
bool hasFeature( const FeatureType &type, S32 index = -1 ) const;
|
||||
|
|
@ -108,7 +111,7 @@ public:
|
|||
/// <param name="type">The shader feature type.</param>
|
||||
/// <param name="index">The inedx the shader feature will be sorted in the set.</param>
|
||||
/// <param name="argStruct">A struct representing arguments for a shader feature.</param>
|
||||
void addFeature( const FeatureType &type, S32 index = -1, void* argStruct = nullptr );
|
||||
void addFeature( const FeatureType &type, S32 index = -1, FeatureParamsBase* argStruct = nullptr );
|
||||
|
||||
///
|
||||
void removeFeature( const FeatureType &type );
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "core/strings/stringFunctions.h"
|
||||
#include "core/util/str.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#include "langElement.h"
|
||||
|
||||
//**************************************************************************
|
||||
|
|
@ -30,69 +31,158 @@
|
|||
//**************************************************************************
|
||||
Vector<LangElement*> LangElement::elementList( __FILE__, __LINE__ );
|
||||
|
||||
const char* LangElement::constTypeToString(GFXShaderConstType constType)
|
||||
static const ShaderTypeInfo ShaderTypes[] =
|
||||
{
|
||||
// Determine shader language based on GFXAdapterAPI
|
||||
if (GFX->getAdapterType() == OpenGL)
|
||||
// ---- FLOATS ----
|
||||
{ GFXSCT_Float, "float", "float", STC_Scalar, 1, 1 },
|
||||
{ GFXSCT_Float2, "vec2", "float2", STC_Vector, 1, 2 },
|
||||
{ GFXSCT_Float3, "vec3", "float3", STC_Vector, 1, 3 },
|
||||
{ GFXSCT_Float4, "vec4", "float4", STC_Vector, 1, 4 },
|
||||
|
||||
// ---- MATRICES ----
|
||||
{ GFXSCT_Float2x2, "mat2", "float2x2", STC_Matrix, 2, 2 },
|
||||
{ GFXSCT_Float3x3, "mat3", "float3x3", STC_Matrix, 3, 3 },
|
||||
{ GFXSCT_Float3x4, "mat3x4", "float3x4", STC_Matrix, 3, 4 },
|
||||
{ GFXSCT_Float4x3, "mat4x3", "float4x3", STC_Matrix, 4, 3 },
|
||||
{ GFXSCT_Float4x4, "mat4", "float4x4", STC_Matrix, 4, 4 },
|
||||
|
||||
// ---- INT ----
|
||||
{ GFXSCT_Int, "int", "int", STC_Scalar, 1, 1 },
|
||||
{ GFXSCT_Int2, "ivec2", "int2", STC_Vector, 1, 2 },
|
||||
{ GFXSCT_Int3, "ivec3", "int3", STC_Vector, 1, 3 },
|
||||
{ GFXSCT_Int4, "ivec4", "int4", STC_Vector, 1, 4 },
|
||||
|
||||
// ---- UINT ----
|
||||
{ GFXSCT_UInt, "uint", "uint", STC_Scalar, 1, 1 },
|
||||
{ GFXSCT_UInt2, "uvec2", "uint2", STC_Vector, 1, 2 },
|
||||
{ GFXSCT_UInt3, "uvec3", "uint3", STC_Vector, 1, 3 },
|
||||
{ GFXSCT_UInt4, "uvec4", "uint4", STC_Vector, 1, 4 },
|
||||
|
||||
// ---- BOOL ----
|
||||
{ GFXSCT_Bool, "bool", "bool", STC_Scalar, 1, 1 },
|
||||
{ GFXSCT_Bool2, "bvec2", "bool2", STC_Vector, 1, 2 },
|
||||
{ GFXSCT_Bool3, "bvec3", "bool3", STC_Vector, 1, 3 },
|
||||
{ GFXSCT_Bool4, "bvec4", "bool4", STC_Vector, 1, 4 },
|
||||
|
||||
// ---- SAMPLERS ----
|
||||
{ GFXSCT_Sampler, "sampler2D", "Texture2D", STC_Sampler, 0, 0 },
|
||||
{ GFXSCT_SamplerCube, "samplerCube", "TextureCube", STC_Sampler, 0, 0 },
|
||||
{ GFXSCT_SamplerTextureArray, "sampler2DArray", "Texture2DArray", STC_Sampler, 0, 0 },
|
||||
{ GFXSCT_SamplerCubeArray, "samplerCubeArray", "TextureCubeArray", STC_Sampler, 0, 0 },
|
||||
};
|
||||
|
||||
static HashMap<String, GFXShaderConstType> glslToType;
|
||||
static HashMap<String, GFXShaderConstType> hlslToType;
|
||||
|
||||
void LangElement::buildTypeMaps()
|
||||
{
|
||||
for (auto& info : ShaderTypes)
|
||||
{
|
||||
switch (constType)
|
||||
{
|
||||
case GFXSCT_Float: return "float"; break;
|
||||
case GFXSCT_Float2: return "vec2"; break;
|
||||
case GFXSCT_Float3: return "vec3"; break;
|
||||
case GFXSCT_Float4: return "vec4"; break;
|
||||
case GFXSCT_Float2x2: return "mat2"; break;
|
||||
case GFXSCT_Float3x3: return "mat3"; break;
|
||||
case GFXSCT_Float3x4: return "mat3x4"; break;
|
||||
case GFXSCT_Float4x3: return "mat4x3"; break;
|
||||
case GFXSCT_Float4x4: return "mat4"; break;
|
||||
case GFXSCT_Int: return "int"; break;
|
||||
case GFXSCT_Int2: return "ivec2"; break;
|
||||
case GFXSCT_Int3: return "ivec3"; break;
|
||||
case GFXSCT_Int4: return "ivec4"; break;
|
||||
case GFXSCT_UInt: return "uint"; break;
|
||||
case GFXSCT_UInt2: return "uvec2"; break;
|
||||
case GFXSCT_UInt3: return "uvec3"; break;
|
||||
case GFXSCT_UInt4: return "uvec4"; break;
|
||||
case GFXSCT_Bool: return "bool"; break;
|
||||
case GFXSCT_Bool2: return "bvec2"; break;
|
||||
case GFXSCT_Bool3: return "bvec3"; break;
|
||||
case GFXSCT_Bool4: return "bvec4"; break;
|
||||
default: return "unknown"; break;
|
||||
}
|
||||
glslToType[info.glslName] = info.type;
|
||||
hlslToType[info.hlslName] = info.type;
|
||||
}
|
||||
else // Assume DirectX/HLSL
|
||||
}
|
||||
|
||||
const ShaderTypeInfo* LangElement::getTypeInfo(GFXShaderConstType type)
|
||||
{
|
||||
for (auto& info : ShaderTypes)
|
||||
if (info.type == type)
|
||||
return &info;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* LangElement::constTypeToString(GFXShaderConstType constType, bool sampler, bool matrix)
|
||||
{
|
||||
const ShaderTypeInfo* info = getTypeInfo(constType);
|
||||
if (!info)
|
||||
return "unknown";
|
||||
|
||||
if (sampler)
|
||||
{
|
||||
switch (constType)
|
||||
if (!info->isSampler())
|
||||
{
|
||||
case GFXSCT_Float: return "float"; break;
|
||||
case GFXSCT_Float2: return "float2"; break;
|
||||
case GFXSCT_Float3: return "float3"; break;
|
||||
case GFXSCT_Float4: return "float4"; break;
|
||||
case GFXSCT_Float2x2: return "float2x2"; break;
|
||||
case GFXSCT_Float3x3: return "float3x3"; break;
|
||||
case GFXSCT_Float3x4: return "float3x4"; break;
|
||||
case GFXSCT_Float4x3: return "float4x3"; break;
|
||||
case GFXSCT_Float4x4: return "float4x4"; break;
|
||||
case GFXSCT_Int: return "int"; break;
|
||||
case GFXSCT_Int2: return "int2"; break;
|
||||
case GFXSCT_Int3: return "int3"; break;
|
||||
case GFXSCT_Int4: return "int4"; break;
|
||||
case GFXSCT_UInt: return "uint"; break;
|
||||
case GFXSCT_UInt2: return "uint2"; break;
|
||||
case GFXSCT_UInt3: return "uint3"; break;
|
||||
case GFXSCT_UInt4: return "uint4"; break;
|
||||
case GFXSCT_Bool: return "bool"; break;
|
||||
case GFXSCT_Bool2: return "bool2"; break;
|
||||
case GFXSCT_Bool3: return "bool3"; break;
|
||||
case GFXSCT_Bool4: return "bool4"; break;
|
||||
default: return "unknown"; break;
|
||||
Con::warnf("LangElement::Requested sampler but input const type is not a sampler");
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
if (matrix)
|
||||
{
|
||||
if (!info->isMatrix())
|
||||
{
|
||||
Con::warnf("LangElement::Requested matrix but input const type is not a matrix");
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
return (GFX->getAdapterType() == OpenGL)
|
||||
? info->glslName
|
||||
: info->hlslName;
|
||||
}
|
||||
|
||||
GFXShaderConstType LangElement::stringToConstType(const char* name)
|
||||
{
|
||||
bool glsl = (GFX->getAdapterType() == OpenGL);
|
||||
|
||||
auto& map = glsl ? glslToType : hlslToType;
|
||||
auto it = map.find(name);
|
||||
|
||||
if (it != map.end())
|
||||
return it->value;
|
||||
|
||||
return GFXSCT_Uknown;
|
||||
}
|
||||
|
||||
bool LangElement::resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo)
|
||||
{
|
||||
outVar = nullptr;
|
||||
outInfo = nullptr;
|
||||
|
||||
// DIRECT VAR
|
||||
if (Var* v = dynamic_cast<Var*>(elem))
|
||||
{
|
||||
outVar = v;
|
||||
outInfo = getTypeInfo(stringToConstType((const char*)v->type));
|
||||
return outInfo != nullptr;
|
||||
}
|
||||
|
||||
// INDEX OP: arrVar[index]
|
||||
if (IndexOp* idx = dynamic_cast<IndexOp*>(elem))
|
||||
{
|
||||
Var* arr = dynamic_cast<Var*>(idx->mInput[0]);
|
||||
if (!arr)
|
||||
return false;
|
||||
|
||||
const ShaderTypeInfo* arrInfo = getTypeInfo(stringToConstType((const char*)arr->type));
|
||||
if (!arrInfo)
|
||||
return false;
|
||||
|
||||
// array element type = same as var type but no array dimension
|
||||
outVar = arr;
|
||||
outInfo = arrInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
// CAST OP: cast var
|
||||
if (CastOp* cast = dynamic_cast<CastOp*>(elem))
|
||||
{
|
||||
Var* castVar = dynamic_cast<Var*>(cast->mInput[0]);
|
||||
if (!castVar)
|
||||
return false;
|
||||
|
||||
const ShaderTypeInfo* castInfo = getTypeInfo(cast->mTargetType);// get the casts target type.
|
||||
if (!castInfo)
|
||||
return false;
|
||||
|
||||
outVar = castVar; // we should probably return null as we should just write the castop langelement, not a var.
|
||||
outInfo = castInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -36,6 +36,46 @@
|
|||
|
||||
#define WRITESTR( a ){ stream.write( dStrlen(a), a ); }
|
||||
|
||||
//**************************************************************************
|
||||
/*!
|
||||
These structs are helpers for unifying both sides of shadergen, the setup
|
||||
allows us to create other shaderops such as constructors for vars, cast
|
||||
operations and also checks to make sure mathops can be executed cleanly.
|
||||
*/
|
||||
//**************************************************************************
|
||||
|
||||
enum ShaderTypeCategory
|
||||
{
|
||||
STC_Scalar,
|
||||
STC_Vector,
|
||||
STC_Matrix,
|
||||
STC_Sampler
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// ShaderTypeInfo type helper for casts and other ops
|
||||
/// </summary>
|
||||
/// <param name="type">GFXShaderConstType enum type</param>
|
||||
/// <param name="glslName">const char* type name for glsl</param>
|
||||
/// <param name="hlslName">const char* type name for hlsl</param>
|
||||
/// <param name="category">ShaderTypeCategory enum for category eg STC_Scalar</param>
|
||||
struct ShaderTypeInfo
|
||||
{
|
||||
GFXShaderConstType type;
|
||||
|
||||
const char* glslName;
|
||||
const char* hlslName;
|
||||
|
||||
ShaderTypeCategory category;
|
||||
|
||||
U32 rows; // for matrices (otherwise 1)
|
||||
U32 cols; // vector size for scalars/vectors, column count for matrices
|
||||
|
||||
bool isSampler() const { return category == STC_Sampler; }
|
||||
bool isVector() const { return category == STC_Vector; }
|
||||
bool isMatrix() const { return category == STC_Matrix; }
|
||||
bool isScalar() const { return category == STC_Scalar; }
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
/*!
|
||||
|
|
@ -52,14 +92,21 @@
|
|||
//**************************************************************************
|
||||
// Language element
|
||||
//**************************************************************************
|
||||
struct Var; // forward declaration
|
||||
struct LangElement
|
||||
{
|
||||
static void buildTypeMaps();
|
||||
static Vector<LangElement*> elementList;
|
||||
static LangElement * find( const char *name );
|
||||
static void deleteElements();
|
||||
|
||||
static const ShaderTypeInfo* getTypeInfo(GFXShaderConstType type);
|
||||
static bool resolveSourceType(LangElement* elem, Var*& outVar, const ShaderTypeInfo*& outInfo);
|
||||
|
||||
U8 name[32];
|
||||
static const char* constTypeToString(GFXShaderConstType constType);
|
||||
|
||||
static const char* constTypeToString(GFXShaderConstType constType, bool sampler = false, bool matrix = false);
|
||||
static GFXShaderConstType stringToConstType(const char* name);
|
||||
|
||||
LangElement();
|
||||
virtual ~LangElement() {};
|
||||
virtual void print( Stream &stream ){};
|
||||
|
|
@ -77,6 +124,8 @@ enum ConstantSortPosition
|
|||
cspPotentialPrimitive,
|
||||
/// Updated one per pass
|
||||
cspPass,
|
||||
/// Set once per scene
|
||||
cspScene,
|
||||
/// Count var, do not use
|
||||
csp_Count
|
||||
};
|
||||
|
|
@ -185,6 +234,13 @@ public:
|
|||
void print( Stream &stream ) override;
|
||||
};
|
||||
|
||||
|
||||
class LiteralStr : public LangElement {
|
||||
public:
|
||||
LiteralStr(const char* s) : mStr(s) {}
|
||||
void print(Stream& stream) override { WRITESTR(mStr.c_str()); }
|
||||
String mStr;
|
||||
};
|
||||
|
||||
#endif // _LANG_ELEMENT_H_
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
ShaderIncludeDependency::ShaderIncludeDependency( const Torque::Path &pathToInclude )
|
||||
: mIncludePath( pathToInclude )
|
||||
{
|
||||
stages = (GFXShaderStage::VERTEX_SHADER | GFXShaderStage::PIXEL_SHADER);
|
||||
}
|
||||
|
||||
bool ShaderIncludeDependency::operator==( const ShaderDependency &cmpTo ) const
|
||||
|
|
@ -39,9 +40,12 @@ bool ShaderIncludeDependency::operator==( const ShaderDependency &cmpTo ) const
|
|||
static_cast<const ShaderIncludeDependency*>( &cmpTo )->mIncludePath == mIncludePath );
|
||||
}
|
||||
|
||||
void ShaderIncludeDependency::print( Stream &s ) const
|
||||
void ShaderIncludeDependency::print( Stream &s , GFXShaderStage stage) const
|
||||
{
|
||||
// Print the include... all shaders support #includes.
|
||||
String include = String::ToString( "#include \"%s\"\r\n", mIncludePath.getFullPath().c_str() );
|
||||
s.write( include.length(), include.c_str() );
|
||||
if (stages & stage)
|
||||
{
|
||||
String include = String::ToString("#include \"%s\"\r\n", mIncludePath.getFullPath().c_str());
|
||||
s.write(include.length(), include.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#ifndef _PATH_H_
|
||||
#include "core/util/path.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXSHADER_H_
|
||||
#include "gfx/gfxShader.h"
|
||||
#endif
|
||||
|
||||
class Stream;
|
||||
|
||||
|
|
@ -35,6 +37,7 @@ class Stream;
|
|||
class ShaderDependency
|
||||
{
|
||||
public:
|
||||
U32 stages;
|
||||
virtual ~ShaderDependency() {}
|
||||
|
||||
/// Compare this dependency to another one.
|
||||
|
|
@ -44,7 +47,7 @@ public:
|
|||
}
|
||||
|
||||
/// Print the dependency into the header of a shader.
|
||||
virtual void print( Stream &s ) const = 0;
|
||||
virtual void print( Stream &s, GFXShaderStage stage) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -60,7 +63,7 @@ public:
|
|||
ShaderIncludeDependency( const Torque::Path &pathToInclude );
|
||||
|
||||
bool operator==( const ShaderDependency &cmpTo ) const override;
|
||||
void print( Stream &s ) const override;
|
||||
void print( Stream &s, GFXShaderStage stage) const override;
|
||||
};
|
||||
|
||||
#endif // _SHADER_DEPENDENCY_H_
|
||||
#endif // _SHADER_DEPENDENCY_H_
|
||||
|
|
|
|||
|
|
@ -27,74 +27,74 @@
|
|||
#include "shaderGen/shaderOp.h"
|
||||
|
||||
|
||||
void ShaderFeature::addDependency( const ShaderDependency *dependsOn )
|
||||
void ShaderFeature::addDependency(const ShaderDependency* dependsOn)
|
||||
{
|
||||
for ( U32 i = 0; i < mDependencies.size(); i++ )
|
||||
for (U32 i = 0; i < mDependencies.size(); i++)
|
||||
{
|
||||
if ( *mDependencies[i] == *dependsOn )
|
||||
if (*mDependencies[i] == *dependsOn)
|
||||
return;
|
||||
}
|
||||
|
||||
mDependencies.push_back( dependsOn );
|
||||
mDependencies.push_back(dependsOn);
|
||||
}
|
||||
|
||||
ShaderFeature::Resources ShaderFeature::getResources( const MaterialFeatureData &fd )
|
||||
ShaderFeature::Resources ShaderFeature::getResources(const MaterialFeatureData& fd)
|
||||
{
|
||||
Resources temp;
|
||||
return temp;
|
||||
Resources temp;
|
||||
return temp;
|
||||
}
|
||||
|
||||
const char* ShaderFeature::getOutputTargetVarName( OutputTarget target ) const
|
||||
const char* ShaderFeature::getOutputTargetVarName(OutputTarget target) const
|
||||
{
|
||||
const char* targName = "col";
|
||||
|
||||
switch(target)
|
||||
switch (target)
|
||||
{
|
||||
case DefaultTarget:
|
||||
targName = "col";
|
||||
break;
|
||||
case DefaultTarget:
|
||||
targName = "col";
|
||||
break;
|
||||
|
||||
case RenderTarget1:
|
||||
case RenderTarget1:
|
||||
targName = "col1";
|
||||
break;
|
||||
break;
|
||||
|
||||
case RenderTarget2:
|
||||
targName = "col2";
|
||||
break;
|
||||
case RenderTarget2:
|
||||
targName = "col2";
|
||||
break;
|
||||
|
||||
case RenderTarget3:
|
||||
targName = "col3";
|
||||
break;
|
||||
case RenderTarget3:
|
||||
targName = "col3";
|
||||
break;
|
||||
|
||||
case RenderTarget4:
|
||||
targName = "col4";
|
||||
break;
|
||||
case RenderTarget4:
|
||||
targName = "col4";
|
||||
break;
|
||||
|
||||
case RenderTarget5:
|
||||
targName = "col5";
|
||||
break;
|
||||
case RenderTarget5:
|
||||
targName = "col5";
|
||||
break;
|
||||
}
|
||||
|
||||
return targName;
|
||||
}
|
||||
|
||||
Var* ShaderFeature::findOrCreateLocal( const char *name,
|
||||
const char *type,
|
||||
MultiLine *multi )
|
||||
Var* ShaderFeature::findOrCreateLocal(const char* name,
|
||||
const char* type,
|
||||
MultiLine* multi)
|
||||
{
|
||||
Var *outVar = (Var*)LangElement::find( name );
|
||||
if ( !outVar )
|
||||
Var* outVar = (Var*)LangElement::find(name);
|
||||
if (!outVar)
|
||||
{
|
||||
outVar = new Var;
|
||||
outVar->setType( type );
|
||||
outVar->setName( name );
|
||||
multi->addStatement( new GenOp( " @;\r\n", new DecOp( outVar ) ) );
|
||||
outVar->setType(type);
|
||||
outVar->setName(name);
|
||||
multi->addStatement(new GenOp(" @;\r\n", new DecOp(outVar)));
|
||||
}
|
||||
|
||||
return outVar;
|
||||
}
|
||||
|
||||
void ShaderFeature::setInstancingFormat(GFXVertexFormat *format)
|
||||
void ShaderFeature::setInstancingFormat(GFXVertexFormat* format)
|
||||
{
|
||||
mInstancingFormat = format;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -237,6 +237,8 @@ public:
|
|||
/// Allows the feature to add macros to vertex shader compiles.
|
||||
virtual void processVertMacros( Vector<GFXShaderMacro> ¯os, const MaterialFeatureData &fd ) {};
|
||||
|
||||
virtual U32 getShaderStages() { return (GFXShaderStage::VERTEX_SHADER | GFXShaderStage::PIXEL_SHADER); }
|
||||
|
||||
/// Identifies what type of blending a feature uses. This is used to
|
||||
/// group features with the same blend operation together in a multipass
|
||||
/// situation.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "gfx/gfxDevice.h"
|
||||
#include "core/memVolume.h"
|
||||
#include "core/module.h"
|
||||
#include "console/persistenceManager.h"
|
||||
|
||||
#ifdef TORQUE_D3D11
|
||||
#include "shaderGen/HLSL/customFeatureHLSL.h"
|
||||
|
|
@ -38,6 +39,31 @@
|
|||
#include "shaderGen/GLSL/customFeatureGLSL.h"
|
||||
#endif
|
||||
|
||||
static const U32 gStageOrder[] =
|
||||
{
|
||||
GFXShaderStage::VERTEX_SHADER,
|
||||
GFXShaderStage::HULL_SHADER,
|
||||
GFXShaderStage::DOMAIN_SHADER,
|
||||
GFXShaderStage::GEOMETRY_SHADER,
|
||||
GFXShaderStage::PIXEL_SHADER,
|
||||
GFXShaderStage::COMPUTE_SHADER
|
||||
};
|
||||
|
||||
static const char* _getStagePostfix(GFXShaderStage stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case GFXShaderStage::VERTEX_SHADER: return "_V";
|
||||
case GFXShaderStage::HULL_SHADER: return "_H";
|
||||
case GFXShaderStage::DOMAIN_SHADER: return "_D";
|
||||
case GFXShaderStage::GEOMETRY_SHADER: return "_G";
|
||||
case GFXShaderStage::PIXEL_SHADER: return "_P";
|
||||
case GFXShaderStage::COMPUTE_SHADER: return "_C";
|
||||
}
|
||||
|
||||
return "_U"; // Unknown
|
||||
}
|
||||
|
||||
MODULE_BEGIN( ShaderGen )
|
||||
|
||||
MODULE_INIT_BEFORE( GFX )
|
||||
|
|
@ -68,6 +94,16 @@ ShaderGen::~ShaderGen()
|
|||
{
|
||||
GFXDevice::getDeviceEventSignal().remove(this, &ShaderGen::_handleGFXEvent);
|
||||
_uninit();
|
||||
|
||||
mFileCache.clear();
|
||||
|
||||
for (ShaderDataMap::Pair data : mProcShaderData)
|
||||
{
|
||||
if (data.value->isProperlyAdded() && !data.value->isDeleted())
|
||||
data.value->unregisterObject();
|
||||
}
|
||||
|
||||
mProcShaderData.clear();
|
||||
}
|
||||
|
||||
void ShaderGen::registerInitDelegate(GFXAdapterType adapterType, ShaderGenInitDelegate& initDelegate)
|
||||
|
|
@ -99,6 +135,8 @@ void ShaderGen::initShaderGen()
|
|||
return;
|
||||
|
||||
const GFXAdapterType adapterType = GFX->getAdapterType();
|
||||
const bool isGl = adapterType == GFXAdapterType::OpenGL;
|
||||
|
||||
if (!mInitDelegates[adapterType])
|
||||
return;
|
||||
|
||||
|
|
@ -133,12 +171,23 @@ void ShaderGen::initShaderGen()
|
|||
|
||||
// Delete the auto-generated conditioner include file.
|
||||
Torque::FS::Remove( "shadergen:/" + ConditionerFeature::ConditionerIncludeFileName );
|
||||
|
||||
Vector<String> fileList;
|
||||
String pattern = "*.";
|
||||
pattern += isGl ? "glsl" : "hlsl";
|
||||
S32 numShaderFiles = Torque::FS::FindByPattern("shadergen:/", pattern, false, fileList);
|
||||
for (U32 i = 0; i < numShaderFiles; i++)
|
||||
{
|
||||
Torque::Path filePath = fileList[i];
|
||||
mFileCache[filePath.getFileName()] = true;
|
||||
}
|
||||
|
||||
// build our type maps.
|
||||
LangElement::buildTypeMaps();
|
||||
}
|
||||
|
||||
void ShaderGen::generateShader( const MaterialFeatureData &featureData,
|
||||
char *vertFile,
|
||||
char *pixFile,
|
||||
F32 *pixVersion,
|
||||
void ShaderGen::generateShader( const MaterialFeatureData& featureData,
|
||||
ShaderData* shaderData,
|
||||
const GFXVertexFormat *vertexFormat,
|
||||
const char* cacheName,
|
||||
Vector<GFXShaderMacro> ¯os)
|
||||
|
|
@ -151,65 +200,115 @@ void ShaderGen::generateShader( const MaterialFeatureData &featureData,
|
|||
_uninit();
|
||||
_init();
|
||||
|
||||
char vertShaderName[256];
|
||||
char pixShaderName[256];
|
||||
const FeatureSet& features = mFeatureData.features;
|
||||
U32 stages = 0;
|
||||
|
||||
// Note: We use a postfix of _V/_P here so that it sorts the matching
|
||||
// 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 ) )
|
||||
// loop through and see which stages this featureset is expecting to make.
|
||||
for (U32 i = 0; i < features.getCount(); i++)
|
||||
{
|
||||
// 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 );
|
||||
const FeatureType& type = features.getAt(i);
|
||||
ShaderFeature* feat = FEATUREMGR->getByType(type);
|
||||
stages |= feat->getShaderStages();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// create vertex shader
|
||||
//------------------------
|
||||
FileStream* s = new FileStream();
|
||||
if(!s->open(vertShaderName, Torque::FS::File::Write ))
|
||||
for (U32 s = 0; s < (sizeof(gStageOrder) / sizeof(U32)); s++)
|
||||
{
|
||||
AssertFatal(false, "Failed to open Shader Stream" );
|
||||
return;
|
||||
U32 stage = gStageOrder[s];
|
||||
|
||||
// skip unused stages
|
||||
if (!(stages & stage))
|
||||
continue;
|
||||
|
||||
bool macrosOnly = !Con::getBoolVariable("ShaderGen::GenNewShaders", true);
|
||||
bool skipPrint = false;
|
||||
GFXShaderStage curStage = (GFXShaderStage)stage;
|
||||
|
||||
char fileName[256];
|
||||
const char* postfix = _getStagePostfix(curStage);
|
||||
String stageName;
|
||||
|
||||
if (curStage & GFXShaderStage::VERTEX_SHADER)
|
||||
stageName += vertexFormat->getDescription();
|
||||
|
||||
// build our filename.
|
||||
for (U32 i = 0; i < features.getCount(); i++)
|
||||
{
|
||||
const FeatureType& type = features.getAt(i);
|
||||
if (stage & FEATUREMGR->getByType(type)->getShaderStages())
|
||||
{
|
||||
stageName += type.getName();
|
||||
}
|
||||
}
|
||||
|
||||
stageName = Torque::getStringHash64(stageName);
|
||||
stageName += postfix;
|
||||
|
||||
FileCacheSet::iterator file = mFileCache.find(stageName);
|
||||
if (file != mFileCache.end())
|
||||
{
|
||||
// set the shaderdata file for this stage, shaderdata ptr needs to be passed in here.
|
||||
dSprintf(fileName, sizeof(fileName), "shadergen:/%s.%s", stageName.c_str(), mFileEnding.c_str());
|
||||
shaderData->setShaderStageFile(curStage, fileName);
|
||||
if (!(curStage & GFXShaderStage::VERTEX_SHADER))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
skipPrint = true;
|
||||
}
|
||||
|
||||
mFileCache[stageName] = true;
|
||||
|
||||
dSprintf(fileName, sizeof(fileName), "shadergen:/%s.%s", stageName.c_str(), mFileEnding.c_str());
|
||||
|
||||
shaderData->setShaderStageFile(curStage, fileName);
|
||||
|
||||
|
||||
FileStream* stream = new FileStream();
|
||||
if (!skipPrint)
|
||||
{
|
||||
if (!stream->open(fileName, Torque::FS::File::Write))
|
||||
{
|
||||
AssertFatal(false, "Failed to open Shader Stream");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (curStage)
|
||||
{
|
||||
case VERTEX_SHADER:
|
||||
mOutput = new MultiLine;
|
||||
mInstancingFormat.clear();
|
||||
_processVertFeatures(macros, macrosOnly);
|
||||
if(!skipPrint || macrosOnly) _printVertShader(*stream);
|
||||
delete stream;
|
||||
((ShaderConnector*)mComponents[C_CONNECTOR])->reset();
|
||||
LangElement::deleteElements();
|
||||
break;
|
||||
case PIXEL_SHADER:
|
||||
mOutput = new MultiLine;
|
||||
_processPixFeatures(macros, macrosOnly);
|
||||
if (!skipPrint || macrosOnly)_printPixShader(*stream);
|
||||
delete stream;
|
||||
LangElement::deleteElements();
|
||||
break;
|
||||
case GEOMETRY_SHADER:
|
||||
break;
|
||||
case DOMAIN_SHADER:
|
||||
break;
|
||||
case HULL_SHADER:
|
||||
break;
|
||||
case COMPUTE_SHADER:
|
||||
break;
|
||||
case ALL_STAGES:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mOutput = new MultiLine;
|
||||
mInstancingFormat.clear();
|
||||
_processVertFeatures(macros);
|
||||
_printVertShader( *s );
|
||||
delete s;
|
||||
|
||||
((ShaderConnector*)mComponents[C_CONNECTOR])->reset();
|
||||
LangElement::deleteElements();
|
||||
|
||||
// create pixel shader
|
||||
//------------------------
|
||||
s = new FileStream();
|
||||
if(!s->open(pixShaderName, Torque::FS::File::Write ))
|
||||
{
|
||||
AssertFatal(false, "Failed to open Shader Stream" );
|
||||
delete s;
|
||||
return;
|
||||
}
|
||||
|
||||
mOutput = new MultiLine;
|
||||
_processPixFeatures(macros);
|
||||
_printPixShader( *s );
|
||||
|
||||
delete s;
|
||||
LangElement::deleteElements();
|
||||
}
|
||||
|
||||
void ShaderGen::_init()
|
||||
|
|
@ -257,20 +356,20 @@ void ShaderGen::_processVertFeatures( Vector<GFXShaderMacro> ¯os, bool macro
|
|||
{
|
||||
S32 index;
|
||||
const FeatureType &type = features.getAt( i, &index );
|
||||
void* args = features.getArguments(i);
|
||||
FeatureParamsBase* args = features.getArguments(i);
|
||||
ShaderFeature* feature = NULL;
|
||||
if(args)
|
||||
feature = FEATUREMGR->createFeature(type, args);
|
||||
else
|
||||
feature = FEATUREMGR->getByType( type );
|
||||
|
||||
if ( feature )
|
||||
if ( feature && (feature->getShaderStages() & GFXShaderStage::VERTEX_SHADER))
|
||||
{
|
||||
feature->setProcessIndex( index );
|
||||
|
||||
feature->processVertMacros( macros, mFeatureData );
|
||||
|
||||
if ( macrosOnly )
|
||||
if (macrosOnly)
|
||||
continue;
|
||||
|
||||
feature->setInstancingFormat( &mInstancingFormat );
|
||||
|
|
@ -306,13 +405,13 @@ void ShaderGen::_processPixFeatures( Vector<GFXShaderMacro> ¯os, bool macros
|
|||
{
|
||||
S32 index;
|
||||
const FeatureType &type = features.getAt( i, &index );
|
||||
void* args = features.getArguments(i);
|
||||
FeatureParamsBase* args = features.getArguments(i);
|
||||
ShaderFeature* feature = NULL;
|
||||
if (args)
|
||||
feature = FEATUREMGR->createFeature(type, args);
|
||||
else
|
||||
feature = FEATUREMGR->getByType(type);
|
||||
if ( feature )
|
||||
if ( feature && (feature->getShaderStages() & GFXShaderStage::PIXEL_SHADER))
|
||||
{
|
||||
feature->setProcessIndex( index );
|
||||
|
||||
|
|
@ -353,7 +452,7 @@ void ShaderGen::_printFeatureList(Stream &stream)
|
|||
{
|
||||
S32 index;
|
||||
const FeatureType &type = features.getAt( i, &index );
|
||||
void* args = features.getArguments(i);
|
||||
FeatureParamsBase* args = features.getArguments(i);
|
||||
ShaderFeature* feature = NULL;
|
||||
if (args)
|
||||
feature = FEATUREMGR->createFeature(type, args);
|
||||
|
|
@ -374,7 +473,7 @@ void ShaderGen::_printFeatureList(Stream &stream)
|
|||
mPrinter->printLine(stream, "");
|
||||
}
|
||||
|
||||
void ShaderGen::_printDependencies(Stream &stream)
|
||||
void ShaderGen::_printDependencies(Stream &stream, GFXShaderStage stage)
|
||||
{
|
||||
Vector<const ShaderDependency *> dependencies;
|
||||
|
||||
|
|
@ -412,7 +511,7 @@ void ShaderGen::_printDependencies(Stream &stream)
|
|||
mPrinter->printLine(stream, "// Dependencies:");
|
||||
|
||||
for( S32 i = 0; i < dependencies.size(); i++ )
|
||||
dependencies[i]->print( stream );
|
||||
dependencies[i]->print( stream, stage);
|
||||
|
||||
mPrinter->printLine(stream, "");
|
||||
}
|
||||
|
|
@ -427,7 +526,7 @@ void ShaderGen::_printVertShader( Stream &stream )
|
|||
{
|
||||
mPrinter->printShaderHeader(stream);
|
||||
|
||||
_printDependencies(stream); // TODO: Split into vert and pix dependencies?
|
||||
_printDependencies(stream, GFXShaderStage::VERTEX_SHADER); // TODO: Split into vert and pix dependencies?
|
||||
_printFeatureList(stream);
|
||||
|
||||
// print out structures
|
||||
|
|
@ -449,7 +548,7 @@ void ShaderGen::_printPixShader( Stream &stream )
|
|||
{
|
||||
mPrinter->printShaderHeader(stream);
|
||||
|
||||
_printDependencies(stream); // TODO: Split into vert and pix dependencies?
|
||||
_printDependencies(stream, GFXShaderStage::PIXEL_SHADER); // TODO: Split into vert and pix dependencies?
|
||||
_printFeatureList(stream);
|
||||
|
||||
mComponents[C_CONNECTOR]->print( stream, false );
|
||||
|
|
@ -466,60 +565,48 @@ void ShaderGen::_printPixShader( Stream &stream )
|
|||
mPrinter->printPixelShaderCloser(stream);
|
||||
}
|
||||
|
||||
GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers )
|
||||
GFXShader* ShaderGen::getShader(const MaterialFeatureData& featureData, const GFXVertexFormat* vertexFormat, const Vector<GFXShaderMacro>* macros, const Vector<String>& samplers)
|
||||
{
|
||||
PROFILE_SCOPE( ShaderGen_GetShader );
|
||||
PROFILE_SCOPE(ShaderGen_GetShader);
|
||||
|
||||
const FeatureSet &features = featureData.codify();
|
||||
const FeatureSet& features = featureData.codify();
|
||||
|
||||
// Build a description string from the features
|
||||
// and vertex format combination ( and macros ).
|
||||
String shaderDescription = vertexFormat->getDescription() + features.getDescription();
|
||||
// Generate a single 64bit hash from the description string.
|
||||
//
|
||||
// Don't get paranoid! This has 1 in 18446744073709551616
|
||||
// chance for collision... it won't happen in this lifetime.
|
||||
//
|
||||
shaderDescription.replace("\n", " ");
|
||||
U64 hash = Torque::hash64( (const U8*)shaderDescription.c_str(), shaderDescription.length(), 0 );
|
||||
hash = convertHostToLEndian(hash);
|
||||
U32 high = (U32)( hash >> 32 );
|
||||
U32 low = (U32)( hash & 0x00000000FFFFFFFF );
|
||||
String cacheKey = String::ToString( "%x%x", high, low );
|
||||
// return shader if exists
|
||||
GFXShader *match = mProcShaders[cacheKey];
|
||||
if ( match )
|
||||
return match;
|
||||
|
||||
// if not, then create it
|
||||
char vertFile[256];
|
||||
char pixFile[256];
|
||||
F32 pixVersion;
|
||||
String cacheKey = Torque::getStringHash64(shaderDescription);
|
||||
|
||||
Vector<GFXShaderMacro> shaderMacros;
|
||||
shaderMacros.push_back( GFXShaderMacro( "TORQUE_SHADERGEN" ) );
|
||||
if ( macros )
|
||||
shaderMacros.merge( *macros );
|
||||
generateShader( featureData, vertFile, pixFile, &pixVersion, vertexFormat, cacheKey, shaderMacros );
|
||||
shaderMacros.push_back(GFXShaderMacro("TORQUE_SHADERGEN"));
|
||||
if (macros)
|
||||
shaderMacros.merge(*macros);
|
||||
|
||||
GFXShader *shader = GFX->createShader();
|
||||
shader->setShaderStageFile(GFXShaderStage::VERTEX_SHADER, vertFile);
|
||||
shader->setShaderStageFile(GFXShaderStage::PIXEL_SHADER, pixFile);
|
||||
|
||||
if (!shader->init(pixVersion, shaderMacros, samplers, &mInstancingFormat))
|
||||
ShaderDataMap::iterator dat = mProcShaderData.find(cacheKey);
|
||||
if (dat != mProcShaderData.end())
|
||||
{
|
||||
delete shader;
|
||||
return NULL;
|
||||
// should we loop vertex shader features to build mInstancingFormat before sending it down to see old hob?
|
||||
return dat->value->getShader(shaderMacros);
|
||||
}
|
||||
|
||||
mProcShaders[cacheKey] = shader;
|
||||
ShaderData* shaderData = new ShaderData;
|
||||
|
||||
return shader;
|
||||
shaderData->setPixVersion(GFX->getPixelShaderVersion());
|
||||
|
||||
for (U32 samp = 0; samp < samplers.size(); samp++)
|
||||
{
|
||||
shaderData->setSamplerName(samplers[samp], samp);
|
||||
}
|
||||
|
||||
generateShader(featureData, shaderData, vertexFormat, cacheKey, shaderMacros);
|
||||
|
||||
shaderData->setInstancingFormat(&mInstancingFormat);
|
||||
|
||||
mProcShaderData.insert(cacheKey, shaderData);
|
||||
return shaderData->getShader(shaderMacros);
|
||||
}
|
||||
|
||||
void ShaderGen::flushProceduralShaders()
|
||||
{
|
||||
// The shaders are reference counted, so we
|
||||
// just need to clear the map.
|
||||
mProcShaders.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -46,6 +46,10 @@
|
|||
#ifndef _MATERIALFEATUREDATA_H_
|
||||
#include "materials/materialFeatureData.h"
|
||||
#endif
|
||||
#ifndef _SHADERDATA_H_
|
||||
#include "materials/shaderData.h"
|
||||
#endif // !_SHADERDATA_H_
|
||||
|
||||
|
||||
/// Base class used by shaderGen to be API agnostic. Subclasses implement the various methods
|
||||
/// in an API specific way.
|
||||
|
|
@ -145,13 +149,11 @@ public:
|
|||
/// the vertex and pixel shader files. pixVersion is also filled in by
|
||||
/// this function.
|
||||
/// @param assignNum used to assign a specific number as the filename
|
||||
void generateShader( const MaterialFeatureData &featureData,
|
||||
char *vertFile,
|
||||
char *pixFile,
|
||||
F32 *pixVersion,
|
||||
const GFXVertexFormat *vertexFormat,
|
||||
void generateShader( const MaterialFeatureData& featureData,
|
||||
ShaderData* shaderData,
|
||||
const GFXVertexFormat* vertexFormat,
|
||||
const char* cacheName,
|
||||
Vector<GFXShaderMacro> ¯os);
|
||||
Vector<GFXShaderMacro>& macros);
|
||||
|
||||
// Returns a shader that implements the features listed by dat.
|
||||
GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector<GFXShaderMacro> *macros, const Vector<String> &samplers );
|
||||
|
|
@ -191,10 +193,15 @@ protected:
|
|||
FeatureInitSignal mFeatureInitSignal;
|
||||
bool mRegisteredWithGFX;
|
||||
Torque::FS::FileSystemRef mMemFS;
|
||||
|
||||
/// Map of cache string -> shaders
|
||||
typedef Map<String, GFXShaderRef> ShaderMap;
|
||||
ShaderMap mProcShaders;
|
||||
|
||||
/// <summary>
|
||||
/// Map of shaderdata, string should be built up of stage files
|
||||
/// </summary>
|
||||
typedef HashMap<String, SimObjectPtr<ShaderData>> ShaderDataMap;
|
||||
ShaderDataMap mProcShaderData;
|
||||
|
||||
typedef HashMap<String, bool> FileCacheSet; // we use a hashmap because it is quicker for finding.
|
||||
FileCacheSet mFileCache;
|
||||
|
||||
ShaderGen();
|
||||
|
||||
|
|
@ -215,7 +222,7 @@ protected:
|
|||
/// print out the processed features to the file stream
|
||||
void _printFeatures( Stream &stream );
|
||||
|
||||
void _printDependencies( Stream &stream );
|
||||
void _printDependencies( Stream &stream, GFXShaderStage stage);
|
||||
|
||||
void _processPixFeatures( Vector<GFXShaderMacro> ¯os, bool macrosOnly = false );
|
||||
void _printPixShader( Stream &stream );
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "gfx/gfxDevice.h"
|
||||
|
||||
#include "shaderOp.h"
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ void EchoOp::print( Stream &stream )
|
|||
//**************************************************************************
|
||||
// Index operation
|
||||
//**************************************************************************
|
||||
IndexOp::IndexOp( Var* var, U32 index ) : Parent( NULL, NULL )
|
||||
IndexOp::IndexOp( Var* var, U32 index ) : Parent(var, NULL )
|
||||
{
|
||||
mInput[0] = var;
|
||||
mIndex = index;
|
||||
|
|
@ -180,18 +180,338 @@ void GenOp::print( Stream &stream )
|
|||
}
|
||||
}
|
||||
|
||||
CastOp::CastOp(Var* in1, GFXShaderConstType type) : Parent(in1, NULL)
|
||||
//----------------------------------------------------------------------------
|
||||
// TYPE OPERATION
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
TypeOp::TypeOp(GFXShaderConstType type) : Parent(NULL, NULL)
|
||||
{
|
||||
mInput[0] = in1;
|
||||
mConstType = constTypeToString(type);
|
||||
mType = type;
|
||||
}
|
||||
|
||||
TypeOp::~TypeOp()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Print
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void TypeOp::print(Stream& stream)
|
||||
{
|
||||
WRITESTR(LangElement::constTypeToString(mType));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CAST OPERATION
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CastOp::CastOp(LangElement* srcVar, GFXShaderConstType type, const char* swizzleStr, const char* fillStr) : Parent(srcVar, NULL)
|
||||
{
|
||||
mInput[0] = srcVar;
|
||||
mTargetType = type;
|
||||
parseStringList(swizzleStr, mSwizzle);
|
||||
parseStringList(fillStr, mFillValues);
|
||||
}
|
||||
|
||||
void CastOp::print(Stream& stream)
|
||||
{
|
||||
Var* var = dynamic_cast<Var*>(mInput[0]);
|
||||
LangElement* srcElem = mInput[0];
|
||||
|
||||
Var* srcVar = nullptr;
|
||||
const ShaderTypeInfo* srcInfo = nullptr;
|
||||
|
||||
if (!resolveSourceType(srcElem, srcVar, srcInfo))
|
||||
{
|
||||
// fallback: at least print something
|
||||
srcElem->print(stream);
|
||||
return;
|
||||
}
|
||||
|
||||
const ShaderTypeInfo* dstInfo = getTypeInfo(mTargetType);
|
||||
|
||||
// no info? types match? nothing to do.
|
||||
if (!srcInfo || !dstInfo)
|
||||
{
|
||||
srcElem->print(stream); // print something....
|
||||
return;
|
||||
}
|
||||
|
||||
const bool glsl = (GFX->getAdapterType() == OpenGL);
|
||||
const char* dstName = glsl ? dstInfo->glslName : dstInfo->hlslName;
|
||||
|
||||
U32 srcSize = srcInfo->cols;
|
||||
U32 dstSize = dstInfo->cols;
|
||||
|
||||
// scalar -> vector
|
||||
if (srcSize == 1 && dstSize > 1)
|
||||
{
|
||||
WRITESTR(dstName);
|
||||
WRITESTR("(");
|
||||
srcElem->print(stream);
|
||||
|
||||
for (U32 i = 1; i < dstSize; i++)
|
||||
{
|
||||
WRITESTR(", ");
|
||||
WRITESTR(mFillValues[i].c_str());
|
||||
}
|
||||
|
||||
WRITESTR(")");
|
||||
return;
|
||||
}
|
||||
|
||||
// vector -> scalar
|
||||
if (srcSize > 1 && dstSize == 1)
|
||||
{
|
||||
srcElem->print(stream);
|
||||
WRITESTR(".");
|
||||
WRITESTR(mSwizzle[0].c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// vector -> vector narrowing
|
||||
if (srcSize > dstSize)
|
||||
{
|
||||
WRITESTR(dstName);
|
||||
WRITESTR("(");
|
||||
srcElem->print(stream);
|
||||
WRITESTR(".");
|
||||
|
||||
for (U32 i = 0; i < dstSize; i++)
|
||||
{
|
||||
WRITESTR(mSwizzle[i].c_str());
|
||||
}
|
||||
|
||||
WRITESTR(")");
|
||||
return;
|
||||
}
|
||||
|
||||
// vector -> vector widening
|
||||
if (srcSize <= dstSize)
|
||||
{
|
||||
WRITESTR(dstName);
|
||||
WRITESTR("(");
|
||||
srcElem->print(stream);
|
||||
if (mSwizzle.size() < srcSize)
|
||||
{
|
||||
WRITESTR(".");
|
||||
|
||||
for (U32 i = 0; i < mSwizzle.size(); i++)
|
||||
{
|
||||
WRITESTR(mSwizzle[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
for (U32 i = getMin((U32)mSwizzle.size(), srcSize); i < dstSize; i++)
|
||||
{
|
||||
WRITESTR(", ");
|
||||
WRITESTR(mFillValues[i].c_str());
|
||||
}
|
||||
|
||||
WRITESTR(")");
|
||||
return;
|
||||
}
|
||||
|
||||
// fallback
|
||||
srcElem->print(stream);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// MATRIX INITIALIZE OPERATION
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void MatrixInitializeOp::print(Stream& stream)
|
||||
{
|
||||
Var* matVar = dynamic_cast<Var*>(mInput[0]);
|
||||
if (!matVar)
|
||||
return;
|
||||
|
||||
const ShaderTypeInfo* matInfo = getTypeInfo(stringToConstType((const char*)matVar->type));
|
||||
if (!matInfo || !matInfo->isMatrix())
|
||||
return;
|
||||
|
||||
// full size of the mat.
|
||||
const bool glsl = (GFX->getAdapterType() == OpenGL);
|
||||
const U32 rows = matInfo->rows;
|
||||
const U32 cols = matInfo->cols;
|
||||
const U32 matSize = rows * cols;
|
||||
|
||||
if (glsl)
|
||||
{
|
||||
WRITESTR(matInfo->glslName);
|
||||
WRITESTR("(\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITESTR("{\r\n");
|
||||
}
|
||||
|
||||
U32 count = 0;
|
||||
for (U32 elem = 0; elem < mInitialVals.size(); elem++)
|
||||
{
|
||||
LangElement* initElem = mInitialVals[elem];
|
||||
Var* initVar = nullptr;
|
||||
const ShaderTypeInfo* initInfo = nullptr;
|
||||
|
||||
if (!resolveSourceType(initElem, initVar, initInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dynamic_cast<IndexOp*>(initElem) || dynamic_cast<CastOp*>(initElem)) // if we are a cast or index, write out.
|
||||
{
|
||||
count += initInfo->cols;
|
||||
initElem->print(stream);
|
||||
}
|
||||
else if(dynamic_cast<Var*>(initElem)) // we are a var (hopefully)
|
||||
{
|
||||
const U32 varSize = initInfo->cols;
|
||||
const bool cast = cols != varSize;
|
||||
|
||||
if (initVar->arraySize > 1)
|
||||
{
|
||||
for (U32 arr = 0; arr < initVar->arraySize; arr++)
|
||||
{
|
||||
initElem = new IndexOp(initVar, arr);
|
||||
if (cast)
|
||||
{
|
||||
CastOp* castOp = new CastOp(initElem, (GFXShaderConstType)(GFXSCT_Float + (cols - 1)));
|
||||
castOp->print(stream);
|
||||
count += cols;
|
||||
}
|
||||
else
|
||||
{
|
||||
initElem->print(stream);
|
||||
count += varSize;
|
||||
}
|
||||
|
||||
if (count < matSize)
|
||||
{
|
||||
WRITESTR(",\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cast)
|
||||
{
|
||||
CastOp* castOp = new CastOp(initElem, (GFXShaderConstType)(GFXSCT_Float + (cols - 1)));
|
||||
castOp->print(stream);
|
||||
count += cols;
|
||||
}
|
||||
else
|
||||
{
|
||||
initElem->print(stream);
|
||||
count += varSize;
|
||||
}
|
||||
|
||||
if (count < matSize)
|
||||
{
|
||||
WRITESTR(",\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not enough elements → pad with identity
|
||||
while (count < matSize)
|
||||
{
|
||||
U32 row = count / cols;
|
||||
U32 col = count % cols;
|
||||
|
||||
if (row == col)
|
||||
{
|
||||
WRITESTR("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITESTR("0");
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
if (count < matSize)
|
||||
{
|
||||
WRITESTR(",\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (glsl)
|
||||
{
|
||||
WRITESTR(")\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITESTR("}\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
MatrixMultiplyOp::MatrixMultiplyOp(LangElement* left, LangElement* right) : Parent(left, right)
|
||||
{
|
||||
mInput[0] = left;
|
||||
mInput[1] = right;
|
||||
}
|
||||
|
||||
void MatrixMultiplyOp::print(Stream& stream)
|
||||
{
|
||||
LangElement* leftElem = mInput[0];
|
||||
Var* leftVar = nullptr;
|
||||
const ShaderTypeInfo* leftInfo = nullptr;
|
||||
|
||||
if (!resolveSourceType(leftElem, leftVar, leftInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LangElement* rightElem = mInput[1];
|
||||
Var* rightVar = nullptr;
|
||||
const ShaderTypeInfo* rightInfo = nullptr;
|
||||
|
||||
if (!resolveSourceType(rightElem, rightVar, rightInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (leftInfo->isMatrix() && rightInfo->isVector())
|
||||
{
|
||||
if (rightInfo->cols != leftInfo->cols)
|
||||
{
|
||||
rightElem = new CastOp(rightVar, (GFXShaderConstType)(GFXSCT_Float + (leftInfo->cols - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
if (leftInfo->isVector() && rightInfo->isMatrix())
|
||||
{
|
||||
if (rightInfo->cols != leftInfo->cols)
|
||||
{
|
||||
leftElem = new CastOp(leftVar, (GFXShaderConstType)(GFXSCT_Float + (rightInfo->cols - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
else if (leftInfo->isMatrix() && rightInfo->isMatrix())
|
||||
{
|
||||
if (leftInfo->cols != rightInfo->rows)
|
||||
Con::warnf("MatrixMultiplyOp: incompatible matrices: (%dx%d) × (%dx%d)",
|
||||
leftInfo->rows, leftInfo->cols,
|
||||
rightInfo->rows, rightInfo->cols);
|
||||
}
|
||||
|
||||
const bool glsl = (GFX->getAdapterType() == OpenGL);
|
||||
|
||||
if (!glsl)
|
||||
{
|
||||
WRITESTR("mul(");
|
||||
leftElem->print(stream);
|
||||
WRITESTR(", ");
|
||||
rightElem->print(stream);
|
||||
WRITESTR(")");
|
||||
}
|
||||
else
|
||||
{
|
||||
leftElem->print(stream);
|
||||
WRITESTR(" * ");
|
||||
rightElem->print(stream);
|
||||
}
|
||||
|
||||
WRITESTR(mConstType);
|
||||
WRITESTR("( ");
|
||||
mInput[0]->print(stream);
|
||||
WRITESTR(" )");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,8 @@
|
|||
///**************************************************************************
|
||||
class ShaderOp : public LangElement
|
||||
{
|
||||
protected:
|
||||
LangElement * mInput[2];
|
||||
|
||||
public:
|
||||
LangElement* mInput[2];
|
||||
ShaderOp( LangElement *in1, LangElement *in2 );
|
||||
};
|
||||
|
||||
|
|
@ -117,7 +115,6 @@ class IndexOp : public ShaderOp
|
|||
{
|
||||
typedef ShaderOp Parent;
|
||||
U32 mIndex;
|
||||
|
||||
public:
|
||||
IndexOp( Var* var, U32 index );
|
||||
void print( Stream &stream ) override;
|
||||
|
|
@ -161,14 +158,95 @@ public:
|
|||
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/*!
|
||||
Like the name suggests, prints out the type as a string, for working between
|
||||
glsl and hlsl.
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
class TypeOp : public ShaderOp
|
||||
{
|
||||
typedef ShaderOp Parent;
|
||||
GFXShaderConstType mType;
|
||||
public:
|
||||
TypeOp(GFXShaderConstType type);
|
||||
~TypeOp();
|
||||
void print(Stream& stream) override;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/*!
|
||||
Casting operation to cast a var from one type to another.
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
class CastOp : public ShaderOp
|
||||
{
|
||||
typedef ShaderOp Parent;
|
||||
const char* mConstType;
|
||||
Vector<String> mSwizzle; // "x", "y", "z", "w"
|
||||
Vector<String> mFillValues; // "0", "0", "0", "1"
|
||||
public:
|
||||
CastOp(Var* in1, GFXShaderConstType type);
|
||||
GFXShaderConstType mTargetType;
|
||||
CastOp( LangElement* srcVar,
|
||||
GFXShaderConstType type,
|
||||
const char* swizzleStr = "x;y;z;w",
|
||||
const char* fillStr = "0;0;0;1");
|
||||
|
||||
void print(Stream& stream) override;
|
||||
|
||||
void parseStringList(const char* src, Vector<String>& out)
|
||||
{
|
||||
out.clear();
|
||||
const char* p = src;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
const char* start = p;
|
||||
while (*p && *p != ';')
|
||||
p++;
|
||||
|
||||
out.push_back(String(start, p - start));
|
||||
|
||||
if (*p == ';')
|
||||
p++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/*!
|
||||
Matrix initialize operation, initializes a matrix with the input
|
||||
vars as a vector.
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class MatrixInitializeOp : public ShaderOp
|
||||
{
|
||||
typedef ShaderOp Parent;
|
||||
Vector<LangElement*> mInitialVals;
|
||||
public:
|
||||
MatrixInitializeOp(Var* matrixVar, const Vector<LangElement*>& inputs)
|
||||
: Parent(matrixVar, nullptr)
|
||||
{
|
||||
mInitialVals = inputs;
|
||||
mInput[0] = matrixVar;
|
||||
}
|
||||
|
||||
void print(Stream& stream) override;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/*!
|
||||
Matrix multiplication operation.
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class MatrixMultiplyOp : public ShaderOp
|
||||
{
|
||||
typedef ShaderOp Parent;
|
||||
public:
|
||||
MatrixMultiplyOp(LangElement* left, LangElement* right);
|
||||
|
||||
void print(Stream& stream) override;
|
||||
};
|
||||
|
||||
#endif // _SHADEROP_H_
|
||||
|
|
|
|||
|
|
@ -1092,7 +1092,7 @@ TSShape* assimpLoadShape(const Torque::Path &path)
|
|||
// Cache the model to a DTS file for faster loading next time.
|
||||
cachedPath.setExtension("cached.dts");
|
||||
// Cache the model to a DTS file for faster loading next time.
|
||||
FileStream dtsStream;
|
||||
FileStream dtsStream(FileStream::AsyncMode::Background);
|
||||
if (dtsStream.open(cachedPath.getFullPath(), Torque::FS::File::Write))
|
||||
{
|
||||
Con::printf("Writing cached shape to %s", cachedPath.getFullPath().c_str());
|
||||
|
|
|
|||
|
|
@ -803,7 +803,7 @@ TSShape* loadColladaShape(const Torque::Path &path)
|
|||
{
|
||||
// Cache the Collada model to a DTS file for faster loading next time.
|
||||
cachedPath.setExtension("cached.dts");
|
||||
FileStream dtsStream;
|
||||
FileStream dtsStream(FileStream::AsyncMode::Background);
|
||||
if (dtsStream.open(cachedPath.getFullPath(), Torque::FS::File::Write))
|
||||
{
|
||||
Torque::FS::FileSystemRef ref = Torque::FS::GetFileSystem(daePath);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue