diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index e901f5b79..a2154b736 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -45,7 +45,7 @@ namespace FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureGLSL( "Terrain Parallax Texture" ) ); FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatGLSL ); - FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureGLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatGLSL); + FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatGLSL); FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature(MFT_TerrainHeightBlend, new TerrainHeightMapBlendGLSL); @@ -142,6 +142,24 @@ Var* TerrainFeatGLSL::_getDetailMapSampler() return detailMapSampler; } +Var* TerrainFeatGLSL::_getMacroMapSampler() +{ + String name("macroMapSampler"); + Var* detailMapSampler = (Var*)LangElement::find(name); + + if (!detailMapSampler) + { + detailMapSampler = new Var; + detailMapSampler->setName(name); + detailMapSampler->setType("sampler2DArray"); + detailMapSampler->uniform = true; + detailMapSampler->sampler = true; + detailMapSampler->constNum = Var::getTexUnitNum(); + } + + return detailMapSampler; +} + Var* TerrainFeatGLSL::_getNormalMapSampler() { String name("normalMapSampler"); @@ -200,18 +218,21 @@ Var* TerrainFeatGLSL::_getDetailIdStrengthParallax() Var* TerrainFeatGLSL::_getMacroIdStrengthParallax() { - String name(String::ToString("macroIdStrengthParallax%d", getProcessIndex())); + String name(String::ToString("macroIdStrengthParallax", getProcessIndex())); Var* detailInfo = (Var*)LangElement::find(name); if (!detailInfo) { detailInfo = new Var; - detailInfo->setType("vec3"); + detailInfo->setType("vec4"); detailInfo->setName(name); detailInfo->uniform = true; detailInfo->constSortPos = cspPotentialPrimitive; + detailInfo->arraySize = getProcessIndex(); } + detailInfo->arraySize = mMax(detailInfo->arraySize, getProcessIndex() + 1); + return detailInfo; } @@ -427,6 +448,19 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1); + // This is done here to make sure the macro array size/alignment is correct + Var* macroScaleAndFade = (Var*)LangElement::find("macroScaleAndFade"); + if (macroScaleAndFade == NULL) + { + macroScaleAndFade = new Var; + macroScaleAndFade->setType("vec4"); + macroScaleAndFade->setName("macroScaleAndFade"); + macroScaleAndFade->uniform = true; + macroScaleAndFade->constSortPos = cspPotentialPrimitive; + } + + macroScaleAndFade->arraySize = mMax(macroScaleAndFade->arraySize, detailIndex + 1); + // Setup the detail coord. // // NOTE: You see here we scale the texture coord by 'xyx' @@ -510,6 +544,9 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component // Get the detail id. Var *detailInfo = _getDetailIdStrengthParallax(); + // This is done here to make sure the macro arrays are the correct size + Var* macroInfo = _getMacroIdStrengthParallax(); + // Create the detail blend var. Var *detailBlend = new Var; detailBlend->setType( "float" ); @@ -568,7 +605,8 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component detailColor, detailMapArray, detCoord, new IndexOp(detailInfo, detailIndex))); } - meta->addStatement(new GenOp(" @ *= @.y * @;\r\n", detailColor, new IndexOp(detailInfo, detailIndex), detailBlend)); + meta->addStatement(new GenOp(" @ *= @.y;\r\n", + detailColor, new IndexOp(detailInfo, detailIndex))); if (!fd.features.hasFeature(MFT_TerrainNormalMap)) { @@ -672,18 +710,23 @@ void TerrainMacroMapFeatGLSL::processVert( Vector &componentL outTex->setStructName( "OUT" ); outTex->setType( "vec4" ); - // Get the detail scale and fade info. - Var *macroScaleAndFade = new Var; + Var* macroScaleAndFade = (Var*)LangElement::find("macroScaleAndFade"); + if (macroScaleAndFade == NULL) + { + macroScaleAndFade = new Var; macroScaleAndFade->setType( "vec4" ); - macroScaleAndFade->setName( String::ToString( "macroScaleAndFade%d", detailIndex ) ); + macroScaleAndFade->setName("macroScaleAndFade"); macroScaleAndFade->uniform = true; macroScaleAndFade->constSortPos = cspPotentialPrimitive; + } + + macroScaleAndFade->arraySize = mMax(macroScaleAndFade->arraySize, detailIndex + 1); // Setup the detail coord. - meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, macroScaleAndFade ) ); + meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(macroScaleAndFade, detailIndex)) ); // And sneak the detail fade thru the w detailCoord. - meta->addStatement( new GenOp( " @.w = ( @.z - @ ) * @.w;\r\n", outTex, macroScaleAndFade, dist, macroScaleAndFade ) ); + meta->addStatement( new GenOp( " @.w = ( @.z - @ ) * @.w;\r\n", outTex, new IndexOp(macroScaleAndFade, detailIndex), dist, new IndexOp(macroScaleAndFade, detailIndex)) ); output = meta; } @@ -761,7 +804,7 @@ void TerrainMacroMapFeatGLSL::processPix( Vector &componentL // Calculate the blend for this detail texture. meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", - new DecOp( detailBlend ), detailInfo, inTex, layerSize, layerSample ) ); + new DecOp( detailBlend ), new IndexOp(detailInfo, detailIndex), inTex, layerSize, layerSample ) ); // Check to see if we have a gbuffer normal. Var* gbNormal = (Var*)LangElement::find("gbNormal"); @@ -779,26 +822,17 @@ void TerrainMacroMapFeatGLSL::processPix( Vector &componentL gbNormal, gbNormal, viewToTangent, detailBlend, detCoord ) ); } - Var *detailColor = (Var*)LangElement::find( "macroColor" ); + Var* detailColor = (Var*)LangElement::find(String::ToString("macroColor%d", detailIndex)); if ( !detailColor ) { detailColor = new Var; detailColor->setType( "vec4" ); - detailColor->setName( "macroColor" ); + detailColor->setName(String::ToString("macroColor%d", detailIndex)); meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); } // Get the detail texture. - Var *detailMapArray = new Var; - detailMapArray->setType( "sampler2D" ); - detailMapArray->setName( String::ToString( "macroMap%d", detailIndex ) ); - detailMapArray->uniform = true; - detailMapArray->sampler = true; - detailMapArray->constNum = Var::getTexUnitNum(); // used as texture unit num here - - meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); - - meta->addStatement( new GenOp( " {\r\n" ) ); + Var* detailMapArray = _getMacroMapSampler(); // Note that we're doing the standard greyscale detail // map technique here which can darken and lighten the @@ -818,20 +852,12 @@ void TerrainMacroMapFeatGLSL::processPix( Vector &componentL } else { - meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n", - detailColor, detailMapArray, detCoord) ); + meta->addStatement(new GenOp(" @ = ( tex2D( @, vec3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n", + detailColor, detailMapArray, detCoord, new IndexOp(detailInfo, detailIndex))); } - meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", detailColor, detailInfo, detCoord) ); - - ShaderFeature::OutputTarget target = (fd.features[MFT_isDeferred]) ? RenderTarget1 : DefaultTarget; - - Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); - - meta->addStatement(new GenOp(" @ += @ * @;\r\n", - outColor, detailColor, detailBlend)); - - meta->addStatement( new GenOp( " }\r\n" ) ); + meta->addStatement(new GenOp(" @ *= @.y;\r\n", + detailColor, new IndexOp(detailInfo, detailIndex))); output = meta; } @@ -844,15 +870,14 @@ ShaderFeature::Resources TerrainMacroMapFeatGLSL::getResources( const MaterialFe { // If this is the first detail pass then we // samples from the layer tex. + res.numTex = 1; + res.numTexReg = 1; + + // Add Detail TextureArray res.numTex += 1; + res.numTexReg += 1; } - res.numTex += 1; - - // Finally we always send the detail texture - // coord to the pixel shader. - res.numTexReg += 1; - return res; } @@ -1252,7 +1277,7 @@ void TerrainHeightMapBlendGLSL::processPix(Vector& componentLi } Var* heightRange = new Var("heightRange", "vec2"); - meta->addStatement(new GenOp(" @ = vec2(2.0f,0);//x=min, y=max\r\n", new DecOp(heightRange))); + meta->addStatement(new GenOp(" @ = vec2(0,0);//x=min, y=max\r\n", new DecOp(heightRange))); // Compute blend factors for (S32 idx = 0; idx < detailCount; ++idx) { @@ -1301,7 +1326,20 @@ void TerrainHeightMapBlendGLSL::processPix(Vector& componentLi { Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); - meta->addStatement(new GenOp(" @ = (@-@.x)/(@.y-@.x)-@.x;\r\n", detailH, detailH, heightRange, heightRange, heightRange)); + Var* blendHardness = (Var*)LangElement::find(String::ToString("blendHardness%d", idx)); + if (!blendHardness) + { + blendHardness = new Var; + blendHardness->setType("float"); + blendHardness->setName(String::ToString("blendHardness%d", idx)); + blendHardness->uniform = true; + blendHardness->constSortPos = cspPrimitive; + } + meta->addStatement(new GenOp(" @ = (@-@.x)/(@.y-@.x)-@.x;\r\n", detailH, detailH, heightRange, heightRange, heightRange, heightRange)); + // Note that blendHardness is clamped between 0-0.99 at the terrain material level to avoid a divide by zero + meta->addStatement(new GenOp(" @ = 1.0f / (1.0f - @) * (@ - @);\r\n", detailH, blendHardness, detailH, blendHardness)); + // This line equation will go out of our 0-1 range, clamp it + meta->addStatement(new GenOp(" @ = clamp(@, 0.0f, 1.0f);\r\n", detailH, detailH)); } meta->addStatement(new GenOp("\r\n")); @@ -1333,6 +1371,31 @@ void TerrainHeightMapBlendGLSL::processPix(Vector& componentLi meta->addStatement(new GenOp(");\r\n")); + // Macro textures, if they exist + bool didMacro = false; + for (S32 idx = 0; idx < detailCount; ++idx) + { + Var* detailColor = (Var*)LangElement::find(String::ToString("macroColor%d", idx)); + if (detailColor) // only do this if the macro map exists for this layer + { + if (!didMacro) + meta->addStatement(new GenOp(" @.rgb += (", outColor)); + + Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); + Var* detCoord = (Var*)LangElement::find(String::ToString("macroCoord%d", idx)); + + if (idx > 0 && didMacro) + { + meta->addStatement(new GenOp(" + ")); + } + + meta->addStatement(new GenOp("((@.rgb * @)*max(@.w,0))", detailColor, detailH, detCoord)); + didMacro = true; + } + } + if (didMacro) + meta->addStatement(new GenOp(");\r\n")); + // Compute ORM Var* ormOutput; if (fd.features[MFT_isDeferred]) diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.h b/Engine/source/terrain/glsl/terrFeatureGLSL.h index 7d56a75bf..135d54b8a 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.h +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.h @@ -45,6 +45,7 @@ public: Var* _getInMacroCoord(Vector &componentList ); Var* _getDetailMapSampler(); + Var* _getMacroMapSampler(); Var* _getNormalMapSampler(); Var* _getOrmMapSampler(); diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp index 07271bc99..dd111ddb4 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp @@ -46,7 +46,7 @@ namespace FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureHLSL( "Terrain Parallax Texture" ) ); FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatHLSL ); - FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureHLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatHLSL); + FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new TerrainMacroMapFeatHLSL); FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature( MFT_TerrainHeightBlend, new TerrainHeightMapBlendHLSL ); @@ -160,6 +160,42 @@ Var* TerrainFeatHLSL::_getDetailMapArray() return detailMapArray; } +Var* TerrainFeatHLSL::_getMacroMapSampler() +{ + String name("macroMapSampler"); + Var* detailMapSampler = (Var*)LangElement::find(name); + + if (!detailMapSampler) + { + detailMapSampler = new Var; + detailMapSampler->setName(name); + detailMapSampler->setType("SamplerState"); + detailMapSampler->uniform = true; + detailMapSampler->sampler = true; + detailMapSampler->constNum = Var::getTexUnitNum(); + } + + return detailMapSampler; +} + +Var* TerrainFeatHLSL::_getMacroMapArray() +{ + String name("macroMapArray"); + Var* detailMapArray = (Var*)LangElement::find(name); + + if (!detailMapArray) + { + detailMapArray = new Var; + detailMapArray->setName(name); + detailMapArray->setType("Texture2DArray"); + detailMapArray->uniform = true; + detailMapArray->texture = true; + detailMapArray->constNum = _getMacroMapSampler()->constNum; + } + + return detailMapArray; +} + Var* TerrainFeatHLSL::_getNormalMapSampler() { String name("normalMapSampler"); @@ -254,18 +290,20 @@ Var* TerrainFeatHLSL::_getDetailIdStrengthParallax() Var* TerrainFeatHLSL::_getMacroIdStrengthParallax() { - String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) ); + String name( String::ToString( "macroIdStrengthParallax", getProcessIndex() ) ); Var *detailInfo = (Var*)LangElement::find( name ); if ( !detailInfo ) { detailInfo = new Var; - detailInfo->setType( "float3" ); + detailInfo->setType( "float4" ); detailInfo->setName( name ); detailInfo->uniform = true; detailInfo->constSortPos = cspPotentialPrimitive; } + detailInfo->arraySize = mMax(detailInfo->arraySize, getProcessIndex() + 1); + return detailInfo; } @@ -483,6 +521,19 @@ void TerrainDetailMapFeatHLSL::processVert( Vector &component detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1); + // Done here to keep array indexes aligned + Var* macroScaleAndFade = (Var*)LangElement::find("macroScaleAndFade"); + if (macroScaleAndFade == NULL) + { + macroScaleAndFade = new Var; + macroScaleAndFade->setType("float4"); + macroScaleAndFade->setName("macroScaleAndFade"); + macroScaleAndFade->uniform = true; + macroScaleAndFade->constSortPos = cspPotentialPrimitive; + } + + macroScaleAndFade->arraySize = mMax(macroScaleAndFade->arraySize, detailIndex + 1); + // Setup the detail coord. // // NOTE: You see here we scale the texture coord by 'xyx' @@ -572,6 +623,9 @@ void TerrainDetailMapFeatHLSL::processPix( Vector &component // Get the detail id. Var *detailInfo = _getDetailIdStrengthParallax(); + // Done here to keep array indexes aligned + Var* macroInfo = _getMacroIdStrengthParallax(); + // Create the detail blend var. Var *detailBlend = new Var; detailBlend->setType( "float" ); @@ -630,7 +684,8 @@ void TerrainDetailMapFeatHLSL::processPix( Vector &component detailColor, detailMapArray, detailMapSampler, detCoord, new IndexOp(detailInfo, detailIndex))); } - meta->addStatement(new GenOp(" @ *= @.y * @;\r\n", detailColor, new IndexOp(detailInfo, detailIndex), detailBlend)); + meta->addStatement(new GenOp(" @ *= @.y;\r\n", + detailColor, new IndexOp(detailInfo, detailIndex))); if (!fd.features.hasFeature(MFT_TerrainNormalMap)) { @@ -854,24 +909,13 @@ void TerrainMacroMapFeatHLSL::processPix( Vector &componentL gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); } - Var *detailColor = (Var*)LangElement::find("macroColor"); - if (!detailColor) - { - detailColor = new Var; + Var* detailColor = new Var; detailColor->setType( "float4" ); - detailColor->setName( "macroColor" ); - meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); - } + detailColor->setName( String::ToString("macroColor%d", detailIndex) ); + meta->addStatement( new GenOp( " @ = float4(0.5f, 0.5f, 0.5f, 1.0f);\r\n", new DecOp( detailColor ) ) ); - // 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" ) ); - - Var* detailMapArray = _getDetailMapArray(); - Var* detailMapSampler = _getDetailMapSampler(); + Var* detailMapArray = _getMacroMapArray(); + Var* detailMapSampler = _getMacroMapSampler(); // Note that we're doing the standard greyscale detail // map technique here which can darken and lighten the @@ -895,17 +939,8 @@ void TerrainMacroMapFeatHLSL::processPix( Vector &componentL detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex))); } - meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", - detailColor, new IndexOp(detailInfo, detailIndex), inDet ) ); - - ShaderFeature::OutputTarget target = (fd.features[MFT_isDeferred]) ? RenderTarget1 : DefaultTarget; - - Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); - - meta->addStatement(new GenOp(" @ += @ * @;\r\n", - outColor, detailColor, detailBlend)); - - meta->addStatement( new GenOp( " }\r\n" ) ); + meta->addStatement(new GenOp(" @ *= @.y;\r\n", + detailColor, new IndexOp(detailInfo, detailIndex))); output = meta; } @@ -919,13 +954,12 @@ ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFe // If this is the first detail pass then we // samples from the layer tex. res.numTex += 1; - } + res.numTexReg += 1; + // Add Detail TextureArray res.numTex += 1; - - // Finally we always send the detail texture - // coord to the pixel shader. - res.numTexReg += 1; + res.numTexReg += 1; + } return res; } @@ -1333,7 +1367,7 @@ void TerrainHeightMapBlendHLSL::processPix(Vector& componentLi } Var* heightRange = new Var("heightRange", "float2"); - meta->addStatement(new GenOp(" @ = float2(2.0f,0);//x=min, y=max\r\n", new DecOp(heightRange))); + meta->addStatement(new GenOp(" @ = float2(0,0);//x=min, y=max\r\n", new DecOp(heightRange))); // Compute blend factors for (S32 idx = 0; idx < detailCount; ++idx) { @@ -1382,7 +1416,20 @@ void TerrainHeightMapBlendHLSL::processPix(Vector& componentLi { Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); + Var* blendHardness = (Var*)LangElement::find(String::ToString("blendHardness%d", idx)); + if (!blendHardness) + { + blendHardness = new Var; + blendHardness->setType("float"); + blendHardness->setName(String::ToString("blendHardness%d", idx)); + blendHardness->uniform = true; + blendHardness->constSortPos = cspPrimitive; + } meta->addStatement(new GenOp(" @ = (@-@.x)/(@.y-@.x)-@.x;\r\n", detailH, detailH, heightRange, heightRange, heightRange, heightRange)); + // Note that blendHardness is clamped between 0-0.99 at the terrain material level to avoid a divide by zero + meta->addStatement(new GenOp(" @ = 1.0f / (1.0f - @) * (@ - @);\r\n", detailH, blendHardness, detailH, blendHardness)); + // This line equation will go out of our 0-1 range, clamp it + meta->addStatement(new GenOp(" @ = clamp(@, 0.0f, 1.0f);\r\n", detailH, detailH)); } meta->addStatement(new GenOp("\r\n")); } @@ -1413,6 +1460,31 @@ void TerrainHeightMapBlendHLSL::processPix(Vector& componentLi meta->addStatement(new GenOp(");\r\n")); + // Macro textures, if they exist + bool didMacro = false; + for (S32 idx = 0; idx < detailCount; ++idx) + { + Var* detailColor = (Var*)LangElement::find(String::ToString("macroColor%d", idx)); + if (detailColor) // only do this if the macro map exists for this layer + { + if (!didMacro) + meta->addStatement(new GenOp(" @.rgb += (", outColor)); + + Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); + Var* detCoord = (Var*)LangElement::find(String::ToString("macroCoord%d", idx)); + + if (idx > 0 && didMacro) + { + meta->addStatement(new GenOp(" + ")); + } + + meta->addStatement(new GenOp("((@.rgb * @)*max(@.w,0))", detailColor, detailH, detCoord)); + didMacro = true; + } + } + if (didMacro) + meta->addStatement(new GenOp(");\r\n")); + // Compute ORM Var* ormOutput; if (fd.features[MFT_isDeferred]) diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.h b/Engine/source/terrain/hlsl/terrFeatureHLSL.h index f3803f2d9..407b8e267 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.h +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.h @@ -47,6 +47,8 @@ public: Var* _getDetailMapSampler(); Var* _getDetailMapArray(); + Var* _getMacroMapSampler(); + Var* _getMacroMapArray(); Var* _getNormalMapSampler(); Var* _getNormalMapArray(); Var* _getOrmMapSampler(); diff --git a/Engine/source/terrain/terrCellMaterial.cpp b/Engine/source/terrain/terrCellMaterial.cpp index be0e5b64b..5c7756c00 100644 --- a/Engine/source/terrain/terrCellMaterial.cpp +++ b/Engine/source/terrain/terrCellMaterial.cpp @@ -548,7 +548,7 @@ bool TerrainCellMaterial::_initShader(bool deferredMat, mDetailInfoVArrayConst = mShader->getShaderConstHandle("$detailScaleAndFade"); mDetailInfoPArrayConst = mShader->getShaderConstHandle("$detailIdStrengthParallax"); - mMacroInfoVArrayConst = mShader->getShaderConstHandle("$macroIdStrengthParallax"); + mMacroInfoVArrayConst = mShader->getShaderConstHandle("$macroScaleAndFade"); mMacroInfoPArrayConst = mShader->getShaderConstHandle("$macroIdStrengthParallax"); mDetailTexArrayConst = mShader->getShaderConstHandle("$detailMapSampler"); @@ -637,6 +637,7 @@ bool TerrainCellMaterial::_initShader(bool deferredMat, mMaterialInfos[i]->mBlendDepthConst = mShader->getShaderConstHandle(avar("$blendDepth%d", i)); mMaterialInfos[i]->mBlendContrastConst = mShader->getShaderConstHandle(avar("$blendContrast%d", i)); + mMaterialInfos[i]->mBlendHardnessConst = mShader->getShaderConstHandle(avar("$blendHardness%d", i)); } // If we're doing deferred it requires some @@ -689,6 +690,9 @@ void TerrainCellMaterial::_updateMaterialConsts( ) AlignedArray detailInfoArray(detailMatCount, sizeof(Point4F)); AlignedArray detailScaleAndFadeArray(detailMatCount, sizeof(Point4F)); + AlignedArray macroInfoArray(detailMatCount, sizeof(Point4F)); + AlignedArray macroScaleAndFadeArray(detailMatCount, sizeof(Point4F)); + int detailIndex = 0; for (MaterialInfo* matInfo : mMaterialInfos) { @@ -745,12 +749,45 @@ void TerrainCellMaterial::_updateMaterialConsts( ) { mConsts->setSafe(matInfo->mBlendContrastConst, matInfo->mat->getBlendContrast()); } + + if (matInfo->mBlendHardnessConst != NULL) + { + mConsts->setSafe(matInfo->mBlendHardnessConst, matInfo->mat->getBlendHardness()); + } + + // macro texture info + + F32 macroSize = matInfo->mat->getMacroSize(); + F32 macroScale = 1.0f; + if (!mIsZero(macroSize)) + macroScale = mTerrain->getWorldBlockSize() / macroSize; + + // Scale the distance by the global scalar. + const F32 macroDistance = mTerrain->smDetailScale * matInfo->mat->getMacroDistance(); + + Point4F macroScaleAndFade(macroScale, + -macroScale, + macroDistance, + 0); + + if (!mIsZero(macroDistance)) + macroScaleAndFade.w = 1.0f / macroDistance; + + Point4F macroIdStrengthParallax(matInfo->layerId, + matInfo->mat->getMacroStrength(), + 0, 0); + + macroScaleAndFadeArray[detailIndex] = macroScaleAndFade; + macroInfoArray[detailIndex] = macroIdStrengthParallax; + detailIndex++; } mConsts->setSafe(mDetailInfoVArrayConst, detailScaleAndFadeArray); mConsts->setSafe(mDetailInfoPArrayConst, detailInfoArray); + mConsts->setSafe(mMacroInfoVArrayConst, macroScaleAndFadeArray); + mConsts->setSafe(mMacroInfoPArrayConst, macroInfoArray); } bool TerrainCellMaterial::setupPass( const SceneRenderState *state, diff --git a/Engine/source/terrain/terrCellMaterial.h b/Engine/source/terrain/terrCellMaterial.h index 46facf70b..c8e6fc05e 100644 --- a/Engine/source/terrain/terrCellMaterial.h +++ b/Engine/source/terrain/terrCellMaterial.h @@ -59,7 +59,7 @@ protected: public: MaterialInfo() - :mat(NULL), layerId(0), mBlendDepthConst(NULL), mBlendContrastConst(NULL) + :mat(NULL), layerId(0), mBlendDepthConst(NULL), mBlendContrastConst(NULL), mBlendHardnessConst(NULL) { } @@ -71,6 +71,7 @@ protected: U32 layerId; GFXShaderConstHandle *mBlendDepthConst; GFXShaderConstHandle *mBlendContrastConst; + GFXShaderConstHandle* mBlendHardnessConst; }; /// @@ -119,6 +120,7 @@ protected: GFXShaderConstHandle *mOrmTexArrayConst; GFXShaderConstHandle* mBlendDepthConst; + GFXShaderConstHandle* mBlendHeightFloorConst; TerrainBlock *mTerrain; diff --git a/Engine/source/terrain/terrMaterial.cpp b/Engine/source/terrain/terrMaterial.cpp index bcc5b812f..8c13861b4 100644 --- a/Engine/source/terrain/terrMaterial.cpp +++ b/Engine/source/terrain/terrMaterial.cpp @@ -25,6 +25,7 @@ #include "console/consoleTypes.h" #include "gfx/gfxTextureManager.h" #include "gfx/bitmap/gBitmap.h" +#include "console/typeValidators.h" #ifdef TORQUE_TOOLS #include "console/persistenceManager.h" @@ -76,6 +77,7 @@ TerrainMaterial::TerrainMaterial() mParallaxScale( 0.0f ), mBlendDepth( 0.0f ), mBlendContrast( 1.0f ), + mBlendHardness( 0.0f ), mIsSRGB(false), mInvertRoughness(false) { @@ -90,6 +92,8 @@ TerrainMaterial::~TerrainMaterial() { } +FRangeValidator hardnessValidator(0.0f, 0.999f); + void TerrainMaterial::initPersistFields() { docsURL; @@ -106,6 +110,9 @@ void TerrainMaterial::initPersistFields() addField("blendHeightContrast", TypeF32, Offset(mBlendContrast, TerrainMaterial), "A fixed value to add while blending using heightmap-based blending." "Higher numbers = larger blend radius."); + addFieldV("blendHeightHardness", TypeF32, Offset(mBlendHardness, TerrainMaterial), &hardnessValidator, "How sharply this layer blends with other textures." + "0->1, soft->hard."); + INITPERSISTFIELD_IMAGEASSET(DetailMap, TerrainMaterial, "Raises and lowers the RGB result of the Base Albedo up close."); addField( "detailSize", TypeF32, Offset( mDetailSize, TerrainMaterial ), "Used to scale the detail map to the material square" ); addField( "detailStrength", TypeF32, Offset( mDetailStrength, TerrainMaterial ), "Exponentially sharpens or lightens the detail map rendering on the material" ); diff --git a/Engine/source/terrain/terrMaterial.h b/Engine/source/terrain/terrMaterial.h index 4e129ef73..7c3025542 100644 --- a/Engine/source/terrain/terrMaterial.h +++ b/Engine/source/terrain/terrMaterial.h @@ -97,6 +97,8 @@ protected: F32 mBlendContrast; + F32 mBlendHardness; + public: TerrainMaterial(); @@ -138,6 +140,8 @@ public: F32 getBlendContrast() const { return mBlendContrast; } + F32 getBlendHardness() const { return mBlendHardness; } + bool getIsSRGB() const { return mIsSRGB; } bool getInvertRoughness() const { return mInvertRoughness; } diff --git a/Templates/BaseGame/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui b/Templates/BaseGame/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui index d31eec0bf..5460d5d87 100644 --- a/Templates/BaseGame/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui +++ b/Templates/BaseGame/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui @@ -394,7 +394,7 @@ $guiContent = new GuiControl(TerrainMaterialDlg,EditorGuiGroup) { }; new GuiContainer(NormalMapContainer) { position = "6 205"; - extent = "261 100"; + extent = "261 120"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; @@ -527,17 +527,45 @@ $guiContent = new GuiControl(TerrainMaterialDlg,EditorGuiGroup) { isContainer = "0"; internalName = "blendHeightContrastTextEditCtrl"; }; + new GuiTextEditCtrl(TerrainMaterialDlgBlendHeightHardnessTextEdit) { + text = "0"; + anchorTop = "0"; + anchorLeft = "0"; + position = "1 99"; + extent = "35 18"; + profile = "ToolsGuiTextEditProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + isContainer = "0"; + internalName = "blendHeightHardnessTextEditCtrl"; + }; + new GuiTextCtrl() { + text = "Blend Hardness"; + position = "115 101"; + extent = "76 15"; + profile = "ToolsGuiTextProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + }; + new GuiSliderCtrl(TerrainMaterialDlgBlendHeightHardnessSlider) { + range = "0 0.999"; + ticks = "0"; + value = "0"; + position = "39 101"; + extent = "70 14"; + profile = "ToolsGuiSliderProfile"; + tooltipProfile = "ToolsGuiToolTipProfile"; + internalName = "blendHeightHardnessSliderCtrl"; + }; }; new GuiBitmapCtrl() { - BitmapAsset = "ToolsModule:separator_v_image"; - position = "6 307"; - extent = "266 2"; + BitmapAsset = "ToolsModule:separator_v_image"; + position = "6 323"; + extent = "266 2"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; }; new GuiContainer(ORMConfigMapContainer) { - position = "6 314"; + position = "6 330"; extent = "261 64"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; @@ -615,14 +643,14 @@ $guiContent = new GuiControl(TerrainMaterialDlg,EditorGuiGroup) { }; new GuiBitmapCtrl() { BitmapAsset = "ToolsModule:separator_v_image"; - position = "6 381"; + position = "6 397"; extent = "266 2"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; tooltipProfile = "ToolsGuiToolTipProfile"; }; new GuiContainer(MacroMapContainer) { - position = "6 388"; + position = "6 404"; extent = "261 72"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; @@ -746,7 +774,7 @@ $guiContent = new GuiControl(TerrainMaterialDlg,EditorGuiGroup) { }; }; new GuiContainer(TerrainEffectsContainer) { - position = "6 460"; + position = "6 476"; extent = "265 97"; horizSizing = "width"; profile = "ToolsGuiDefaultProfile"; diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.tscript index a73f2bae0..991d5550e 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.tscript @@ -477,6 +477,10 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat ) %this-->blendHeightContrastTextEditCtrl.setText( %blendHeightContrast ); %this-->blendHeightContrastSliderCtrl.setValue( %mat.blendHeightContrast ); + %blendHeightHardness = mFloor(%mat.blendHeightHardness * 1000)/1000; + %this-->blendHeightHardnessTextEditCtrl.setText( %blendHeightHardness ); + %this-->blendHeightHardnessSliderCtrl.setValue( %mat.blendHeightHardness ); + %this-->macroSizeCtrl.setText( %mat.macroSize ); %this-->macroStrengthCtrl.setText( %mat.macroStrength ); %this-->macroDistanceCtrl.setText( %mat.macroDistance ); @@ -686,6 +690,7 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %materialAssetId ) %parallaxScale = %this-->parallaxScaleCtrl.getText(); %blendHeightBase = %this-->blendHeightBaseTextEditCtrl.getText(); %blendHeightContrast = %this-->blendHeightContrastTextEditCtrl.getText(); + %blendHeightHardness = %this-->blendHeightHardnessTextEditCtrl.getText(); %macroSize = %this-->macroSizeCtrl.getText(); %macroStrength = %this-->macroStrengthCtrl.getText(); @@ -725,6 +730,7 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %materialAssetId ) %mat.parallaxScale == %parallaxScale && %mat.blendHeightBase == %blendHeightBase && %mat.blendHeightContrast == %blendHeightContrast && + %mat.blendHeightHardness == %blendHeightHardness && %mat.isSRGB == %isSRGB && %mat.invertRoughness == %invertRoughness && %fxMat.effectColor[0] == %effectColor0 && @@ -772,6 +778,7 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %materialAssetId ) %mat.parallaxScale = %parallaxScale; %mat.blendHeightBase = %blendHeightBase; %mat.blendHeightContrast = %blendHeightContrast; + %mat.blendHeightHardness = %blendHeightHardness; %mat.isSRGB = %isSRGB; %mat.invertRoughness = %invertRoughness; @@ -861,6 +868,7 @@ function TerrainMaterialDlg::snapshotMaterials( %this ) parallaxScale = %mat.parallaxScale; blendHeightBase = %mat.blendHeightBase; blendHeightContrast = %mat.blendHeightContrast; + blendHeightHardness = %mat.blendHeightHardness; isSRGB = %mat.isSRGB; invertRoughness = %mat.invertRoughness; }; @@ -901,6 +909,7 @@ function TerrainMaterialDlg::restoreMaterials( %this ) %mat.parallaxScale = %obj.parallaxScale; %mat.blendHeightBase = %obj.blendHeightBase; %mat.blendHeightContrast = %obj.blendHeightContrast; + %mat.blendHeightHardness = %obj.blendHeightHardness; %mat.isSRGB = %obj.isSRGB; %mat.invertRoughness = %obj.invertRoughness; } @@ -971,6 +980,25 @@ function TerrainMaterialDlgBlendHeightContrastTextEdit::onValidate(%this) TerrainMaterialDlg.matDirty = true; } +function TerrainMaterialDlgBlendHeightHardnessSlider::onMouseDragged(%this) +{ + %value = mClamp(%this.value, 0.0, 0.999); + %value = mFloor(%value * 1000)/1000; + TerrainMaterialDlgBlendHeightHardnessTextEdit.setText(%value); + TerrainMaterialDlg.activeMat.blendHeightHardness = %value; + TerrainMaterialDlg.matDirty = true; +} + +function TerrainMaterialDlgBlendHeightHardnessTextEdit::onValidate(%this) +{ + %value = mClamp(%this.getText(), 0.0, 0.999); + %value = mFloor(%value * 1000)/1000; + %this.setText(%value); + TerrainMaterialDlgBlendHeightHardnessSlider.setValue(%value); + TerrainMaterialDlg.activeMat.blendHeightHardness = %value; + TerrainMaterialDlg.matDirty = true; +} + // // function terrMatEdDragNDropMapAssignment(%mapName, %payload)