Skip to content
This repository has been archived by the owner on Jul 13, 2023. It is now read-only.

Commit

Permalink
Merge pull request GarageGames#962 from BeamNG/fix_opengl_new_terrain…
Browse files Browse the repository at this point in the history
…_blend

Fix OpenGL new terrain blend
  • Loading branch information
LuisAntonRebollo committed Nov 30, 2014
2 parents 32e8725 + fb08faf commit a0d5dc2
Show file tree
Hide file tree
Showing 39 changed files with 842 additions and 86 deletions.
270 changes: 223 additions & 47 deletions Engine/source/terrain/glsl/terrFeatureGLSL.cpp
Expand Up @@ -379,6 +379,9 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
const U32 detailIndex = getProcessIndex();
Var *inTex = getVertTexCoord( "texCoord" );

// new terrain
bool hasNormal = fd.features.hasFeature(MFT_TerrainNormalMap, detailIndex);

MultiLine *meta = new MultiLine;

// We need the negative tangent space view vector
Expand Down Expand Up @@ -447,6 +450,95 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) );

// New terrain

Var *lerpBlend = (Var*)LangElement::find("lerpBlend");
if (!lerpBlend)
{
lerpBlend = new Var;
lerpBlend->setType("float");
lerpBlend->setName("lerpBlend");
lerpBlend->uniform = true;
lerpBlend->constSortPos = cspPrimitive;
}


Var *blendDepth = (Var*)LangElement::find(String::ToString("blendDepth%d", detailIndex));
if (!blendDepth)
{
blendDepth = new Var;
blendDepth->setType("float");
blendDepth->setName(String::ToString("blendDepth%d", detailIndex));
blendDepth->uniform = true;
blendDepth->constSortPos = cspPrimitive;
}

Var *baseColor = (Var*)LangElement::find("baseColor");
Var *outColor = (Var*)LangElement::find(getOutputTargetVarName(DefaultTarget));

if (!outColor)
{
// create color var
outColor = new Var;
outColor->setType("float4");
outColor->setName("col");
meta->addStatement(new GenOp(" @;\r\n", new DecOp(outColor)));
//outColor->setStructName("OUT");
}

Var *detailColor = (Var*)LangElement::find("detailColor");
if (!detailColor)
{
detailColor = new Var;
detailColor->setType("float4");
detailColor->setName("detailColor");
meta->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor)));
}

// Get the detail texture.
Var *detailMap = new Var;
detailMap->setType("sampler2D");
detailMap->setName(String::ToString("detailMap%d", detailIndex));
detailMap->uniform = true;
detailMap->sampler = true;
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here

// Get the normal map texture.
Var *normalMap = _getNormalMapTex();

// Issue happens somewhere here -----

// Sample the normal map.
//
// We take two normal samples and lerp between them for
// side projection layers... else a single sample.
LangElement *texOp;

// Note that we're doing the standard greyscale detail
// map technique here which can darken and lighten the
// diffuse texture.
//
// We take two color samples and lerp between them for
// side projection layers... else a single sample.
//
if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex))
{
meta->addStatement(new GenOp(" @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet, detailMap, inDet, inTex));

texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
normalMap, inDet, normalMap, inDet, inTex);
}
else
{
meta->addStatement(new GenOp(" @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet));

texOp = new GenOp("tex2D(@, @.xy)", normalMap, inDet);
}

// New terrain

// Get a var and accumulate the blend amount.
Var *blendTotal = (Var*)LangElement::find( "blendTotal" );
if ( !blendTotal )
Expand All @@ -460,6 +552,95 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
// Add to the blend total.
meta->addStatement( new GenOp( " @ = max( @, @ );\r\n", blendTotal, blendTotal, detailBlend ) );

// New terrain
Var *bumpNorm = (Var*)LangElement::find("bumpNormal");
Var *invBlend = (Var*)LangElement::find("invBlend");
Var *currentAlpha = (Var*)LangElement::find("currentAlpha");
Var *ma = (Var*)LangElement::find("ma");
Var *b1 = (Var*)LangElement::find("b1");
Var *b2 = (Var*)LangElement::find("b2");

// Get a var and accumulate the blend amount.
if (!currentAlpha)
{
currentAlpha = new Var;
currentAlpha->setName("currentAlpha");
currentAlpha->setType("float");
meta->addStatement(new GenOp(" @ = 0;\r\n", new DecOp(currentAlpha)));
}

if (hasNormal)
{
// create bump normal
bool bumpNormWasDefined = bumpNorm ? true : false;
LangElement *bumpNormDecl = bumpNorm;

if (!bumpNormWasDefined)
{
bumpNorm = new Var;
bumpNorm->setName("bumpNormal");
bumpNorm->setType("float4");
bumpNormDecl = new DecOp(bumpNorm);
}
meta->addStatement(new GenOp(" @ = @;\r\n", bumpNormDecl, texOp));
meta->addStatement(new GenOp(" @.a = max(@.a, 0.000001);\r\n", bumpNorm, bumpNorm));

// -----

// Get a var and accumulate the blend amount.
if (!invBlend)
{
invBlend = new Var;
invBlend->setName("invBlend");
invBlend->setType("float");
meta->addStatement(new GenOp(" @;\r\n", new DecOp(invBlend)));
}

// Get a var and accumulate the blend amount.
if (!ma)
{
ma = new Var;
ma->setName("ma");
ma->setType("float");
meta->addStatement(new GenOp(" @;\r\n", new DecOp(ma)));
}

// Get a var and accumulate the blend amount.
if (!b1)
{
b1 = new Var;
b1->setName("b1");
b1->setType("float");
meta->addStatement(new GenOp(" @;\r\n", new DecOp(b1)));
}
// Get a var and accumulate the blend amount.
if (!b2)
{
b2 = new Var;
b2->setName("b2");
b2->setType("float");
meta->addStatement(new GenOp(" @;\r\n", new DecOp(b2)));
}

meta->addStatement(new GenOp(" if( @ <= 0 ) \r\n { \r\n", lerpBlend));

meta->addStatement(new GenOp(" @ = 1-@;\r\n", invBlend, detailBlend));

meta->addStatement(new GenOp(" @ = max(@.a + @, @ + @) - @;\r\n", ma, bumpNorm, detailBlend, currentAlpha, invBlend, blendDepth));

meta->addStatement(new GenOp(" @ = max(@.a + @ - @, 0);\r\n", b1, bumpNorm, detailBlend, ma));

meta->addStatement(new GenOp(" @ = max(@ + @ - @, 0);\r\n", b2, currentAlpha, invBlend, ma));

meta->addStatement(new GenOp(" }\r\n"));
}
else
{
meta->addStatement(new GenOp(" @ = max(@,@);\r\n", currentAlpha, currentAlpha, detailBlend));
}

// New terrain

// If we had a parallax feature... then factor in the parallax
// amount so that it fades out with the layer blending.
if ( fd.features.hasFeature( MFT_TerrainParallaxMap, detailIndex ) )
Expand Down Expand Up @@ -495,58 +676,36 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
return;
}

Var *detailColor = (Var*)LangElement::find( "detailColor" );
if ( !detailColor )
{
detailColor = new Var;
detailColor->setType( "vec4" );
detailColor->setName( "detailColor" );
meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) );
}

// Get the detail texture.
Var *detailMap = new Var;
detailMap->setType( "sampler2D" );
detailMap->setName( String::ToString( "detailMap%d", detailIndex ) );
detailMap->uniform = true;
detailMap->sampler = true;
detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
// used as texture unit num here

// If we're using SM 3.0 then take advantage of
// dynamic branching to skip layers per-pixel.


if ( GFX->getPixelShaderVersion() >= 3.0f )
meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) );

meta->addStatement( new GenOp( " {\r\n" ) );

// Note that we're doing the standard greyscale detail
// map technique here which can darken and lighten the
// diffuse texture.
//
// We take two color samples and lerp between them for
// side projection layers... else a single sample.
//
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
{
meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
}
else
{
meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
detailColor, detailMap, inDet ) );
}

meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
detailColor, detailInfo, inDet ) );

Var *baseColor = (Var*)LangElement::find( "baseColor" );
Var *outColor = (Var*)LangElement::find( "col" );
// New terrain
if (hasNormal)
{
meta->addStatement(new GenOp(" if( @ <= 0 ) \r\n", lerpBlend));
meta->addStatement(new GenOp(" @.rgb = ((@ + @).rgb * @ + @.rgb * @) / (@ + @);\r\n", outColor, baseColor, detailColor, b1, outColor, b2, b1, b2));
meta->addStatement(new GenOp(" else\r\n"));
}

meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n",
outColor, outColor, baseColor, detailColor, detailBlend ) );
meta->addStatement(new GenOp(" @ += @ * @;\r\n", outColor, detailColor, detailBlend));

// New terrain
if (hasNormal)
{
meta->addStatement(new GenOp(" if( @ <= 0 ) \r\n", lerpBlend));
meta->addStatement(new GenOp(" @ = (@.a * @ + @ * @) / (@ + @);\r\n", currentAlpha, bumpNorm, b1, currentAlpha, b2, b1, b2));
}

meta->addStatement( new GenOp( " }\r\n" ) );

Expand Down Expand Up @@ -812,13 +971,9 @@ void TerrainMacroMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentL
meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
detailColor, detailInfo, inDet ) );

Var *baseColor = (Var*)LangElement::find( "baseColor" );
Var *outColor = (Var*)LangElement::find( "col" );

meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );\r\n",
outColor, outColor, outColor, detailColor, detailBlend ) );
//outColor, outColor, baseColor, detailColor, detailBlend ) );

meta->addStatement(new GenOp(" @ += @ * @;\r\n", outColor, detailColor, detailBlend));
meta->addStatement( new GenOp( " }\r\n" ) );

output = meta;
Expand Down Expand Up @@ -920,15 +1075,36 @@ void TerrainNormalMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
texOp = new GenOp( "tex2D(@, @.xy)", normalMap, inDet );

// create bump normal
Var *bumpNorm = new Var;
bumpNorm->setName( "bumpNormal" );
bumpNorm->setType( "vec4" );
// New terrain
Var *bumpNorm = (Var*)LangElement::find("bumpNormal");
bool bumpNormWasDefined = bumpNorm ? true : false;
LangElement *bumpNormDecl = bumpNorm;

if (!bumpNormWasDefined)
{
bumpNorm = new Var;
bumpNorm->setName("bumpNormal");
bumpNorm->setType("float4");
bumpNormDecl = new DecOp(bumpNorm);
}

LangElement *bumpNormDecl = new DecOp( bumpNorm );
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );

// New terrain
Var *lerpBlend = (Var*)LangElement::find("lerpBlend");
AssertFatal(lerpBlend, "The lerpBlend is missing!");
Var *b1 = (Var*)LangElement::find("b1");
AssertFatal(b1, "The b1 is missing!");
Var *b2 = (Var*)LangElement::find("b2");
AssertFatal(b2, "The b2 is missing!");

// Normalize is done later...
// Note: The reverse mul order is intentional. Affine matrix.

// New terrain
meta->addStatement(new GenOp(" if( @ <= 0 ) \r\n", lerpBlend));
meta->addStatement(new GenOp(" @ = (tMul( @.xyz, @ ).rgb * @ + @.rgb * @) / (@ + @);\r\n", gbNormal, bumpNorm, viewToTangent, b1, gbNormal, b2, b1, b2));
meta->addStatement(new GenOp(" else\r\n"));
meta->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n",
gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet ) );

Expand Down
9 changes: 9 additions & 0 deletions Engine/source/terrain/terrCellMaterial.cpp
Expand Up @@ -574,6 +574,10 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
matInfo->detailInfoVConst = pass->shader->getShaderConstHandle( avar( "$detailScaleAndFade%d", i ) );
matInfo->detailInfoPConst = pass->shader->getShaderConstHandle( avar( "$detailIdStrengthParallax%d", i ) );

// New blending
matInfo->lerpBlend = pass->shader->getShaderConstHandle("$lerpBlend");
matInfo->blendDepth = pass->shader->getShaderConstHandle(avar("$blendDepth%d", i));

matInfo->detailTexConst = pass->shader->getShaderConstHandle( avar( "$detailMap%d", i ) );
if ( matInfo->detailTexConst->isValid() )
{
Expand Down Expand Up @@ -711,6 +715,11 @@ void TerrainCellMaterial::_updateMaterialConsts( Pass *pass )
pass->consts->setSafe( matInfo->detailInfoVConst, detailScaleAndFade );
pass->consts->setSafe( matInfo->detailInfoPConst, detailIdStrengthParallax );

// New blending
bool lerpBlend = Con::getBoolVariable("$Pref::Terrain::LerpBlend", true);
pass->consts->setSafe(matInfo->lerpBlend, lerpBlend ? 1.0f : 0.0f);
pass->consts->setSafe(matInfo->blendDepth, matInfo->mat->getBlendDepth());

// macro texture info

F32 macroSize = matInfo->mat->getMacroSize();
Expand Down
4 changes: 4 additions & 0 deletions Engine/source/terrain/terrCellMaterial.h
Expand Up @@ -80,6 +80,10 @@ class TerrainCellMaterial
GFXShaderConstHandle *detailInfoVConst;
GFXShaderConstHandle *detailInfoPConst;

// New blending
GFXShaderConstHandle *lerpBlend;
GFXShaderConstHandle *blendDepth;

GFXShaderConstHandle *macroInfoVConst;
GFXShaderConstHandle *macroInfoPConst;
};
Expand Down
6 changes: 5 additions & 1 deletion Engine/source/terrain/terrMaterial.cpp
Expand Up @@ -65,7 +65,8 @@ TerrainMaterial::TerrainMaterial()
mMacroSize( 200.0f ),
mMacroStrength( 0.7f ),
mMacroDistance( 500.0f ),
mParallaxScale( 0.0f )
mParallaxScale(0.0f),
mBlendDepth(0.4f)
{
}

Expand Down Expand Up @@ -97,6 +98,9 @@ void TerrainMaterial::initPersistFields()
addField( "parallaxScale", TypeF32, Offset( mParallaxScale, TerrainMaterial ), "Used to scale the height from the normal map to give some self "
"occlusion effect (aka parallax) to the terrain material" );

addField("blendDepth", TypeF32, Offset(mBlendDepth, TerrainMaterial), "Depth for blending the textures using the new blending method by Lukas Joergensen."
"Higher numbers = larger blend radius.");

Parent::initPersistFields();

// Gotta call this at least once or it won't get created!
Expand Down

0 comments on commit a0d5dc2

Please sign in to comment.