A clean implementation of Lukas' Fix side projection #684 PR with Az's addendum fix rolled in

This commit is contained in:
JeffR 2021-12-13 15:56:14 -06:00
parent 1f4c488640
commit 434c6c26fe
3 changed files with 147 additions and 359 deletions

View file

@ -223,29 +223,16 @@ void TerrainBaseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis
output = meta; output = meta;
// Generate the incoming texture var. // Generate the incoming texture var.
Var *inTex; Var* inPos = (Var*)LangElement::find("inPosition");
{ if (!inPos)
Var *inPos = (Var*)LangElement::find( "inPosition" ); inPos = (Var*)LangElement::find("position");
if ( !inPos )
inPos = (Var*)LangElement::find( "position" );
inTex = new Var( "texCoord", "vec3" ); Var* inTex = new Var("texCoord", "vec3");
Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass ); Var* oneOverTerrainSize = _getUniformVar("oneOverTerrainSize", "float", cspPass);
// NOTE: The y coord here should be negative to have meta->addStatement(new GenOp(" @ = @.xyz * vec3( @, @, @ );\r\n",
// the texture maps not end up flipped which also caused new DecOp(inTex), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize));
// normal and parallax mapping to be incorrect.
//
// This mistake early in development means that the layer
// id bilinear blend depends on it being that way.
//
// So instead i fixed this by flipping the base and detail
// coord y scale to compensate when rendering.
//
meta->addStatement( new GenOp( " @ = @.xyz * vec3( @, @, -@ );\r\n",
new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
}
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
@ -253,21 +240,27 @@ void TerrainBaseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis
Var *outTex = connectComp->getElement( RT_TEXCOORD ); Var *outTex = connectComp->getElement( RT_TEXCOORD );
outTex->setName( "outTexCoord" ); outTex->setName( "outTexCoord" );
outTex->setStructName( "OUT" ); outTex->setStructName( "OUT" );
outTex->setType( "vec3" ); outTex->setType( "vec4" );
meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) ); meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) );
// If this shader has a side projected layer then we // If this shader has a side projected layer then we
// pass the dot product between the +Y and the normal // pass the dot product between the +Y and the normal
// thru outTexCoord.z for use in blending the textures. // thru outTexCoord.z and w for use in blending the textures.
if ( fd.features.hasFeature( MFT_TerrainSideProject ) ) if ( fd.features.hasFeature( MFT_TerrainSideProject ) )
{ {
Var *inNormal = (Var*)LangElement::find( "normal" ); Var* inNormal = (Var*)LangElement::find("normal");
meta->addStatement(
new GenOp(" @.z = clamp(abs( dot( normalize( vec3( @.x, @.y, 0 ) ), vec3( 0, 1, 0 ) ) ), 0.0, 1.0);\r\n",
outTex, inNormal, inNormal));
meta->addStatement( meta->addStatement(
new GenOp( " @.z = pow( abs( dot( normalize( vec3( @.x, @.y, 0 ) ), vec3( 0, 1, 0 ) ) ), 10.0 );\r\n", new GenOp(" @.w = 1.0 - abs( dot( normalize( @.xyz ), vec3( 0, 0, 1 ) ) );\r\n",
outTex, inNormal, inNormal ) ); outTex, inNormal));
} }
else else
meta->addStatement( new GenOp( " @.z = 0;\r\n", outTex ) ); {
meta->addStatement(new GenOp(" @.z = 0;\r\n", outTex));
meta->addStatement(new GenOp(" @.w = 0;\r\n", outTex));
}
// HACK: This is sort of lazy... we generate the tanget // HACK: This is sort of lazy... we generate the tanget
// vector here so that we're sure it exists in the parallax // vector here so that we're sure it exists in the parallax
@ -289,7 +282,7 @@ void TerrainBaseMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentLis
const MaterialFeatureData &fd ) const MaterialFeatureData &fd )
{ {
// grab connector texcoord register // grab connector texcoord register
Var *texCoord = getInTexCoord( "texCoord", "vec3", componentList ); Var *texCoord = getInTexCoord( "texCoord", "vec4", componentList );
// create texture var // create texture var
Var *diffuseMap = new Var; Var *diffuseMap = new Var;
@ -446,8 +439,8 @@ void TerrainDetailMapFeatGLSL::processVert( Vector<ShaderComponent*> &component
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) ); meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) );
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)) ); outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)));
output = meta; output = meta;
} }
@ -562,8 +555,12 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// amount so that it fades out with the layer blending. // amount so that it fades out with the layer blending.
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{ {
meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, vec3(@.xy, @.x) ), lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z ), @.w) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet, new IndexOp(detailInfo, detailIndex), detailMap, inDet, new IndexOp(detailInfo, detailIndex), inTex)); detailColor,
detailMap, inDet, new IndexOp(detailInfo, detailIndex),
detailMap, inDet, new IndexOp(detailInfo, detailIndex),
detailMap, inDet, new IndexOp(detailInfo, detailIndex),
inTex, inTex));
} }
else else
{ {
@ -574,7 +571,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement(new GenOp(" @ *= @.y * @.w;\r\n", meta->addStatement(new GenOp(" @ *= @.y * @.w;\r\n",
detailColor, new IndexOp(detailInfo, detailIndex), inDet)); detailColor, new IndexOp(detailInfo, detailIndex), inDet));
if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) if (!fd.features.hasFeature(MFT_TerrainNormalMap))
{ {
// Check to see if we have a gbuffer normal. // Check to see if we have a gbuffer normal.
Var* gbNormal = (Var*)LangElement::find("gbNormal"); Var* gbNormal = (Var*)LangElement::find("gbNormal");
@ -834,8 +831,12 @@ void TerrainMacroMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentL
// //
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) ) if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
{ {
meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, vec3(@.xy, @.x) ), lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z ), @.w) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet, detailMap, inDet, inTex ) ); detailColor,
detailMap, inDet, new IndexOp(detailInfo, detailIndex),
detailMap, inDet, new IndexOp(detailInfo, detailIndex),
detailMap, inDet, new IndexOp(detailInfo, detailIndex),
inTex, inTex));
} }
else else
{ {
@ -940,8 +941,11 @@ void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
LangElement *texOp; LangElement *texOp;
if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) ) if ( fd.features.hasFeature( MFT_TerrainSideProject, normalIndex ) )
{ {
texOp = new GenOp( "lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z )", texOp = new GenOp("lerp( tex2D( @, float3(@.xy, @.x) ), lerp( tex2D( @, float3(@.yz, @.x) ), tex2D( @, float3(@.xz, @.x) ), @.z ), @.w )",
normalMap, inDet, new IndexOp(detailInfo, normalIndex), normalMap, inDet, inTex, new IndexOp(detailInfo, normalIndex)); normalMap, inDet, new IndexOp(detailInfo, normalIndex),
normalMap, inDet, new IndexOp(detailInfo, normalIndex),
normalMap, inDet, new IndexOp(detailInfo, normalIndex),
inTex, inTex);
} }
else else
texOp = new GenOp( String::ToString("tex2D(@, vec3(@.xy, @.x))", normalIndex), normalMap, inDet, new IndexOp(detailInfo, normalIndex)); texOp = new GenOp( String::ToString("tex2D(@, vec3(@.xy, @.x))", normalIndex), normalMap, inDet, new IndexOp(detailInfo, normalIndex));
@ -954,7 +958,7 @@ void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
LangElement *bumpNormDecl = new DecOp( bumpNorm ); LangElement *bumpNormDecl = new DecOp( bumpNorm );
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) ); meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) if (!fd.features.hasFeature(MFT_TerrainNormalMap))
{ {
Var* viewToTangent = getInViewToTangent(componentList); Var* viewToTangent = getInViewToTangent(componentList);
@ -1059,100 +1063,22 @@ ShaderFeature::Resources TerrainLightMapFeatGLSL::getResources( const MaterialFe
return res; return res;
} }
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
//.b = specular strength, a= spec power.
void TerrainORMMapFeatGLSL::processVert(Vector<ShaderComponent*> &componentList, void TerrainORMMapFeatGLSL::processVert(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd) const MaterialFeatureData &fd)
{ {
const S32 detailIndex = getProcessIndex(); // We only need to process normals during the deferred.
if (!fd.features.hasFeature(MFT_DeferredConditioner))
return;
// Grab incoming texture coords... the base map feature MultiLine* meta = new MultiLine;
// made sure this was created.
Var *inTex = (Var*)LangElement::find("texCoord");
AssertFatal(inTex, "The texture coord is missing!");
// Grab the input position. if (!fd.features.hasFeature(MFT_TerrainHeightBlend))
Var *inPos = (Var*)LangElement::find("inPosition");
if (!inPos)
inPos = (Var*)LangElement::find("position");
// Get the object space eye position.
Var *eyePos = _getUniformVar("eyePos", "vec3", cspPotentialPrimitive);
MultiLine *meta = new MultiLine;
// If we have parallax mapping then make sure we've sent
// the negative view vector to the pixel shader.
if (fd.features.hasFeature(MFT_TerrainParallaxMap) &&
!LangElement::find("outNegViewTS"))
{ {
// Get the object to tangent transform which // Make sure the world to tangent transform
// will consume 3 output registers. // is created and available for the pixel shader.
Var *objToTangentSpace = getOutObjToTangentSpace(componentList, meta, fd); getOutViewToTangent(componentList, meta, fd);
// Now use a single output register to send the negative
// view vector in tangent space to the pixel shader.
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
Var *outNegViewTS = connectComp->getElement(RT_TEXCOORD);
outNegViewTS->setName("outNegViewTS");
outNegViewTS->setStructName("OUT");
outNegViewTS->setType("vec3");
meta->addStatement(new GenOp(" @ = @ * vec3( @ - @.xyz );\r\n",
outNegViewTS, objToTangentSpace, eyePos, inPos));
} }
// Get the distance from the eye to this vertex.
Var *dist = (Var*)LangElement::find("dist");
if (!dist)
{
dist = new Var;
dist->setType("float");
dist->setName("dist");
meta->addStatement(new GenOp(" @ = distance( @.xyz, @ );\r\n",
new DecOp(dist), inPos, eyePos));
}
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex));
if (outTex == NULL)
{
outTex = new Var;
outTex = connectComp->getElement(RT_TEXCOORD);
outTex->setName(String::ToString("detCoord%d", detailIndex));
outTex->setStructName("OUT");
outTex->setType("vec4");
}
// Get the detail scale and fade info.
Var *detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade");
if (detScaleAndFade == NULL)
{
detScaleAndFade = new Var;
detScaleAndFade->setType("vec4");
detScaleAndFade->setName("detailScaleAndFade");
detScaleAndFade->uniform = true;
detScaleAndFade->constSortPos = cspPotentialPrimitive;
}
detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord.
//
// NOTE: You see here we scale the texture coord by 'xyx'
// to generate the detail coord. This y is here because
// its scale is flipped to correct for the non negative y
// in texCoord.
//
// See TerrainBaseMapFeatGLSL::processVert().
//
meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex)));
// And sneak the detail fade thru the w detailCoord.
meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)));
output = meta; output = meta;
} }
@ -1180,8 +1106,11 @@ void TerrainORMMapFeatGLSL::processPix(Vector<ShaderComponent*> &componentList,
if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex))
{ {
texOp = new GenOp("lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z )", texOp = new GenOp("lerp( tex2D( @, vec3(@.xy, @.x) ), lerp( tex2D( @, vec3(@.yz, @.x) ), tex2D( @, vec3(@.xz, @.x) ), @.z ), @.w )",
ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex), ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex), inTex); ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex),
ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex),
ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex),
inTex, inTex);
} }
else else
texOp = new GenOp("tex2D(@, vec3(@.xy, @.x))", ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex)); texOp = new GenOp("tex2D(@, vec3(@.xy, @.x))", ormConfigMap, inDet, new IndexOp(detailInfo, compositeIndex));
@ -1332,6 +1261,13 @@ void TerrainHeightMapBlendGLSL::processPix(Vector<ShaderComponent*>& componentLi
MultiLine* meta = new MultiLine; MultiLine* meta = new MultiLine;
Var* detailTot = (Var*)LangElement::find("detailTot");
if (detailTot == NULL)
{
detailTot = new Var("detailTot", "float");
meta->addStatement(new GenOp("@=0;\r\n", new DecOp(detailTot)));
}
// Count the number of detail textures // Count the number of detail textures
int detailCount = 0; int detailCount = 0;
while (true) while (true)
@ -1391,11 +1327,11 @@ void TerrainHeightMapBlendGLSL::processPix(Vector<ShaderComponent*>& componentLi
} }
else else
{ {
meta->addStatement(new GenOp(" @ = clamp(0.5 + @, 0.0, 1.0);\r\n", meta->addStatement(new GenOp(" @ = clamp(@, 0.0, 1.0);\r\n",
detailH, blendDepth)); detailH, blendDepth));
} }
meta->addStatement(new GenOp(" @ = max((@ * 2.0f - 1.0f) * @ + 0.5f, 0.0f);\r\n", meta->addStatement(new GenOp(" @ = max((@ * 2.0f - 1.0f) * @, 0.0f);\r\n",
detailH, detailH, blendContrast)); detailH, detailH, blendContrast));
meta->addStatement(new GenOp(" }\r\n")); meta->addStatement(new GenOp(" }\r\n"));
@ -1453,6 +1389,7 @@ void TerrainHeightMapBlendGLSL::processPix(Vector<ShaderComponent*>& componentLi
meta->addStatement(new GenOp(" @ = max(@ + @ - @, 0);\r\n", meta->addStatement(new GenOp(" @ = max(@ + @ - @, 0);\r\n",
new DecOp(detailB), detailH, detailBlend, ma)); new DecOp(detailB), detailH, detailBlend, ma));
} }
meta->addStatement(new GenOp(" @ += @;\r\n", detailTot, detailB));
} }
meta->addStatement(new GenOp("\r\n")); meta->addStatement(new GenOp("\r\n"));
@ -1478,22 +1415,7 @@ void TerrainHeightMapBlendGLSL::processPix(Vector<ShaderComponent*>& componentLi
meta->addStatement(new GenOp("@.rgb * @", detailColor, detailB)); meta->addStatement(new GenOp("@.rgb * @", detailColor, detailB));
} }
meta->addStatement(new GenOp(") / (")); meta->addStatement(new GenOp(") / @;\r\n", detailTot));
for (S32 idx = 0; idx < detailCount; ++idx)
{
Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx));
if (idx > 0)
{
meta->addStatement(new GenOp(" + "));
}
meta->addStatement(new GenOp("@", detailB));
}
meta->addStatement(new GenOp(");\r\n"));
meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n", meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n",
outColor, outColor)); outColor, outColor));
@ -1532,23 +1454,7 @@ void TerrainHeightMapBlendGLSL::processPix(Vector<ShaderComponent*>& componentLi
} }
} }
meta->addStatement(new GenOp(") / (")); meta->addStatement(new GenOp(") / @;\r\n", detailTot));
for (S32 idx = 0; idx < detailCount; ++idx)
{
Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx));
if (idx > 0)
{
meta->addStatement(new GenOp(" + "));
}
meta->addStatement(new GenOp("@", detailB));
}
meta->addStatement(new GenOp(");\r\n"));
meta->addStatement(new GenOp("\r\n")); meta->addStatement(new GenOp("\r\n"));
@ -1635,22 +1541,7 @@ void TerrainHeightMapBlendGLSL::processPix(Vector<ShaderComponent*>& componentLi
} }
} }
meta->addStatement(new GenOp(") / (")); meta->addStatement(new GenOp(") / @;\r\n", detailTot));
for (S32 idx = 0; idx < detailCount; ++idx)
{
Var* normalDetailB = (Var*)LangElement::find(String::ToString("normalDetailB%d", idx));
if (idx > 0)
{
meta->addStatement(new GenOp(" + "));
}
meta->addStatement(new GenOp("@", normalDetailB));
}
meta->addStatement(new GenOp(");\r\n"));
} }

View file

@ -270,58 +270,52 @@ Var* TerrainFeatHLSL::_getMacroIdStrengthParallax()
} }
void TerrainBaseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, void TerrainBaseMapFeatHLSL::processVert(Vector<ShaderComponent*>& componentList,
const MaterialFeatureData &fd ) const MaterialFeatureData& fd)
{ {
MultiLine *meta = new MultiLine; MultiLine* meta = new MultiLine;
output = meta; output = meta;
// Generate the incoming texture var. // Generate the incoming texture var.
Var *inTex;
{
Var *inPos = (Var*)LangElement::find( "inPosition" );
if ( !inPos )
inPos = (Var*)LangElement::find( "position" );
inTex = new Var( "texCoord", "float3" ); Var* inPos = (Var*)LangElement::find("inPosition");
if (!inPos)
inPos = (Var*)LangElement::find("position");
Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass ); Var* inTex = new Var("texCoord", "float3");
// NOTE: The y coord here should be negative to have Var* oneOverTerrainSize = _getUniformVar("oneOverTerrainSize", "float", cspPass);
// the texture maps not end up flipped which also caused
// normal and parallax mapping to be incorrect.
//
// This mistake early in development means that the layer
// id bilinear blend depends on it being that way.
//
// So instead i fixed this by flipping the base and detail
// coord y scale to compensate when rendering.
//
meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n",
new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
}
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); meta->addStatement(new GenOp(" @ = @.xyz * @;\r\n",
new DecOp(inTex), inPos, oneOverTerrainSize));
ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]);
// Pass the texture coord to the pixel shader. // Pass the texture coord to the pixel shader.
Var *outTex = connectComp->getElement( RT_TEXCOORD ); Var* outTex = connectComp->getElement(RT_TEXCOORD);
outTex->setName( "outTexCoord" ); outTex->setName("outTexCoord");
outTex->setStructName( "OUT" ); outTex->setStructName("OUT");
outTex->setType( "float3" ); outTex->setType("float4");
meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) ); meta->addStatement(new GenOp(" @.xy = @.xy;\r\n", outTex, inTex));
// If this shader has a side projected layer then we // If this shader has a side projected layer then we
// pass the dot product between the +Y and the normal // pass the dot product between the +Y and the normal
// thru outTexCoord.z for use in blending the textures. // thru outTexCoord.z for use in blending the textures.
if ( fd.features.hasFeature( MFT_TerrainSideProject ) ) if (fd.features.hasFeature(MFT_TerrainSideProject))
{ {
Var *inNormal = (Var*)LangElement::find( "normal" ); Var* inNormal = (Var*)LangElement::find("normal");
meta->addStatement( meta->addStatement(
new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n", new GenOp(" @.z = clamp(abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 0.0, 1.0);\r\n",
outTex, inNormal, inNormal ) ); outTex, inNormal, inNormal));
meta->addStatement(
new GenOp(" @.w = 1.0 - abs( dot( normalize( @.xyz ), float3( 0, 0, 1 ) ) );\r\n",
outTex, inNormal));
} }
else else
meta->addStatement( new GenOp( " @.z = 0;\r\n", outTex ) ); {
meta->addStatement(new GenOp(" @.z = 0;\r\n", outTex));
meta->addStatement(new GenOp(" @.w = 0;\r\n", outTex));
}
// HACK: This is sort of lazy... we generate the tanget // HACK: This is sort of lazy... we generate the tanget
// vector here so that we're sure it exists in the parallax // vector here so that we're sure it exists in the parallax
@ -341,7 +335,7 @@ void TerrainBaseMapFeatHLSL::processPix(Vector<ShaderComponent*>& componentList,
const MaterialFeatureData& fd) const MaterialFeatureData& fd)
{ {
// grab connector texcoord register // grab connector texcoord register
Var* texCoord = getInTexCoord("texCoord", "float3", componentList); Var *texCoord = getInTexCoord( "texCoord", "float4", componentList );
// create texture var // create texture var
Var* diffuseMap = new Var; Var* diffuseMap = new Var;
@ -501,8 +495,8 @@ void TerrainDetailMapFeatHLSL::processVert( Vector<ShaderComponent*> &component
meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) ); meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) );
// And sneak the detail fade thru the w detailCoord. // And sneak the detail fade thru the w detailCoord.
meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)) ); outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)));
output = meta; output = meta;
} }
@ -623,8 +617,12 @@ void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{ {
meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.xy, @.x) ), lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ), @.w) * 2.0 ) - 1.0;\r\n",
detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), inTex)); detailColor,
detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex),
detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex),
detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex),
inTex, inTex));
} }
else else
{ {
@ -635,7 +633,7 @@ void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement(new GenOp(" @ *= @.y * @.w;\r\n", meta->addStatement(new GenOp(" @ *= @.y * @.w;\r\n",
detailColor, new IndexOp(detailInfo, detailIndex), inDet)); detailColor, new IndexOp(detailInfo, detailIndex), inDet));
if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) if (!fd.features.hasFeature(MFT_TerrainNormalMap))
{ {
// Check to see if we have a gbuffer normal. // Check to see if we have a gbuffer normal.
Var* gbNormal = (Var*)LangElement::find("gbNormal"); Var* gbNormal = (Var*)LangElement::find("gbNormal");
@ -902,8 +900,12 @@ void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentL
// //
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{ {
meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n", meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.xy, @.x) ), lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ), @.w ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), inTex)); detailColor,
detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex),
detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex),
detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex),
inTex, inTex));
} }
else else
{ {
@ -1007,8 +1009,11 @@ void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex))
{ {
texOp = new GenOp("lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z )", texOp = new GenOp("lerp( @.Sample( @, float3(@.xy, @.x) ), lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ), @.w )",
normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex), normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex), inTex); normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex),
normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex),
normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex),
inTex, inTex);
} }
else else
texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex)); texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex));
@ -1021,7 +1026,7 @@ void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &component
LangElement* bumpNormDecl = new DecOp(bumpNorm); LangElement* bumpNormDecl = new DecOp(bumpNorm);
meta->addStatement(expandNormalMap(texOp, bumpNormDecl, bumpNorm, fd)); meta->addStatement(expandNormalMap(texOp, bumpNormDecl, bumpNorm, fd));
if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) if (!fd.features.hasFeature(MFT_TerrainNormalMap))
{ {
Var* viewToTangent = getInViewToTangent(componentList); Var* viewToTangent = getInViewToTangent(componentList);
@ -1131,98 +1136,22 @@ ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFe
return res; return res;
} }
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
//.b = specular strength, a= spec power.
void TerrainORMMapFeatHLSL::processVert(Vector<ShaderComponent*> &componentList, void TerrainORMMapFeatHLSL::processVert(Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd) const MaterialFeatureData &fd)
{ {
const S32 detailIndex = getProcessIndex(); // We only need to process normals during the deferred.
if (!fd.features.hasFeature(MFT_DeferredConditioner))
return;
// Grab incoming texture coords... the base map feature MultiLine* meta = new MultiLine;
// made sure this was created.
Var *inTex = (Var*)LangElement::find("texCoord");
AssertFatal(inTex, "The texture coord is missing!");
// Grab the input position. if (!fd.features.hasFeature(MFT_TerrainHeightBlend))
Var *inPos = (Var*)LangElement::find("inPosition");
if (!inPos)
inPos = (Var*)LangElement::find("position");
// Get the object space eye position.
Var *eyePos = _getUniformVar("eyePos", "float3", cspPotentialPrimitive);
MultiLine *meta = new MultiLine;
// If we have parallax mapping then make sure we've sent
// the negative view vector to the pixel shader.
if (fd.features.hasFeature(MFT_TerrainParallaxMap) &&
!LangElement::find("outNegViewTS"))
{ {
// Get the object to tangent transform which // Make sure the world to tangent transform
// will consume 3 output registers. // is created and available for the pixel shader.
Var *objToTangentSpace = getOutObjToTangentSpace(componentList, meta, fd); getOutViewToTangent(componentList, meta, fd);
// Now use a single output register to send the negative
// view vector in tangent space to the pixel shader.
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
Var *outNegViewTS = connectComp->getElement(RT_TEXCOORD);
outNegViewTS->setName("outNegViewTS");
outNegViewTS->setStructName("OUT");
outNegViewTS->setType("float3");
meta->addStatement(new GenOp(" @ = mul( @, float3( @ - @.xyz ) );\r\n",
outNegViewTS, objToTangentSpace, eyePos, inPos));
} }
// Get the distance from the eye to this vertex.
Var *dist = (Var*)LangElement::find("dist");
if (!dist)
{
dist = new Var;
dist->setType("float");
dist->setName("dist");
meta->addStatement(new GenOp(" @ = distance( @.xyz, @ );\r\n",
new DecOp(dist), inPos, eyePos));
}
// grab connector texcoord register
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex));
if (outTex == NULL)
{
outTex = connectComp->getElement(RT_TEXCOORD);
outTex->setName(String::ToString("detCoord%d", detailIndex));
outTex->setStructName("OUT");
outTex->setType("float4");
}
// Get the detail scale and fade info.
Var *detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade");
if (detScaleAndFade == NULL)
{
detScaleAndFade = new Var;
detScaleAndFade->setType("float4");
detScaleAndFade->setName("detailScaleAndFade");
detScaleAndFade->uniform = true;
detScaleAndFade->constSortPos = cspPotentialPrimitive;
}
detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1);
// Setup the detail coord.
//
// NOTE: You see here we scale the texture coord by 'xyx'
// to generate the detail coord. This y is here because
// its scale is flipped to correct for the non negative y
// in texCoord.
//
// See TerrainBaseMapFeatHLSL::processVert().
//
meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex)));
// And sneak the detail fade thru the w detailCoord.
meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)));
output = meta; output = meta;
} }
@ -1251,8 +1180,11 @@ void TerrainORMMapFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
Var* ormMapSampler = _getOrmMapSampler(); Var* ormMapSampler = _getOrmMapSampler();
if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex)) if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex))
{ {
texOp = new GenOp("lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z )", texOp = new GenOp("lerp( @.Sample( @, float3(@.xy, @.x) ), lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ), @.w )",
ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex), ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex), inTex); ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex),
ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex),
ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex),
inTex, inTex);
} }
else else
texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex)); texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex));
@ -1402,6 +1334,13 @@ void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentLi
MultiLine* meta = new MultiLine; MultiLine* meta = new MultiLine;
Var* detailTot = (Var*)LangElement::find("detailTot");
if (detailTot == NULL)
{
detailTot = new Var("detailTot","float");
meta->addStatement(new GenOp("@=0;\r\n", new DecOp(detailTot)));
}
// Count number of detail layers // Count number of detail layers
int detailCount = 0; int detailCount = 0;
while (true) while (true)
@ -1461,11 +1400,11 @@ void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentLi
} }
else else
{ {
meta->addStatement(new GenOp(" @ = clamp(0.5 + @, 0.0, 1.0);\r\n", meta->addStatement(new GenOp(" @ = clamp(@, 0.0, 1.0);\r\n",
detailH, blendDepth)); detailH, blendDepth));
} }
meta->addStatement(new GenOp(" @ = max((@ * 2.0f - 1.0f) * @ + 0.5f, 0.0f);\r\n", meta->addStatement(new GenOp(" @ = max((@ * 2.0f - 1.0f) * @, 0.0f);\r\n",
detailH, detailH, blendContrast)); detailH, detailH, blendContrast));
meta->addStatement(new GenOp(" }\r\n")); meta->addStatement(new GenOp(" }\r\n"));
@ -1522,6 +1461,7 @@ void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentLi
meta->addStatement(new GenOp(" @ = max(@ + @ - @, 0);\r\n", meta->addStatement(new GenOp(" @ = max(@ + @ - @, 0);\r\n",
new DecOp(detailB), detailH, detailBlend, ma)); new DecOp(detailB), detailH, detailBlend, ma));
} }
meta->addStatement(new GenOp(" @ += @;\r\n", detailTot, detailB));
} }
meta->addStatement(new GenOp("\r\n")); meta->addStatement(new GenOp("\r\n"));
@ -1547,23 +1487,7 @@ void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentLi
meta->addStatement(new GenOp("@.rgb * @", detailColor, detailB)); meta->addStatement(new GenOp("@.rgb * @", detailColor, detailB));
} }
meta->addStatement(new GenOp(") / (")); meta->addStatement(new GenOp(") / @;\r\n", detailTot));
for (S32 idx = 0; idx < detailCount; ++idx)
{
Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx));
if (idx > 0)
{
meta->addStatement(new GenOp(" + "));
}
meta->addStatement(new GenOp("@", detailB));
}
meta->addStatement(new GenOp(");\r\n"));
meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n", meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n",
outColor, outColor)); outColor, outColor));
@ -1601,23 +1525,7 @@ void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentLi
} }
} }
meta->addStatement(new GenOp(") / (")); meta->addStatement(new GenOp(") / @;\r\n", detailTot));
for (S32 idx = 0; idx < detailCount; ++idx)
{
Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx));
if (idx > 0)
{
meta->addStatement(new GenOp(" + "));
}
meta->addStatement(new GenOp("@", detailB));
}
meta->addStatement(new GenOp(");\r\n"));
meta->addStatement(new GenOp("\r\n")); meta->addStatement(new GenOp("\r\n"));
@ -1704,22 +1612,7 @@ void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentLi
} }
} }
meta->addStatement(new GenOp(") / (")); meta->addStatement(new GenOp(") / @;\r\n", detailTot));
for (S32 idx = 0; idx < detailCount; ++idx)
{
Var* normalDetailB = (Var*)LangElement::find(String::ToString("normalDetailB%d", idx));
if (idx > 0)
{
meta->addStatement(new GenOp(" + "));
}
meta->addStatement(new GenOp("@", normalDetailB));
}
meta->addStatement(new GenOp(");\r\n"));
} }

View file

@ -26,6 +26,10 @@
#include "gfx/gfxTextureManager.h" #include "gfx/gfxTextureManager.h"
#include "gfx/bitmap/gBitmap.h" #include "gfx/bitmap/gBitmap.h"
#ifdef TORQUE_TOOLS
#include "console\persistenceManager.h"
#endif
#include <string> #include <string>