output vars

add output vars to the param types
fixed gl bug need samplertype
This commit is contained in:
marauder2k7 2025-11-26 05:16:26 +00:00
parent 7d3b4d8ac9
commit dfbea4540d
2 changed files with 206 additions and 69 deletions

View file

@ -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<Var*>(LangElement::find(texVarName));
Var* samplerVar = dynamic_cast<Var*>(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<Var*>(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<ShaderComponent*>& componentList,
void TextureFeature::processPix(Vector<ShaderComponent*>& 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<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 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;
}

View file

@ -22,6 +22,7 @@
DeclareFeatureType(SNF_DefaultTexCoord);
DeclareFeatureType(SNF_TextureFeature);
DeclareFeatureType(SNF_NormalMapFeature);
/// <summary>
/// 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<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>
@ -78,6 +99,12 @@ struct TextureFeatureParams : public FeatureParamsBase
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);
@ -88,22 +115,6 @@ struct TextureFeatureParams : public FeatureParamsBase
}
};
REGISTER_FEATURE_PARAMS(SNF_TextureFeature, TextureFeatureParams)
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 "Default TexCoord";
}
};
class TextureFeature : public ShaderFeatureNode
{
private:
@ -124,7 +135,7 @@ public:
void processPix(Vector<ShaderComponent*>& 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
//--------------------------------------------------------
/// <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;
}
};