Implementation of reflection and skylight probes.

Moves lighting math to the diffuse/specular two-channel logic.
This commit is contained in:
Areloch 2018-09-16 22:15:07 -05:00
parent 1f7cf55204
commit b19a4b22c8
102 changed files with 12346 additions and 1911 deletions

View file

@ -670,4 +670,29 @@ public:
virtual String getName() { return "Hardware Skinning"; }
};
/// Reflection Probes
class ReflectionProbeFeatGLSL : public ShaderFeatureGLSL
{
public:
virtual void processVert(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd) {}
virtual void processPix(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd) {}
virtual Resources getResources(const MaterialFeatureData &fd) {
return Resources();
}
// Sets textures and texture flags for current pass
virtual void setTexData(Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex) {}
virtual String getName()
{
return "Reflection Probes";
}
};
#endif // _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_

View file

@ -2933,3 +2933,225 @@ void HardwareSkinningFeatureHLSL::processVert( Vector<ShaderComponent*> &compo
output = meta;
}
//****************************************************************************
// ReflectionProbeFeatHLSL
//****************************************************************************
ReflectionProbeFeatHLSL::ReflectionProbeFeatHLSL()
: mDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/lighting.hlsl"))
{
addDependency(&mDep);
}
void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd)
{
// Skip out on realtime lighting if we don't have a normal
// or we're doing some sort of baked lighting.
//
// TODO: We can totally detect for this in the material
// feature setup... we should move it out of here!
//
if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit])
return;
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
MultiLine *meta = new MultiLine;
// Look for a wsNormal or grab it from the connector.
Var *wsNormal = (Var*)LangElement::find("wsNormal");
if (!wsNormal)
{
wsNormal = connectComp->getElement(RT_TEXCOORD);
wsNormal->setName("wsNormal");
wsNormal->setStructName("IN");
wsNormal->setType("float3");
// If we loaded the normal its our responsibility
// to normalize it... the interpolators won't.
//
// Note we cast to half here to get partial precision
// optimized code which is an acceptable loss of
// precision for normals and performs much better
// on older Geforce cards.
//
meta->addStatement(new GenOp(" @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal));
}
// Now the wsPosition and wsView.
Var *wsPosition = getInWsPosition(componentList);
Var *wsView = getWsView(wsPosition, meta);
Var *metalness = (Var*)LangElement::find("metalness");
Var *smoothness = (Var*)LangElement::find("smoothness");
if (!fd.features[MFT_SpecularMap])
{
if (!metalness)
{
metalness = new Var("metalness", "float");
metalness->uniform = true;
metalness->constSortPos = cspPotentialPrimitive;
}
if (!smoothness)
{
smoothness = new Var("smoothness", "float");
smoothness->uniform = true;
smoothness->constSortPos = cspPotentialPrimitive;
}
}
Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
//Reflection Probe WIP
Var *inProbePos = new Var("inProbePos", "float3");
inProbePos->arraySize = 4;
inProbePos->uniform = true;
inProbePos->constSortPos = cspPotentialPrimitive;
Var *inProbeRadius = new Var("inProbeRadius", "float");
inProbeRadius->arraySize = 4;
inProbeRadius->uniform = true;
inProbeRadius->constSortPos = cspPotentialPrimitive;
Var *inProbeBoxMin = new Var("inProbeBoxMin", "float3");
inProbeBoxMin->arraySize = 4;
inProbeBoxMin->uniform = true;
inProbeBoxMin->constSortPos = cspPotentialPrimitive;
Var *inProbeBoxMax = new Var("inProbeBoxMax", "float3");
inProbeBoxMax->arraySize = 4;
inProbeBoxMax->uniform = true;
inProbeBoxMax->constSortPos = cspPotentialPrimitive;
Var *inProbeIsSphere = new Var("inProbeIsSphere", "float");
inProbeIsSphere->arraySize = 4;
inProbeIsSphere->uniform = true;
inProbeIsSphere->constSortPos = cspPotentialPrimitive;
Var *inProbeLocalPos = new Var("inProbeLocalPos", "float3");
inProbeLocalPos->arraySize = 4;
inProbeLocalPos->uniform = true;
inProbeLocalPos->constSortPos = cspPotentialPrimitive;
Var *inProbeCubemap = new Var("inProbeCubemap", "SamplerState");
//inProbeCubemap->arraySize = 4;
inProbeCubemap->uniform = true;
inProbeCubemap->sampler = true;
inProbeCubemap->constNum = Var::getTexUnitNum(); // used as texture unit num here
Var *inProbeCubemapTex = new Var("inProbeCubemapTex", "TextureCube");
//inProbeCubemapTex->arraySize = 4;
inProbeCubemapTex->uniform = true;
inProbeCubemapTex->texture = true;
inProbeCubemapTex->constNum = inProbeCubemap->constNum;
//Var *nDotL = new Var("nDotL", "float3");
//meta->addStatement(new GenOp(" @ = abs(dot(@,@);\r\n", new DecOp(nDotL), wsView, wsNormal));
Var *probeVec = new Var("probeVec", "float3");
meta->addStatement(new GenOp(" @ = @[0] - @;\r\n", new DecOp(probeVec), inProbePos, wsPosition));
Var *nDotL = new Var("nDotL", "float");
meta->addStatement(new GenOp(" @ = abs(dot(@, @));\r\n", new DecOp(nDotL), probeVec, wsNormal));
meta->addStatement(new GenOp(" \r\n"));
Var *reflectDir = new Var("reflectDir", "float3");
meta->addStatement(new GenOp(" @ = reflect(-float4(@,0),float4(@,@)).xyz;\r\n", new DecOp(reflectDir), wsView, wsNormal, nDotL));
meta->addStatement(new GenOp(" \r\n"));
Var *nrDir = new Var("nrDir", "float3");
meta->addStatement(new GenOp(" @ = normalize(@);\r\n", new DecOp(nrDir), reflectDir));
Var *rbmax = new Var("rbmax", "float3");
meta->addStatement(new GenOp(" @ = (@[0] - @) / @;\r\n", new DecOp(rbmax), inProbeBoxMax, wsPosition, nrDir));
Var *rbmin = new Var("rbmin", "float3");
meta->addStatement(new GenOp(" @ = (@[0] - @) / @;\r\n", new DecOp(rbmin), inProbeBoxMin, wsPosition, nrDir));
Var *rbMinMax = new Var("rbMinMax", "float3");
meta->addStatement(new GenOp(" @ = (@ > 0.0) ? @ : @;\r\n", new DecOp(rbMinMax), nrDir, rbmax, rbmin));
meta->addStatement(new GenOp(" \r\n"));
Var *fa = new Var("fa", "float3");
meta->addStatement(new GenOp(" @ = min(min(@.x,@.y),@.z);\r\n", new DecOp(fa), rbMinMax, rbMinMax, rbMinMax));
meta->addStatement(new GenOp("/* if (dot( @, @ ) < 0.0f)\r\n", probeVec, wsNormal));
meta->addStatement(new GenOp(" clip(@); */\r\n", fa));
meta->addStatement(new GenOp(" \r\n"));
Var *posOnBox = new Var("posOnBox", "float3");
meta->addStatement(new GenOp(" @ = @ + @ * @;\r\n", new DecOp(posOnBox), wsPosition, nrDir, fa));
meta->addStatement(new GenOp(" @ = @ - @[0];\r\n", reflectDir, posOnBox, inProbePos));
meta->addStatement(new GenOp(" \r\n"));
Var *probeColor = new Var("wipProbeColor", "float3");
Var *probeMip = new Var("probeMip", "float");
meta->addStatement(new GenOp(" @ = min((1.0 - @)*11.0 + 1.0, 8.0);\r\n", new DecOp(probeMip), smoothness));
meta->addStatement(new GenOp(" @ = @.SampleLevel(@, @, @).rgb;\r\n", new DecOp(probeColor), inProbeCubemapTex, inProbeCubemap, reflectDir, probeMip));
//meta->addStatement(new GenOp(" @ = @.rgb;\r\n", new DecOp(probeColor), inProbeTestColor));
Var *FRESNEL_BIAS = new Var("FRESNEL_BIAS", "float");
meta->addStatement(new GenOp(" @ = 0.1;\r\n", new DecOp(FRESNEL_BIAS)));
Var *FRESNEL_POWER = new Var("FRESNEL_POWER", "float");
meta->addStatement(new GenOp(" @ = 1;\r\n", new DecOp(FRESNEL_POWER)));
Var *angle = new Var("angle", "float");
meta->addStatement(new GenOp(" @ = saturate(dot(@, @));\r\n", new DecOp(angle), wsView, wsNormal));
meta->addStatement(new GenOp("\r\n"));
if (metalness)
{
Var *dColor = new Var("difColor", "float3");
Var *reflectColor = new Var("reflctColor", "float3");
meta->addStatement(new GenOp(" @ = @.rgb - (@.rgb * @);\r\n", new DecOp(dColor), albedo, albedo, metalness));
meta->addStatement(new GenOp(" @ = @; //@.rgb*(@).rgb*@;\r\n", new DecOp(reflectColor), probeColor, albedo, probeColor, metalness));
meta->addStatement(new GenOp(" @.rgb = simpleFresnel(@, @, @, @, @, @);\r\n", albedo, dColor, reflectColor, metalness, angle, FRESNEL_BIAS, FRESNEL_POWER));
}
//else if (lerpVal)
// meta->addStatement(new GenOp(" @ *= float4(@.rgb*@.a, @.a);\r\n", targ, texCube, lerpVal, targ));
else
{
meta->addStatement(new GenOp(" @.rgb = simpleFresnel(@.rgb, @, 0, @, @, @));\r\n", albedo, albedo, probeColor, angle, FRESNEL_BIAS, FRESNEL_POWER));
}
output = meta;
}
ShaderFeature::Resources ReflectionProbeFeatHLSL::getResources(const MaterialFeatureData &fd)
{
Resources res;
//res.numTex = 4;
//res.numTexReg = 4;
res.numTex = 4;
res.numTexReg = 4;
return res;
}
void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat,
const MaterialFeatureData &stageFeatures,
RenderPassData &passData,
U32 &texIndex)
{
if (stageFeatures.features[MFT_ReflectionProbes])
{
// assuming here that it is a scenegraph cubemap
passData.mSamplerNames[texIndex] = "inProbeCubemap";
passData.mTexType[texIndex++] = Material::SGCube;
}
}

View file

@ -672,4 +672,30 @@ public:
virtual String getName() { return "Hardware Skinning"; }
};
/// Reflection Probes
class ReflectionProbeFeatHLSL : public ShaderFeatureHLSL
{
protected:
ShaderIncludeDependency mDep;
public:
ReflectionProbeFeatHLSL();
virtual void processPix(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd);
virtual Resources getResources(const MaterialFeatureData &fd);
// Sets textures and texture flags for current pass
virtual void setTexData(Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex);
virtual String getName()
{
return "Reflection Probes";
}
};
#endif // _SHADERGEN_HLSL_SHADERFEATUREHLSL_H_

View file

@ -64,6 +64,7 @@ void _initShaderGenHLSL( ShaderGen *shaderGen )
FEATUREMGR->registerFeature( MFT_DetailMap, new DetailFeatHLSL );
FEATUREMGR->registerFeature( MFT_StaticCubemap, new NamedFeatureHLSL( "Static Cubemap" ) );
FEATUREMGR->registerFeature( MFT_CubeMap, new ReflectCubeFeatHLSL );
FEATUREMGR->registerFeature( MFT_ReflectionProbes, new ReflectionProbeFeatHLSL);
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL );
FEATUREMGR->registerFeature( MFT_InvertSmoothness, new NamedFeatureHLSL( "Roughest = 1.0" ) );
FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureHLSL( "Translucent" ) );

View file

@ -68,6 +68,15 @@ const String ShaderGenVars::specularColor("$specularColor");
const String ShaderGenVars::smoothness("$smoothness");
const String ShaderGenVars::metalness("$metalness");
//Reflection Probes
const String ShaderGenVars::probePosition("$inProbePos");
const String ShaderGenVars::probeRadius("$inProbeRadius");
const String ShaderGenVars::probeBoxMin("$inProbeBoxMin");
const String ShaderGenVars::probeBoxMax("$inProbeBoxMax");
const String ShaderGenVars::probeLocalPos("$inProbeLocalPos");
const String ShaderGenVars::probeIsSphere("$inProbeIsSphere");
const String ShaderGenVars::probeCubemap("$inProbeCubemap");
// These are ignored by the D3D layers.
const String ShaderGenVars::fogMap("$fogMap");
const String ShaderGenVars::dlightMap("$dlightMap");

View file

@ -80,6 +80,15 @@ struct ShaderGenVars
const static String specularColor;
const static String smoothness;
const static String metalness;
//Reflection Probes
const static String probePosition;
const static String probeRadius;
const static String probeBoxMin;
const static String probeBoxMax;
const static String probeLocalPos;
const static String probeIsSphere;
const static String probeCubemap;
// Textures
const static String fogMap;