diff --git a/Engine/source/shaderGen/NODE/shaderGenNodes.cpp b/Engine/source/shaderGen/NODE/shaderGenNodes.cpp index 011d29e38..8634bc32d 100644 --- a/Engine/source/shaderGen/NODE/shaderGenNodes.cpp +++ b/Engine/source/shaderGen/NODE/shaderGenNodes.cpp @@ -15,12 +15,14 @@ #include "materials/materialFeatureTypes.h" -ImplementFeatureType(SNF_DefaultTexCoord, U32(-1), -1, false); -ImplementFeatureType(SNF_TextureFeature, 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_DefaultTexCoord, "SNF_DefaultTexCoord", "Setup the default texcoord." }, - { ShaderNodeFeature_enum::eSNF_TextureFeature, "SNF_TextureFeature", "Sample a Texture - Params: (string,string,GFXSamplerStateData,bool)." }, + { 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 @@ -28,7 +30,11 @@ namespace void register_node_features(GFXAdapterType type) { FEATUREMGR->registerFeature(SNF_DefaultTexCoord, new DefaultTexcoordFeature); - FEATUREMGR->registerFeature(SNF_TextureFeature, new TextureFeature, TextureFeature::createFunction); + 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); } }; @@ -58,14 +64,15 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName, // ---- Create or find texture/sampler vars ---- String texVarName = samplerName + "_tex"; - String sampVarName = samplerName + "_sampler"; + String sampVarName = samplerName; + String resultVarName = samplerName + "_col"; - Var* textureVar = dynamic_cast(LangElement::find(texVarName)); + Var* samplerVar = dynamic_cast(LangElement::find(sampVarName)); - - if (!isGL) + Var* textureVar; + + if (!isGL) // HLSL requires both Texture + SamplerState { - // HLSL requires both Texture + SamplerState if (!samplerVar) { samplerVar = new Var; @@ -76,6 +83,7 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName, samplerVar->constNum = Var::getTexUnitNum(); } + textureVar = dynamic_cast(LangElement::find(texVarName)); if (!textureVar) { textureVar = new Var; @@ -88,65 +96,80 @@ void ShaderFeatureNode::setupTextureSample( const String& samplerName, } else { - // GLSL uses a single sampler uniform - if (!textureVar) + if (!samplerVar) { - textureVar = new Var; - textureVar->setType(LangElement::samplerTypeToString(samplerType)); - textureVar->setName(texVarName); - textureVar->uniform = true; - textureVar->sampler = true; - textureVar->constNum = Var::getTexUnitNum(); + samplerVar = new Var; + samplerVar->setType(LangElement::samplerTypeToString(samplerType)); + samplerVar->setName(sampVarName); + samplerVar->uniform = true; + samplerVar->sampler = true; + samplerVar->constNum = Var::getTexUnitNum(); } } - // ---- Emit sampling code ---- - String sampleFunc; - if (isComparison) + // The sampled color variable (e.g. "samplerName_col") should always be new but just in case + Var* sampledColor = (Var*)LangElement::find(resultVarName); + if (!sampledColor) { - if (useGather) - sampleFunc = isGL ? "textureGather" : "SampleCmpGather"; - else - sampleFunc = isGL ? "texture" : "SampleCmp"; + sampledColor->setType(GFXSCT_Float4); + sampledColor->setName(resultVarName); // The result var will be named like the sampler + meta->addStatement(new GenOp(" @", new DecOp(sampledColor))); } else { - sampleFunc = isGL ? "texture" : "Sample"; + meta->addStatement(new GenOp(" @",sampledColor)); } - - // The sampled color variable (e.g. "diffuseColor") - Var* sampledColor = new Var; - sampledColor->setType("float4"); - sampledColor->setName(samplerName); // The result var will be named like the sampler - + if (isGL) { - if (isComparison) - { - meta->addStatement(new GenOp(" @ = %s(@, @, @);\r\n", - sampledColor, sampleFunc.c_str(), textureVar, texCoord, compareValue)); - } - else - { - meta->addStatement(new GenOp(" @ = %s(@, @);\r\n", - sampledColor, sampleFunc.c_str(), textureVar, texCoord)); - } - } - else - { + // ---------------- GLSL Sampling ---------------- if (isComparison) { if (useGather) - meta->addStatement(new GenOp(" @ = @.%s(@, @, @);\r\n", - sampledColor, textureVar, sampleFunc.c_str(), samplerVar, texCoord, compareValue)); + meta->addStatement(new GenOp( + " = textureGather(@, @, @);\r\n", + samplerVar, texCoord, compareValue)); else - meta->addStatement(new GenOp(" @ = @.%s(@, @, @);\r\n", - sampledColor, textureVar, sampleFunc.c_str(), samplerVar, texCoord, compareValue)); + meta->addStatement(new GenOp( + " = texture(@, @, @);\r\n", + samplerVar, texCoord, compareValue)); } else { - meta->addStatement(new GenOp(" @ = @.%s(@, @);\r\n", - sampledColor, textureVar, sampleFunc.c_str(), samplerVar, texCoord)); + 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 (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)); } } } @@ -272,7 +295,7 @@ void DefaultTexcoordFeature::processPix(Vector& componentList, void TextureFeature::processPix(Vector& componentList, const MaterialFeatureData& fd) { // find the uv var. - Var* inTex = (Var*)LangElement::find(params->uvName); + Var* inTex = getInTexCoord(params->uvName, GFXSCT_Float2, componentList); if (!inTex) return; @@ -300,3 +323,43 @@ ShaderFeature::Resources TextureFeature::getResources(const MaterialFeatureData& return res; } + +//-------------------------------------------------------- +// NORMAL MAPPING FEATURE +//-------------------------------------------------------- + +void NormalMapFeature::processPix(Vector& 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 float3 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 *= float2(@, @);\r\n", tempNorm, params->flipX ? -1.0f : 1.0f, params->flipY ? -1.0f : 1.0f)); + + meta->addStatement(new GenOp(" @.xyz = normalize( float3( @.xy * @, @.z ) );\r\n", + tempNorm, tempNorm, params->strength, tempNorm)); + + // write back into our known variable. + meta->addStatement(new GenOp(" @ = @;\r\n", sampledColor, tempNorm)); + + output = meta; + +} diff --git a/Engine/source/shaderGen/NODE/shaderGenNodes.h b/Engine/source/shaderGen/NODE/shaderGenNodes.h index 8cef15786..b1082f3d8 100644 --- a/Engine/source/shaderGen/NODE/shaderGenNodes.h +++ b/Engine/source/shaderGen/NODE/shaderGenNodes.h @@ -22,6 +22,7 @@ DeclareFeatureType(SNF_DefaultTexCoord); DeclareFeatureType(SNF_TextureFeature); +DeclareFeatureType(SNF_NormalMapFeature); /// /// This enum is so we can map to nodes in script. @@ -30,6 +31,7 @@ enum ShaderNodeFeature_enum { eSNF_DefaultTexCoord, eSNF_TextureFeature, + eSNF_NormalMapFeature, }; DefineEnumType(ShaderNodeFeature_enum); @@ -56,6 +58,25 @@ public: LangElement* assignColor(LangElement* elem, Material::BlendOp blend, LangElement* lerpElem = NULL, ShaderFeature::OutputTarget outputTarget = ShaderFeature::DefaultTarget) override; }; + +class DefaultTexcoordFeature : public ShaderFeatureNode +{ + void processVert(Vector& componentList, + const MaterialFeatureData& fd) override; + + void processPix(Vector& componentList, + const MaterialFeatureData& fd) override; + + String getName() override + { + return "DefaultTexCoord"; + } +}; + +//-------------------------------------------------------- +// TEXTURE SAMPLER FEATURE +//-------------------------------------------------------- + /// /// Parameters for the TextureFeature /// @@ -78,6 +99,12 @@ struct TextureFeatureParams : public FeatureParamsBase const char* getFeatureParamTypeName() const override { return "TextureFeatureParams"; } + /// + /// Texture features output variable is samplerName + "_col" + /// + /// The output variable for a texture feature. + const char* getOutputVar() const override { return samplerName + "_col"; } + static void persistedFields(Vector& fields) { addParam(fields, "sampler", Offset(samplerName, TextureFeatureParams), TypeString); @@ -88,22 +115,6 @@ struct TextureFeatureParams : public FeatureParamsBase } }; -REGISTER_FEATURE_PARAMS(SNF_TextureFeature, TextureFeatureParams) - -class DefaultTexcoordFeature : public ShaderFeatureNode -{ - void processVert(Vector& componentList, - const MaterialFeatureData& fd) override; - - void processPix(Vector& componentList, - const MaterialFeatureData& fd) override; - - String getName() override - { - return "Default TexCoord"; - } -}; - class TextureFeature : public ShaderFeatureNode { private: @@ -124,7 +135,7 @@ public: void processPix(Vector& componentList, const MaterialFeatureData& fd) override; - ShaderFeature::Resources getResources(const MaterialFeatureData& fd); + ShaderFeature::Resources getResources(const MaterialFeatureData& fd) override; // create a static function on the feature class static ShaderFeature* createFunction(FeatureParamsBase* args) @@ -135,6 +146,69 @@ public: String getName() override { - return "Texture Sampler"; + return "TextureSampler_" + params->samplerName + "_" + params->uvName; + } +}; + +//-------------------------------------------------------- +// NORMAL MAPPING FEATURE +//-------------------------------------------------------- + +/// +/// Parameters for the NormalMapFeature +/// +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"; } + + /// + /// Normal map feature writes the result into the input name + /// + /// The output variable for a normal map feature. + const char* getOutputVar() const override { return inputName; } + + static void persistedFields(Vector& 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& 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(args)); + } + + String getName() override + { + return "NormalMap_" + params->inputName; } };