terrFeatureHLSL.cpp
Engine/source/terrain/hlsl/terrFeatureHLSL.cpp
Public Variables
Detailed Description
Public Variables
MODULE_END
MODULE_INIT
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "terrain/hlsl/terrFeatureHLSL.h" 26 27#include "terrain/terrFeatureTypes.h" 28#include "materials/materialFeatureTypes.h" 29#include "materials/materialFeatureData.h" 30#include "materials/processedMaterial.h" 31#include "gfx/gfxDevice.h" 32#include "shaderGen/langElement.h" 33#include "shaderGen/shaderOp.h" 34#include "shaderGen/featureType.h" 35#include "shaderGen/featureMgr.h" 36#include "shaderGen/shaderGen.h" 37#include "core/module.h" 38 39namespace 40{ 41 void register_hlsl_shader_features_for_terrain(GFXAdapterType type) 42 { 43 if (type != Direct3D11) 44 return; 45 46 FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatHLSL ); 47 FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureHLSL( "Terrain Parallax Texture" ) ); 48 FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatHLSL ); 49 FEATUREMGR->registerFeature( MFT_TerrainNormalMap, new TerrainNormalMapFeatHLSL ); 50 FEATUREMGR->registerFeature( MFT_TerrainMacroMap, new NamedFeatureHLSL("TerrainMacroMap Deprecated")); // new TerrainMacroMapFeatHLSL); 51 FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL ); 52 FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) ); 53 FEATUREMGR->registerFeature( MFT_TerrainHeightBlend, new TerrainHeightMapBlendHLSL ); 54 FEATUREMGR->registerFeature( MFT_TerrainORMMap, new TerrainORMMapFeatHLSL ); 55 FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL ); 56 } 57}; 58 59MODULE_BEGIN( TerrainFeatHLSL ) 60 61 MODULE_INIT_AFTER( ShaderGen ) 62 63 MODULE_INIT 64 { 65 SHADERGEN->getFeatureInitSignal().notify(®ister_hlsl_shader_features_for_terrain); 66 } 67 68MODULE_END; 69 70 71TerrainFeatHLSL::TerrainFeatHLSL() 72 : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" )) 73{ 74 addDependency( &mTorqueDep ); 75} 76 77Var* TerrainFeatHLSL::_getUniformVar( const char *name, const char *type, ConstantSortPosition csp ) 78{ 79 Var *theVar = (Var*)LangElement::find( name ); 80 if ( !theVar ) 81 { 82 theVar = new Var; 83 theVar->setType( type ); 84 theVar->setName( name ); 85 theVar->uniform = true; 86 theVar->constSortPos = csp; 87 } 88 89 return theVar; 90} 91 92Var* TerrainFeatHLSL::_getInDetailCoord( Vector<ShaderComponent*> &componentList ) 93{ 94 String name( String::ToString( "detCoord%d", getProcessIndex() ) ); 95 Var *inDet = (Var*)LangElement::find( name ); 96 97 if ( !inDet ) 98 { 99 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 100 101 inDet = connectComp->getElement( RT_TEXCOORD ); 102 inDet->setName( name ); 103 inDet->setStructName( "IN" ); 104 inDet->setType( "float4" ); 105 } 106 107 return inDet; 108} 109 110Var* TerrainFeatHLSL::_getInMacroCoord( Vector<ShaderComponent*> &componentList ) 111{ 112 String name( String::ToString( "macroCoord%d", getProcessIndex() ) ); 113 Var *inDet = (Var*)LangElement::find( name ); 114 115 if ( !inDet ) 116 { 117 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 118 119 inDet = connectComp->getElement( RT_TEXCOORD ); 120 inDet->setName( name ); 121 inDet->setStructName( "IN" ); 122 inDet->setType( "float4" ); 123 } 124 125 return inDet; 126} 127 128Var* TerrainFeatHLSL::_getDetailMapSampler() 129{ 130 String name("detailMapSampler"); 131 Var* detailMapSampler = (Var*)LangElement::find(name); 132 133 if(!detailMapSampler) 134 { 135 detailMapSampler = new Var; 136 detailMapSampler->setName(name); 137 detailMapSampler->setType("SamplerState"); 138 detailMapSampler->uniform = true; 139 detailMapSampler->sampler = true; 140 detailMapSampler->constNum = Var::getTexUnitNum(); 141 } 142 143 return detailMapSampler; 144} 145 146Var* TerrainFeatHLSL::_getDetailMapArray() 147{ 148 String name("detailMapArray"); 149 Var* detailMapArray = (Var*)LangElement::find(name); 150 151 if(!detailMapArray) 152 { 153 detailMapArray = new Var; 154 detailMapArray->setName(name); 155 detailMapArray->setType("Texture2DArray"); 156 detailMapArray->uniform = true; 157 detailMapArray->texture = true; 158 detailMapArray->constNum = _getDetailMapSampler()->constNum; 159 } 160 161 return detailMapArray; 162} 163 164Var* TerrainFeatHLSL::_getNormalMapSampler() 165{ 166 String name("normalMapSampler"); 167 Var* normalMapSampler = (Var*)LangElement::find(name); 168 169 if (!normalMapSampler) 170 { 171 normalMapSampler = new Var; 172 normalMapSampler->setName(name); 173 normalMapSampler->setType("SamplerState"); 174 normalMapSampler->uniform = true; 175 normalMapSampler->sampler = true; 176 normalMapSampler->constNum = Var::getTexUnitNum(); 177 } 178 179 return normalMapSampler; 180} 181 182Var* TerrainFeatHLSL::_getNormalMapArray() 183{ 184 String name("normalMapArray"); 185 Var* normalMapArray = (Var*)LangElement::find(name); 186 187 if (!normalMapArray) 188 { 189 normalMapArray = new Var; 190 normalMapArray->setName(name); 191 normalMapArray->setType("Texture2DArray"); 192 normalMapArray->uniform = true; 193 normalMapArray->texture = true; 194 normalMapArray->constNum = _getNormalMapSampler()->constNum; 195 } 196 197 return normalMapArray; 198} 199 200Var* TerrainFeatHLSL::_getOrmMapSampler() 201{ 202 String name("ormMapSampler"); 203 Var* ormMapSampler = (Var*)LangElement::find(name); 204 205 if (!ormMapSampler) 206 { 207 ormMapSampler = new Var; 208 ormMapSampler->setName(name); 209 ormMapSampler->setType("SamplerState"); 210 ormMapSampler->uniform = true; 211 ormMapSampler->sampler = true; 212 ormMapSampler->constNum = Var::getTexUnitNum(); 213 } 214 215 return ormMapSampler; 216} 217 218Var* TerrainFeatHLSL::_getOrmMapArray() 219{ 220 String name("ormMapArray"); 221 Var* ormMapArray = (Var*)LangElement::find(name); 222 223 if (!ormMapArray) 224 { 225 ormMapArray = new Var; 226 ormMapArray->setName(name); 227 ormMapArray->setType("Texture2DArray"); 228 ormMapArray->uniform = true; 229 ormMapArray->texture = true; 230 ormMapArray->constNum = _getOrmMapSampler()->constNum; 231 } 232 233 return ormMapArray; 234} 235 236Var* TerrainFeatHLSL::_getDetailIdStrengthParallax() 237{ 238 String name( String::ToString( "detailIdStrengthParallax", getProcessIndex() ) ); 239 240 Var *detailInfo = (Var*)LangElement::find( name ); 241 if ( !detailInfo ) 242 { 243 detailInfo = new Var; 244 detailInfo->setType( "float4" ); 245 detailInfo->setName( name ); 246 detailInfo->uniform = true; 247 detailInfo->constSortPos = cspPotentialPrimitive; 248 detailInfo->arraySize = getProcessIndex(); 249 } 250 251 detailInfo->arraySize = mMax(detailInfo->arraySize, getProcessIndex() + 1); 252 253 return detailInfo; 254} 255 256Var* TerrainFeatHLSL::_getMacroIdStrengthParallax() 257{ 258 String name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) ); 259 260 Var *detailInfo = (Var*)LangElement::find( name ); 261 if ( !detailInfo ) 262 { 263 detailInfo = new Var; 264 detailInfo->setType( "float3" ); 265 detailInfo->setName( name ); 266 detailInfo->uniform = true; 267 detailInfo->constSortPos = cspPotentialPrimitive; 268 } 269 270 return detailInfo; 271} 272 273 274void TerrainBaseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 275 const MaterialFeatureData &fd ) 276{ 277 MultiLine *meta = new MultiLine; 278 output = meta; 279 280 // Generate the incoming texture var. 281 Var *inTex; 282 { 283 Var *inPos = (Var*)LangElement::find( "inPosition" ); 284 if ( !inPos ) 285 inPos = (Var*)LangElement::find( "position" ); 286 287 inTex = new Var( "texCoord", "float3" ); 288 289 Var *oneOverTerrainSize = _getUniformVar( "oneOverTerrainSize", "float", cspPass ); 290 291 // NOTE: The y coord here should be negative to have 292 // the texture maps not end up flipped which also caused 293 // normal and parallax mapping to be incorrect. 294 // 295 // This mistake early in development means that the layer 296 // id bilinear blend depends on it being that way. 297 // 298 // So instead i fixed this by flipping the base and detail 299 // coord y scale to compensate when rendering. 300 // 301 meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n", 302 new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) ); 303 } 304 305 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 306 307 // Pass the texture coord to the pixel shader. 308 Var *outTex = connectComp->getElement( RT_TEXCOORD ); 309 outTex->setName( "outTexCoord" ); 310 outTex->setStructName( "OUT" ); 311 outTex->setType( "float3" ); 312 meta->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex, inTex ) ); 313 314 // If this shader has a side projected layer then we 315 // pass the dot product between the +Y and the normal 316 // thru outTexCoord.z for use in blending the textures. 317 if ( fd.features.hasFeature( MFT_TerrainSideProject ) ) 318 { 319 Var *inNormal = (Var*)LangElement::find( "normal" ); 320 meta->addStatement( 321 new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n", 322 outTex, inNormal, inNormal ) ); 323 } 324 else 325 meta->addStatement( new GenOp( " @.z = 0;\r\n", outTex ) ); 326 327 // HACK: This is sort of lazy... we generate the tanget 328 // vector here so that we're sure it exists in the parallax 329 // and normal features which will expect "T" to exist. 330 // 331 // If this shader doesn't use it the shader compiler will 332 // optimize away this code. 333 // 334 Var *inTangentZ = getVertTexCoord( "tcTangentZ" ); 335 Var *inTanget = new Var( "T", "float3" ); 336 Var *squareSize = _getUniformVar( "squareSize", "float", cspPass ); 337 meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n", 338 new DecOp( inTanget ), squareSize, inTangentZ ) ); 339} 340 341void TerrainBaseMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 342 const MaterialFeatureData &fd ) 343{ 344 // grab connector texcoord register 345 Var *texCoord = getInTexCoord( "texCoord", "float3", componentList ); 346 347 // create texture var 348 Var *diffuseMap = new Var; 349 diffuseMap->setType( "SamplerState" ); 350 diffuseMap->setName( "baseTexMap" ); 351 diffuseMap->uniform = true; 352 diffuseMap->sampler = true; 353 diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 354 355 MultiLine *meta = new MultiLine; 356 357 Var *baseColor = new Var; 358 baseColor->setType( "float4" ); 359 baseColor->setName( "baseColor" ); 360 361 Var *diffuseTex = new Var; 362 diffuseTex->setType("Texture2D"); 363 diffuseTex->setName("baseTexture"); 364 diffuseTex->uniform = true; 365 diffuseTex->texture = true; 366 diffuseTex->constNum = diffuseMap->constNum; 367 meta->addStatement(new GenOp(" @ = @.Sample( @, @.xy );\r\n", new DecOp(baseColor), diffuseTex, diffuseMap, texCoord)); 368 369 ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; 370 371 if (fd.features.hasFeature(MFT_isDeferred)) 372 { 373 target= ShaderFeature::RenderTarget1; 374 } 375 376 meta->addStatement( new GenOp( " @;\r\n", assignColor( baseColor, Material::Mul,NULL,target ) ) ); 377 378 if (fd.features[MFT_isDeferred]) 379 { 380 // Set base ORM info 381 Var* ormConfig; 382 OutputTarget targ = RenderTarget1; 383 targ = RenderTarget2; 384 ormConfig = (Var*)LangElement::find(getOutputTargetVarName(targ)); 385 if (!ormConfig) 386 { 387 // create color var 388 ormConfig = new Var; 389 ormConfig->setType("fragout"); 390 ormConfig->setName(getOutputTargetVarName(targ)); 391 ormConfig->setStructName("OUT"); 392 } 393 394 meta->addStatement(new GenOp(" @ = float4(0.0, 1.0, 1.0, 0.0);\r\n", ormConfig)); 395 } 396 397 output = meta; 398} 399 400ShaderFeature::Resources TerrainBaseMapFeatHLSL::getResources( const MaterialFeatureData &fd ) 401{ 402 Resources res; 403 res.numTexReg = 1; 404 res.numTex = 1; 405 406 return res; 407} 408 409U32 TerrainBaseMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const 410{ 411 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 | ShaderFeature::RenderTarget2 : ShaderFeature::DefaultTarget; 412} 413 414TerrainDetailMapFeatHLSL::TerrainDetailMapFeatHLSL() 415 : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" )), 416 mTerrainDep(ShaderGen::smCommonShaderPath + String("/terrain/terrain.hlsl" )) 417 418{ 419 addDependency( &mTorqueDep ); 420 addDependency( &mTerrainDep ); 421} 422 423void TerrainDetailMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 424 const MaterialFeatureData &fd ) 425{ 426 const S32 detailIndex = getProcessIndex(); 427 428 // Grab incoming texture coords... the base map feature 429 // made sure this was created. 430 Var *inTex = (Var*)LangElement::find( "texCoord" ); 431 AssertFatal( inTex, "The texture coord is missing!" ); 432 433 // Grab the input position. 434 Var *inPos = (Var*)LangElement::find( "inPosition" ); 435 if ( !inPos ) 436 inPos = (Var*)LangElement::find( "position" ); 437 438 // Get the object space eye position. 439 Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive ); 440 441 MultiLine *meta = new MultiLine; 442 443 // If we have parallax mapping then make sure we've sent 444 // the negative view vector to the pixel shader. 445 if ( fd.features.hasFeature( MFT_TerrainParallaxMap ) && 446 !LangElement::find( "outNegViewTS" ) ) 447 { 448 // Get the object to tangent transform which 449 // will consume 3 output registers. 450 Var *objToTangentSpace = getOutObjToTangentSpace( componentList, meta, fd ); 451 452 // Now use a single output register to send the negative 453 // view vector in tangent space to the pixel shader. 454 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 455 Var *outNegViewTS = connectComp->getElement( RT_TEXCOORD ); 456 outNegViewTS->setName( "outNegViewTS" ); 457 outNegViewTS->setStructName( "OUT" ); 458 outNegViewTS->setType( "float3" ); 459 meta->addStatement( new GenOp( " @ = mul( @, float3( @ - @.xyz ) );\r\n", 460 outNegViewTS, objToTangentSpace, eyePos, inPos ) ); 461 } 462 463 // Get the distance from the eye to this vertex. 464 Var *dist = (Var*)LangElement::find( "dist" ); 465 if ( !dist ) 466 { 467 dist = new Var; 468 dist->setType( "float" ); 469 dist->setName( "dist" ); 470 471 meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n", 472 new DecOp( dist ), inPos, eyePos ) ); 473 } 474 475 // grab connector texcoord register 476 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 477 Var *outTex = connectComp->getElement( RT_TEXCOORD ); 478 outTex->setName( String::ToString( "detCoord%d", detailIndex ) ); 479 outTex->setStructName( "OUT" ); 480 outTex->setType( "float4" ); 481 482 // Get the detail scale and fade info. 483 Var* detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade"); 484 if (detScaleAndFade == NULL) 485 { 486 detScaleAndFade = new Var; 487 detScaleAndFade->setType("float4"); 488 detScaleAndFade->setName("detailScaleAndFade"); 489 detScaleAndFade->uniform = true; 490 detScaleAndFade->constSortPos = cspPotentialPrimitive; 491 } 492 493 detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1); 494 495 // Setup the detail coord. 496 // 497 // NOTE: You see here we scale the texture coord by 'xyx' 498 // to generate the detail coord. This y is here because 499 // its scale is flipped to correct for the non negative y 500 // in texCoord. 501 // 502 // See TerrainBaseMapFeatHLSL::processVert(). 503 // 504 meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex) ) ); 505 506 // And sneak the detail fade thru the w detailCoord. 507 meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", 508 outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex)) ); 509 510 output = meta; 511} 512 513void TerrainDetailMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 514 const MaterialFeatureData &fd ) 515{ 516 const S32 detailIndex = getProcessIndex(); 517 Var *inTex = getVertTexCoord( "texCoord" ); 518 519 MultiLine *meta = new MultiLine; 520 521 // We need the negative tangent space view vector 522 // as in parallax mapping we step towards the camera. 523 Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); 524 if ( !negViewTS && 525 fd.features.hasFeature( MFT_TerrainParallaxMap ) ) 526 { 527 Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); 528 if ( !inNegViewTS ) 529 { 530 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 531 inNegViewTS = connectComp->getElement( RT_TEXCOORD ); 532 inNegViewTS->setName( "outNegViewTS" ); 533 inNegViewTS->setStructName( "IN" ); 534 inNegViewTS->setType( "float3" ); 535 } 536 537 negViewTS = new Var( "negViewTS", "float3" ); 538 meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); 539 } 540 541 // Get the layer samples. 542 Var *layerSample = (Var*)LangElement::find( "layerSample" ); 543 if ( !layerSample ) 544 { 545 layerSample = new Var; 546 layerSample->setType( "float4" ); 547 layerSample->setName( "layerSample" ); 548 549 // Get the layer texture var 550 Var *layerTex = new Var; 551 layerTex->setType( "SamplerState" ); 552 layerTex->setName( "layerTex" ); 553 layerTex->uniform = true; 554 layerTex->sampler = true; 555 layerTex->constNum = Var::getTexUnitNum(); 556 557 Var* layerTexObj = new Var; 558 layerTexObj->setName("layerTexObj"); 559 layerTexObj->setType("Texture2D"); 560 layerTexObj->uniform = true; 561 layerTexObj->texture = true; 562 layerTexObj->constNum = layerTex->constNum; 563 // Read the layer texture to get the samples. 564 meta->addStatement(new GenOp(" @ = round( @.Sample( @, @.xy ) * 255.0f );\r\n", 565 new DecOp(layerSample), layerTexObj, layerTex, inTex)); 566 } 567 568 Var *layerSize = (Var*)LangElement::find( "layerSize" ); 569 if ( !layerSize ) 570 { 571 layerSize = new Var; 572 layerSize->setType( "float" ); 573 layerSize->setName( "layerSize" ); 574 layerSize->uniform = true; 575 layerSize->constSortPos = cspPass; 576 } 577 578 // Grab the incoming detail coord. 579 Var *inDet = _getInDetailCoord( componentList ); 580 581 // Get the detail id. 582 Var *detailInfo = _getDetailIdStrengthParallax(); 583 584 // Create the detail blend var. 585 Var *detailBlend = new Var; 586 detailBlend->setType( "float" ); 587 detailBlend->setName( String::ToString( "detailBlend%d", detailIndex ) ); 588 589 // Calculate the blend for this detail texture. 590 meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", 591 new DecOp( detailBlend ), new IndexOp(detailInfo, detailIndex), inTex, layerSize, layerSample ) ); 592 593 // If we had a parallax feature... then factor in the parallax 594 // amount so that it fades out with the layer blending. 595 if (fd.features.hasFeature(MFT_TerrainParallaxMap, detailIndex)) 596 { 597 Var* normalMapArray = _getNormalMapArray(); 598 Var* normalMapSampler = _getNormalMapSampler(); 599 600 // Call the library function to do the rest. 601 if (fd.features.hasFeature(MFT_IsBC3nm, detailIndex)) 602 { 603 meta->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnmTexArray( @, @, float3(@.xy, @.x), @, @.z * @ );\r\n", 604 inDet, normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, detailIndex), negViewTS, new IndexOp(detailInfo, detailIndex), detailBlend)); 605 } 606 else 607 { 608 meta->addStatement(new GenOp(" @.xy += parallaxOffsetTexArray( @, @, float3(@.xy, @.x), @, @.z * @ );\r\n", 609 inDet, normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, detailIndex), negViewTS, new IndexOp(detailInfo, detailIndex), detailBlend)); 610 } 611 612 } 613 614 Var *detailColor = (Var*)LangElement::find(String::ToString("detailColor%d", detailIndex)); 615 if ( !detailColor ) 616 { 617 detailColor = new Var; 618 detailColor->setType( "float4" ); 619 detailColor->setName( String::ToString("detailColor%d", detailIndex) ); 620 meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); 621 } 622 623 //Sampled detail texture that is not expanded 624 Var* detailMapArray = _getDetailMapArray(); 625 Var* detailMapSampler = _getDetailMapSampler(); 626 627 if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) 628 { 629 meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n", 630 detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), inTex)); 631 } 632 else 633 { 634 meta->addStatement(new GenOp(" @ = ( @.Sample( @, float3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n", 635 detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex))); 636 } 637 638 meta->addStatement(new GenOp(" @ *= @.y * @.w;\r\n", 639 detailColor, new IndexOp(detailInfo, detailIndex), inDet)); 640 641 if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) 642 { 643 // Check to see if we have a gbuffer normal. 644 Var* gbNormal = (Var*)LangElement::find("gbNormal"); 645 646 // If we have a gbuffer normal and we don't have a 647 // normal map feature then we need to lerp in a 648 // default normal else the normals below this layer 649 // will show thru. 650 if (gbNormal && 651 !fd.features.hasFeature(MFT_TerrainNormalMap, detailIndex)) 652 { 653 Var* viewToTangent = getInViewToTangent(componentList); 654 655 meta->addStatement(new GenOp(" @ = lerp( @, @[2], min( @, @.w ) );\r\n", 656 gbNormal, gbNormal, viewToTangent, detailBlend, inDet)); 657 } 658 659 // If we're using SM 3.0 then take advantage of 660 // dynamic branching to skip layers per-pixel. 661 if (GFX->getPixelShaderVersion() >= 3.0f) 662 meta->addStatement(new GenOp(" if ( @ > 0.0f )\r\n", detailBlend)); 663 664 meta->addStatement(new GenOp(" {\r\n")); 665 666 ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; 667 668 if (fd.features.hasFeature(MFT_isDeferred)) 669 target = ShaderFeature::RenderTarget1; 670 671 Var* outColor = (Var*)LangElement::find(getOutputTargetVarName(target)); 672 673 meta->addStatement(new GenOp(" @.rgb = toGamma(@.rgb);\r\n", outColor, outColor)); 674 675 meta->addStatement(new GenOp(" @ += @ * @;\r\n", 676 outColor, detailColor, detailBlend)); 677 678 meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n", outColor, outColor)); 679 680 meta->addStatement(new GenOp(" }\r\n")); 681 } 682 683 output = meta; 684} 685 686ShaderFeature::Resources TerrainDetailMapFeatHLSL::getResources( const MaterialFeatureData &fd ) 687{ 688 Resources res; 689 690 if ( getProcessIndex() == 0 ) 691 { 692 // If this is the first detail pass then we 693 // samples from the layer tex. 694 res.numTex += 1; 695 res.numTexReg += 1; 696 697 // Add Detail TextureArray 698 res.numTex += 1; 699 res.numTexReg += 1; 700 } 701 702 return res; 703} 704 705U32 TerrainDetailMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const 706{ 707 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; 708} 709 710 711TerrainMacroMapFeatHLSL::TerrainMacroMapFeatHLSL() 712 : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" )), 713 mTerrainDep(ShaderGen::smCommonShaderPath + String("/terrain/terrain.hlsl" )) 714 715{ 716 addDependency( &mTorqueDep ); 717 addDependency( &mTerrainDep ); 718} 719 720 721void TerrainMacroMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 722 const MaterialFeatureData &fd ) 723{ 724 const S32 detailIndex = getProcessIndex(); 725 726 // Grab incoming texture coords... the base map feature 727 // made sure this was created. 728 Var *inTex = (Var*)LangElement::find( "texCoord" ); 729 AssertFatal( inTex, "The texture coord is missing!" ); 730 731 // Grab the input position. 732 Var *inPos = (Var*)LangElement::find( "inPosition" ); 733 if ( !inPos ) 734 inPos = (Var*)LangElement::find( "position" ); 735 736 // Get the object space eye position. 737 Var *eyePos = _getUniformVar( "eyePos", "float3", cspPotentialPrimitive ); 738 739 MultiLine *meta = new MultiLine; 740 741 // Get the distance from the eye to this vertex. 742 Var *dist = (Var*)LangElement::find( "macroDist" ); 743 if ( !dist ) 744 { 745 dist = new Var; 746 dist->setType( "float" ); 747 dist->setName( "macroDist" ); 748 749 meta->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n", 750 new DecOp( dist ), inPos, eyePos ) ); 751 } 752 753 // grab connector texcoord register 754 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 755 Var *outTex = connectComp->getElement( RT_TEXCOORD ); 756 outTex->setName( String::ToString( "macroCoord%d", detailIndex ) ); 757 outTex->setStructName( "OUT" ); 758 outTex->setType( "float4" ); 759 760 // Get the detail scale and fade info. 761 Var* macroScaleAndFade = (Var*)LangElement::find("macroScaleAndFade"); 762 if (macroScaleAndFade == NULL) 763 { 764 macroScaleAndFade = new Var; 765 macroScaleAndFade->setType("float4"); 766 macroScaleAndFade->setName("macroScaleAndFade"); 767 macroScaleAndFade->uniform = true; 768 macroScaleAndFade->constSortPos = cspPotentialPrimitive; 769 } 770 771 macroScaleAndFade->arraySize = mMax(macroScaleAndFade->arraySize, detailIndex + 1); 772 773 // Setup the detail coord. 774 meta->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(macroScaleAndFade, detailIndex)) ); 775 776 // And sneak the detail fade thru the w detailCoord. 777 meta->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", 778 outTex, new IndexOp(macroScaleAndFade, detailIndex), dist, new IndexOp(macroScaleAndFade, detailIndex)) ); 779 780 output = meta; 781} 782 783 784void TerrainMacroMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 785 const MaterialFeatureData &fd ) 786{ 787 const S32 detailIndex = getProcessIndex(); 788 Var *inTex = getVertTexCoord( "texCoord" ); 789 790 MultiLine *meta = new MultiLine; 791 792 // We need the negative tangent space view vector 793 // as in parallax mapping we step towards the camera. 794 Var *negViewTS = (Var*)LangElement::find( "negViewTS" ); 795 if ( !negViewTS && 796 fd.features.hasFeature( MFT_TerrainParallaxMap ) ) 797 { 798 Var *inNegViewTS = (Var*)LangElement::find( "outNegViewTS" ); 799 if ( !inNegViewTS ) 800 { 801 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 802 inNegViewTS = connectComp->getElement( RT_TEXCOORD ); 803 inNegViewTS->setName( "outNegViewTS" ); 804 inNegViewTS->setStructName( "IN" ); 805 inNegViewTS->setType( "float3" ); 806 } 807 808 negViewTS = new Var( "negViewTS", "float3" ); 809 meta->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS ), inNegViewTS ) ); 810 } 811 812 // Get the layer samples. 813 Var *layerSample = (Var*)LangElement::find( "layerSample" ); 814 if ( !layerSample ) 815 { 816 layerSample = new Var; 817 layerSample->setType( "float4" ); 818 layerSample->setName( "layerSample" ); 819 820 // Get the layer texture var 821 Var *layerTex = new Var; 822 layerTex->setType( "SamplerState" ); 823 layerTex->setName( "macrolayerTex" ); 824 layerTex->uniform = true; 825 layerTex->sampler = true; 826 layerTex->constNum = Var::getTexUnitNum(); 827 828 // Read the layer texture to get the samples. 829 Var *layerTexObj = new Var; 830 layerTexObj->setType("Texture2D"); 831 layerTexObj->setName("macroLayerTexObj"); 832 layerTexObj->uniform = true; 833 layerTexObj->texture = true; 834 layerTexObj->constNum = layerTex->constNum; 835 meta->addStatement(new GenOp(" @ = round( @.Sample( @, @.xy ) * 255.0f );\r\n", 836 new DecOp(layerSample), layerTexObj, layerTex, inTex)); 837 } 838 839 Var *layerSize = (Var*)LangElement::find( "layerSize" ); 840 if ( !layerSize ) 841 { 842 layerSize = new Var; 843 layerSize->setType( "float" ); 844 layerSize->setName( "layerSize" ); 845 layerSize->uniform = true; 846 layerSize->constSortPos = cspPass; 847 } 848 849 // Grab the incoming detail coord. 850 Var *inDet = _getInMacroCoord( componentList ); 851 852 // Get the detail id. 853 Var *detailInfo = _getMacroIdStrengthParallax(); 854 855 // Create the detail blend var. 856 Var *detailBlend = new Var; 857 detailBlend->setType( "float" ); 858 detailBlend->setName( String::ToString( "macroBlend%d", detailIndex ) ); 859 860 // Calculate the blend for this detail texture. 861 meta->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n", 862 new DecOp( detailBlend ), new IndexOp(detailInfo, detailIndex), inTex, layerSize, layerSample ) ); 863 864 // Check to see if we have a gbuffer normal. 865 Var *gbNormal = (Var*)LangElement::find( "gbNormal" ); 866 867 // If we have a gbuffer normal and we don't have a 868 // normal map feature then we need to lerp in a 869 // default normal else the normals below this layer 870 // will show thru. 871 if ( gbNormal && 872 !fd.features.hasFeature( MFT_TerrainNormalMap, detailIndex ) ) 873 { 874 Var *viewToTangent = getInViewToTangent( componentList ); 875 876 meta->addStatement( new GenOp( " @ = lerp( @, @[2], min( @, @.w ) );\r\n", 877 gbNormal, gbNormal, viewToTangent, detailBlend, inDet ) ); 878 } 879 880 Var *detailColor = (Var*)LangElement::find("macroColor"); 881 if (!detailColor) 882 { 883 detailColor = new Var; 884 detailColor->setType( "float4" ); 885 detailColor->setName( "macroColor" ); 886 meta->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor ) ) ); 887 } 888 889 // If we're using SM 3.0 then take advantage of 890 // dynamic branching to skip layers per-pixel. 891 if ( GFX->getPixelShaderVersion() >= 3.0f ) 892 meta->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend ) ); 893 894 meta->addStatement( new GenOp( " {\r\n" ) ); 895 896 Var* detailMapArray = _getDetailMapArray(); 897 Var* detailMapSampler = _getDetailMapSampler(); 898 899 // Note that we're doing the standard greyscale detail 900 // map technique here which can darken and lighten the 901 // diffuse texture. 902 // 903 // We take two color samples and lerp between them for 904 // side projection layers... else a single sample. 905 // 906 if (fd.features.hasFeature(MFT_TerrainSideProject, detailIndex)) 907 { 908 meta->addStatement(new GenOp(" @ = ( lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z ) * 2.0 ) - 1.0;\r\n", 909 detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex), inTex)); 910 } 911 else 912 { 913 meta->addStatement(new GenOp(" @ = ( @.Sample( @, float3(@.xy, @.x) ) * 2.0 ) - 1.0;\r\n", 914 detailColor, detailMapArray, detailMapSampler, inDet, new IndexOp(detailInfo, detailIndex))); 915 } 916 917 meta->addStatement( new GenOp( " @ *= @.y * @.w;\r\n", 918 detailColor, new IndexOp(detailInfo, detailIndex), inDet ) ); 919 920 ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; 921 922 if (fd.features.hasFeature(MFT_isDeferred)) 923 target= ShaderFeature::RenderTarget1; 924 925 Var *outColor = (Var*)LangElement::find( getOutputTargetVarName(target) ); 926 927 meta->addStatement(new GenOp(" @.rgb = toGamma(@.rgb);\r\n", outColor, outColor)); 928 929 meta->addStatement(new GenOp(" @ += @ * @;\r\n", 930 outColor, detailColor, detailBlend)); 931 932 meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n", outColor, outColor)); 933 934 meta->addStatement( new GenOp( " }\r\n" ) ); 935 936 output = meta; 937} 938 939ShaderFeature::Resources TerrainMacroMapFeatHLSL::getResources( const MaterialFeatureData &fd ) 940{ 941 Resources res; 942 943 if ( getProcessIndex() == 0 ) 944 { 945 // If this is the first detail pass then we 946 // samples from the layer tex. 947 res.numTex += 1; 948 } 949 950 res.numTex += 1; 951 952 // Finally we always send the detail texture 953 // coord to the pixel shader. 954 res.numTexReg += 1; 955 956 return res; 957} 958 959U32 TerrainMacroMapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const 960{ 961 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; 962} 963 964void TerrainNormalMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 965 const MaterialFeatureData &fd ) 966{ 967 // We only need to process normals during the deferred. 968 if ( !fd.features.hasFeature( MFT_DeferredConditioner ) ) 969 return; 970 971 MultiLine *meta = new MultiLine; 972 973 if ( !fd.features.hasFeature(MFT_TerrainHeightBlend) ) 974 { 975 // Make sure the world to tangent transform 976 // is created and available for the pixel shader. 977 getOutViewToTangent(componentList, meta, fd); 978 } 979 980 output = meta; 981} 982 983void TerrainNormalMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 984 const MaterialFeatureData &fd ) 985{ 986 // We only need to process normals during the deferred. 987 if (!fd.features.hasFeature(MFT_DeferredConditioner)) 988 return; 989 990 MultiLine *meta = new MultiLine; 991 992 const S32 normalIndex = getProcessIndex(); 993 994 Var *detailBlend = (Var*)LangElement::find( String::ToString( "detailBlend%d", normalIndex ) ); 995 AssertFatal( detailBlend, "The detail blend is missing!" ); 996 997 /// Get the texture coord. 998 Var* inDet = _getInDetailCoord(componentList); 999 Var* inTex = getVertTexCoord("texCoord"); 1000 Var* detailInfo = _getDetailIdStrengthParallax(); 1001 1002 // Sample the normal map. 1003 // 1004 // We take two normal samples and lerp between them for 1005 // side projection layers... else a single sample. 1006 LangElement* texOp; 1007 1008 Var* normalMapSampler = _getNormalMapSampler(); 1009 Var* normalMapArray = _getNormalMapArray(); 1010 1011 if (fd.features.hasFeature(MFT_TerrainSideProject, normalIndex)) 1012 { 1013 texOp = new GenOp("lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z )", 1014 normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex), normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex), inTex); 1015 } 1016 else 1017 texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", normalMapArray, normalMapSampler, inDet, new IndexOp(detailInfo, normalIndex)); 1018 1019 // create bump normal 1020 Var* bumpNorm = new Var; 1021 bumpNorm->setName(String::ToString("bumpNormal%d", normalIndex)); 1022 bumpNorm->setType("float4"); 1023 1024 LangElement* bumpNormDecl = new DecOp(bumpNorm); 1025 meta->addStatement(expandNormalMap(texOp, bumpNormDecl, bumpNorm, fd)); 1026 1027 if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) 1028 { 1029 Var* viewToTangent = getInViewToTangent(componentList); 1030 1031 // This var is read from GBufferConditionerHLSL and 1032 // used in the deferred output. 1033 Var* gbNormal = (Var*)LangElement::find("gbNormal"); 1034 if (!gbNormal) 1035 { 1036 gbNormal = new Var; 1037 gbNormal->setName("gbNormal"); 1038 gbNormal->setType("float3"); 1039 meta->addStatement(new GenOp(" @ = @[2];\r\n", new DecOp(gbNormal), viewToTangent)); 1040 } 1041 1042 // If we're using SM 3.0 then take advantage of 1043 // dynamic branching to skip layers per-pixel. 1044 if (GFX->getPixelShaderVersion() >= 3.0f) 1045 meta->addStatement(new GenOp(" if ( @ > 0.0f )\r\n", detailBlend)); 1046 1047 meta->addStatement(new GenOp(" {\r\n")); 1048 1049 // Normalize is done later... 1050 // Note: The reverse mul order is intentional. Affine matrix. 1051 meta->addStatement(new GenOp(" @ = lerp( @, mul( @.xyz, @ ), min( @, @.w ) );\r\n", 1052 gbNormal, gbNormal, bumpNorm, viewToTangent, detailBlend, inDet)); 1053 1054 // End the conditional block. 1055 meta->addStatement(new GenOp(" }\r\n")); 1056 } 1057 1058 output = meta; 1059} 1060 1061ShaderFeature::Resources TerrainNormalMapFeatHLSL::getResources( const MaterialFeatureData &fd ) 1062{ 1063 Resources res; 1064 1065 if (!fd.features.hasFeature(MFT_DeferredConditioner)) 1066 { 1067 return res; 1068 } 1069 1070 S32 featureIndex = 0, firstNormalMapIndex = 0; 1071 for (int idx = 0; idx < fd.features.getCount(); ++idx) { 1072 const FeatureType &type = fd.features.getAt(idx, &featureIndex); 1073 if (type == MFT_TerrainNormalMap) { 1074 firstNormalMapIndex = getMin(firstNormalMapIndex, featureIndex); 1075 } 1076 } 1077 1078 // We only need to process normals during the deferred. 1079 if (getProcessIndex() == firstNormalMapIndex) 1080 { 1081 res.numTexReg += 1; 1082 res.numTex += 1; 1083 } 1084 1085 return res; 1086} 1087 1088void TerrainLightMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 1089 const MaterialFeatureData &fd ) 1090{ 1091 // grab connector texcoord register 1092 Var *inTex = (Var*)LangElement::find( "texCoord" ); 1093 if ( !inTex ) 1094 return; 1095 1096 // Get the lightmap texture. 1097 Var *lightMap = new Var; 1098 lightMap->setType( "SamplerState" ); 1099 lightMap->setName( "lightMapTex" ); 1100 lightMap->uniform = true; 1101 lightMap->sampler = true; 1102 lightMap->constNum = Var::getTexUnitNum(); 1103 1104 MultiLine *meta = new MultiLine; 1105 1106 // Find or create the lightMask value which is read by 1107 // RTLighting to mask out the lights. 1108 // 1109 // The first light is always the sunlight so we apply 1110 // the shadow mask to only the first channel. 1111 // 1112 Var *lightMask = (Var*)LangElement::find( "lightMask" ); 1113 if ( !lightMask ) 1114 { 1115 lightMask = new Var( "lightMask", "float4" ); 1116 meta->addStatement( new GenOp( " @ = 1;\r\n", new DecOp( lightMask ) ) ); 1117 } 1118 1119 Var* lightMapTex = new Var; 1120 lightMapTex->setName("lightMapTexObj"); 1121 lightMapTex->setType("Texture2D"); 1122 lightMapTex->uniform = true; 1123 lightMapTex->texture = true; 1124 lightMapTex->constNum = lightMap->constNum; 1125 meta->addStatement(new GenOp(" @[0] = @.Sample( @, @.xy ).r;\r\n", lightMask, lightMapTex, lightMap, inTex)); 1126 1127 output = meta; 1128} 1129 1130ShaderFeature::Resources TerrainLightMapFeatHLSL::getResources( const MaterialFeatureData &fd ) 1131{ 1132 Resources res; 1133 res.numTex = 1; 1134 return res; 1135} 1136 1137//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), 1138//.b = specular strength, a= spec power. 1139 1140void TerrainORMMapFeatHLSL::processVert(Vector<ShaderComponent*> &componentList, 1141 const MaterialFeatureData &fd) 1142{ 1143 const S32 detailIndex = getProcessIndex(); 1144 1145 // Grab incoming texture coords... the base map feature 1146 // made sure this was created. 1147 Var *inTex = (Var*)LangElement::find("texCoord"); 1148 AssertFatal(inTex, "The texture coord is missing!"); 1149 1150 // Grab the input position. 1151 Var *inPos = (Var*)LangElement::find("inPosition"); 1152 if (!inPos) 1153 inPos = (Var*)LangElement::find("position"); 1154 1155 // Get the object space eye position. 1156 Var *eyePos = _getUniformVar("eyePos", "float3", cspPotentialPrimitive); 1157 1158 MultiLine *meta = new MultiLine; 1159 1160 // If we have parallax mapping then make sure we've sent 1161 // the negative view vector to the pixel shader. 1162 if (fd.features.hasFeature(MFT_TerrainParallaxMap) && 1163 !LangElement::find("outNegViewTS")) 1164 { 1165 // Get the object to tangent transform which 1166 // will consume 3 output registers. 1167 Var *objToTangentSpace = getOutObjToTangentSpace(componentList, meta, fd); 1168 1169 // Now use a single output register to send the negative 1170 // view vector in tangent space to the pixel shader. 1171 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]); 1172 Var *outNegViewTS = connectComp->getElement(RT_TEXCOORD); 1173 outNegViewTS->setName("outNegViewTS"); 1174 outNegViewTS->setStructName("OUT"); 1175 outNegViewTS->setType("float3"); 1176 meta->addStatement(new GenOp(" @ = mul( @, float3( @ - @.xyz ) );\r\n", 1177 outNegViewTS, objToTangentSpace, eyePos, inPos)); 1178 } 1179 1180 // Get the distance from the eye to this vertex. 1181 Var *dist = (Var*)LangElement::find("dist"); 1182 if (!dist) 1183 { 1184 dist = new Var; 1185 dist->setType("float"); 1186 dist->setName("dist"); 1187 1188 meta->addStatement(new GenOp(" @ = distance( @.xyz, @ );\r\n", 1189 new DecOp(dist), inPos, eyePos)); 1190 } 1191 1192 // grab connector texcoord register 1193 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]); 1194 Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex)); 1195 if (outTex == NULL) 1196 { 1197 outTex = connectComp->getElement(RT_TEXCOORD); 1198 outTex->setName(String::ToString("detCoord%d", detailIndex)); 1199 outTex->setStructName("OUT"); 1200 outTex->setType("float4"); 1201 } 1202 // Get the detail scale and fade info. 1203 Var *detScaleAndFade = (Var*)LangElement::find("detailScaleAndFade"); 1204 if (detScaleAndFade == NULL) 1205 { 1206 detScaleAndFade = new Var; 1207 detScaleAndFade->setType("float4"); 1208 detScaleAndFade->setName("detailScaleAndFade"); 1209 detScaleAndFade->uniform = true; 1210 detScaleAndFade->constSortPos = cspPotentialPrimitive; 1211 } 1212 1213 detScaleAndFade->arraySize = mMax(detScaleAndFade->arraySize, detailIndex + 1); 1214 1215 // Setup the detail coord. 1216 // 1217 // NOTE: You see here we scale the texture coord by 'xyx' 1218 // to generate the detail coord. This y is here because 1219 // its scale is flipped to correct for the non negative y 1220 // in texCoord. 1221 // 1222 // See TerrainBaseMapFeatHLSL::processVert(). 1223 // 1224 meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, new IndexOp(detScaleAndFade, detailIndex))); 1225 1226 // And sneak the detail fade thru the w detailCoord. 1227 meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n", 1228 outTex, new IndexOp(detScaleAndFade, detailIndex), dist, new IndexOp(detScaleAndFade, detailIndex))); 1229 1230 output = meta; 1231} 1232 1233U32 TerrainORMMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const 1234{ 1235 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget2 : ShaderFeature::DefaultTarget; 1236} 1237 1238void TerrainORMMapFeatHLSL::processPix(Vector<ShaderComponent*> &componentList, 1239 const MaterialFeatureData &fd) 1240{ 1241 /// Get the texture coord. 1242 Var *inDet = _getInDetailCoord(componentList); 1243 Var *inTex = getVertTexCoord("texCoord"); 1244 Var* detailInfo = _getDetailIdStrengthParallax(); 1245 1246 const S32 compositeIndex = getProcessIndex(); 1247 // Sample the normal map. 1248 // 1249 // We take two normal samples and lerp between them for 1250 // side projection layers... else a single sample. 1251 LangElement *texOp; 1252 1253 Var* ormMapArray = _getOrmMapArray(); 1254 Var* ormMapSampler = _getOrmMapSampler(); 1255 if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex)) 1256 { 1257 texOp = new GenOp("lerp( @.Sample( @, float3(@.yz, @.x) ), @.Sample( @, float3(@.xz, @.x) ), @.z )", 1258 ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex), ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex), inTex); 1259 } 1260 else 1261 texOp = new GenOp("@.Sample(@, float3(@.xy, @.x))", ormMapArray, ormMapSampler, inDet, new IndexOp(detailInfo, compositeIndex)); 1262 1263 // search for material var 1264 Var * ormConfig; 1265 OutputTarget targ = RenderTarget1; 1266 if (fd.features[MFT_isDeferred]) 1267 { 1268 targ = RenderTarget2; 1269 } 1270 ormConfig = (Var*)LangElement::find(getOutputTargetVarName(targ)); 1271 1272 MultiLine * meta = new MultiLine; 1273 if (!ormConfig) 1274 { 1275 // create color var 1276 ormConfig = new Var; 1277 ormConfig->setType("fragout"); 1278 ormConfig->setName(getOutputTargetVarName(targ)); 1279 ormConfig->setStructName("OUT"); 1280 } 1281 1282 Var *detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", compositeIndex)); 1283 AssertFatal(detailBlend, "The detail blend is missing!"); 1284 1285 String matinfoName(String::ToString("matinfoCol%d", compositeIndex)); 1286 Var *matinfoCol = new Var(matinfoName, "float3"); 1287 1288 if (compositeIndex == 0) 1289 { 1290 meta->addStatement(new GenOp(" @ = float4(0.0, 0.0, 0.0, 0.0);\r\n", ormConfig)); 1291 } 1292 1293 meta->addStatement(new GenOp(" @ = @.rgb;\r\n", new DecOp(matinfoCol), texOp)); 1294 1295 if (fd.features.hasFeature(MFT_InvertRoughness, compositeIndex)) 1296 { 1297 meta->addStatement(new GenOp(" @.b = 1.0 - @.b;\r\n", matinfoCol, matinfoCol)); 1298 } 1299 1300 meta->addStatement(new GenOp(" @ = lerp(float3(1.0, 1.0, 0.0), @, @.y * @.w);\r\n", matinfoCol, matinfoCol, new IndexOp(detailInfo, compositeIndex), inDet)); 1301 1302 if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) 1303 { 1304 meta->addStatement(new GenOp(" @.gba += @ * @;\r\n", ormConfig, matinfoCol, detailBlend)); 1305 } 1306 1307 output = meta; 1308} 1309 1310ShaderFeature::Resources TerrainORMMapFeatHLSL::getResources(const MaterialFeatureData &fd) 1311{ 1312 Resources res; 1313 res.numTex = 1; 1314 return res; 1315} 1316 1317// reminder, the matinfo buffer is flags, smooth, ao, metal 1318U32 TerrainBlankInfoMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const 1319{ 1320 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1; 1321} 1322 1323void TerrainBlankInfoMapFeatHLSL::processPix(Vector<ShaderComponent*> &componentList, 1324 const MaterialFeatureData &fd) 1325{ 1326 S32 compositeIndex = getProcessIndex(); 1327 1328 // search for material var 1329 Var *material; 1330 OutputTarget ormConfig = RenderTarget1; 1331 if (fd.features[MFT_isDeferred]) 1332 { 1333 ormConfig = RenderTarget2; 1334 } 1335 material = (Var*)LangElement::find(getOutputTargetVarName(ormConfig)); 1336 1337 MultiLine * meta = new MultiLine; 1338 if (!material) 1339 { 1340 // create color var 1341 material = new Var; 1342 material->setType("fragout"); 1343 material->setName(getOutputTargetVarName(ormConfig)); 1344 material->setStructName("OUT"); 1345 } 1346 1347 if (compositeIndex == 0) 1348 { 1349 meta->addStatement(new GenOp(" @ = float4(0.0, 0.0, 0.0, 0.0);\r\n", material)); 1350 } 1351 1352 Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", compositeIndex)); 1353 AssertFatal(detailBlend, "The detail blend is missing!"); 1354 1355 String matinfoName(String::ToString("matinfoCol%d", compositeIndex)); 1356 1357 if (!fd.features.hasFeature(MFT_TerrainHeightBlend)) 1358 { 1359 meta->addStatement(new GenOp(" @.gba += float3(@, @, 0.0);\r\n", material, detailBlend, detailBlend)); 1360 } 1361 1362 output = meta; 1363} 1364 1365void TerrainHeightMapBlendHLSL::processVert(Vector<ShaderComponent*>& componentList, 1366 const MaterialFeatureData& fd) 1367{ 1368 // We only need to process normals during the deferred. 1369 if (!fd.features.hasFeature(MFT_DeferredConditioner)) 1370 return; 1371 1372 MultiLine* meta = new MultiLine; 1373 1374 // Handle an edge-case when there are no detail-maps available 1375 if (fd.features.getNextFeatureIndex(MFT_TerrainDetailMap, -1) >= 0) 1376 { 1377 // Make sure the world to tangent transform 1378 // is created and available for the pixel shader. 1379 getOutViewToTangent(componentList, meta, fd); 1380 } 1381 1382 output = meta; 1383} 1384 1385void TerrainHeightMapBlendHLSL::processPix(Vector<ShaderComponent*>& componentList, 1386 const MaterialFeatureData& fd) 1387{ 1388 1389 ShaderFeature::OutputTarget target = ShaderFeature::DefaultTarget; 1390 1391 if (fd.features.hasFeature(MFT_isDeferred)) 1392 target = ShaderFeature::RenderTarget1; 1393 1394 Var* outColor = (Var*)LangElement::find(getOutputTargetVarName(target)); 1395 1396 if (!outColor) 1397 return; 1398 1399 MultiLine* meta = new MultiLine; 1400 1401 // Count number of detail layers 1402 int detailCount = 0; 1403 while (true) 1404 { 1405 if(LangElement::find(String::ToString("detailBlend%d", detailCount)) == NULL) 1406 { 1407 break; 1408 } 1409 1410 ++detailCount; 1411 } 1412 1413 if ( detailCount == 0 ) 1414 { 1415 return; 1416 } 1417 1418 // Compute blend factors 1419 for (S32 idx = 0; idx < detailCount; ++idx) 1420 { 1421 Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); 1422 Var* bumpNormal = (Var*)LangElement::find(String::ToString("bumpNormal%d", idx)); 1423 Var* blendDepth = (Var*)LangElement::find(String::ToString("blendDepth%d", idx)); 1424 if (!blendDepth) 1425 { 1426 blendDepth = new Var; 1427 blendDepth->setType("float"); 1428 blendDepth->setName(String::ToString("blendDepth%d", idx)); 1429 blendDepth->uniform = true; 1430 blendDepth->constSortPos = cspPrimitive; 1431 } 1432 1433 Var* blendContrast = (Var*)LangElement::find(String::ToString("blendContrast%d", idx)); 1434 if (!blendContrast) 1435 { 1436 blendContrast = new Var; 1437 blendContrast->setType("float"); 1438 blendContrast->setName(String::ToString("blendContrast%d", idx)); 1439 blendContrast->uniform = true; 1440 blendContrast->constSortPos = cspPrimitive; 1441 } 1442 1443 Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); 1444 if (!detailH) 1445 { 1446 detailH = new Var; 1447 detailH->setType("float"); 1448 detailH->setName(String::ToString("detailH%d", idx)); 1449 1450 meta->addStatement(new GenOp(" @ = 0;\r\n", 1451 new DecOp(detailH))); 1452 meta->addStatement(new GenOp(" if (@ > 0.0f) {\r\n", detailBlend)); 1453 if (bumpNormal != NULL) 1454 { 1455 meta->addStatement(new GenOp(" @ = clamp(@.a + @, 0.0, 1.0);\r\n", 1456 detailH, bumpNormal, blendDepth)); 1457 } 1458 else 1459 { 1460 meta->addStatement(new GenOp(" @ = clamp(0.5 + @, 0.0, 1.0);\r\n", 1461 detailH, blendDepth)); 1462 } 1463 1464 meta->addStatement(new GenOp(" @ = max((@ * 2.0f - 1.0f) * @ + 0.5f, 0.0f);\r\n", 1465 detailH, detailH, blendContrast)); 1466 1467 meta->addStatement(new GenOp(" }\r\n")); 1468 } 1469 } 1470 1471 meta->addStatement(new GenOp("\r\n")); 1472 1473 Var* depth = (Var*)LangElement::find("baseBlendDepth"); 1474 if (depth == NULL) 1475 { 1476 depth = new Var; 1477 depth->setType("float"); 1478 depth->setName("baseBlendDepth"); 1479 depth->uniform = true; 1480 depth->constSortPos = cspPrimitive; 1481 } 1482 1483 Var* ma = (Var*)LangElement::find("ma"); 1484 if (ma == NULL) 1485 { 1486 ma = new Var; 1487 ma->setType("float"); 1488 ma->setName("ma"); 1489 meta->addStatement(new GenOp(" @ = 0;\r\n", 1490 new DecOp(ma))); 1491 } 1492 1493 for (S32 idx = 0; idx < detailCount; ++idx) 1494 { 1495 Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); 1496 Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); 1497 1498 meta->addStatement(new GenOp(" @ = max(@, @ + @);\r\n", 1499 ma, ma, detailH, detailBlend)); 1500 } 1501 1502 meta->addStatement(new GenOp(" @ -= @;\r\n", 1503 ma, depth)); 1504 1505 meta->addStatement(new GenOp("\r\n")); 1506 1507 for (S32 idx = 0; idx < detailCount; ++idx) 1508 { 1509 Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); 1510 Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); 1511 Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx)); 1512 if (!detailB) 1513 { 1514 detailB = new Var; 1515 detailB->setType("float"); 1516 detailB->setName(String::ToString("detailB%d", idx)); 1517 1518 meta->addStatement(new GenOp(" @ = max(@ + @ - @, 0);\r\n", 1519 new DecOp(detailB), detailH, detailBlend, ma)); 1520 } 1521 } 1522 1523 meta->addStatement(new GenOp("\r\n")); 1524 1525 // Compute albedo 1526 meta->addStatement(new GenOp(" @.rgb = toGamma(@.rgb);\r\n", 1527 outColor, outColor)); 1528 1529 meta->addStatement(new GenOp(" @.rgb += (", 1530 outColor)); 1531 1532 for (S32 idx = 0; idx < detailCount; ++idx) 1533 { 1534 Var* detailColor = (Var*)LangElement::find(String::ToString("detailColor%d", idx)); 1535 Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx)); 1536 1537 1538 if (idx > 0) 1539 { 1540 meta->addStatement(new GenOp(" + ")); 1541 } 1542 1543 meta->addStatement(new GenOp("@.rgb * @", detailColor, detailB)); 1544 } 1545 1546 meta->addStatement(new GenOp(") / (")); 1547 1548 for (S32 idx = 0; idx < detailCount; ++idx) 1549 { 1550 Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx)); 1551 1552 if (idx > 0) 1553 { 1554 meta->addStatement(new GenOp(" + ")); 1555 } 1556 1557 meta->addStatement(new GenOp("@", detailB)); 1558 } 1559 1560 1561 meta->addStatement(new GenOp(");\r\n")); 1562 1563 meta->addStatement(new GenOp(" @.rgb = toLinear(clamp(@.rgb, 0, 1));\r\n", 1564 outColor, outColor)); 1565 1566 meta->addStatement(new GenOp("\r\n")); 1567 1568 // Compute ORM 1569 Var* ormOutput; 1570 OutputTarget targ = DefaultTarget; 1571 if (fd.features[MFT_isDeferred]) 1572 { 1573 targ = RenderTarget2; 1574 } 1575 ormOutput = (Var*)LangElement::find(getOutputTargetVarName(targ)); 1576 1577 meta->addStatement(new GenOp(" @.gba = (", 1578 ormOutput)); 1579 1580 for (S32 idx = 0; idx < detailCount; ++idx) 1581 { 1582 Var* matinfoCol = (Var*)LangElement::find(String::ToString("matinfoCol%d", idx)); 1583 Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx)); 1584 1585 1586 if (idx > 0) 1587 { 1588 meta->addStatement(new GenOp(" + ")); 1589 } 1590 if (matinfoCol) 1591 { 1592 meta->addStatement(new GenOp("@ * @", matinfoCol, detailB)); 1593 } 1594 else 1595 { 1596 meta->addStatement(new GenOp("float3(1.0, 1.0, 0.0) * @", detailB)); 1597 } 1598 } 1599 1600 meta->addStatement(new GenOp(") / (")); 1601 1602 for (S32 idx = 0; idx < detailCount; ++idx) 1603 { 1604 Var* detailB = (Var*)LangElement::find(String::ToString("detailB%d", idx)); 1605 1606 if (idx > 0) 1607 { 1608 meta->addStatement(new GenOp(" + ")); 1609 } 1610 1611 meta->addStatement(new GenOp("@", detailB)); 1612 } 1613 1614 1615 meta->addStatement(new GenOp(");\r\n")); 1616 1617 1618 meta->addStatement(new GenOp("\r\n")); 1619 1620 // Compute normal-specific blending factors 1621 // LukasPJ: I'm not sure why this is necessary, it might not be. 1622 Var* normalMa = (Var*)LangElement::find("normalMa"); 1623 if (normalMa == NULL) 1624 { 1625 normalMa = new Var; 1626 normalMa->setType("float"); 1627 normalMa->setName("normalMa"); 1628 meta->addStatement(new GenOp(" @ = 0;\r\n", 1629 new DecOp(normalMa))); 1630 } 1631 1632 for (S32 idx = 0; idx < detailCount; ++idx) 1633 { 1634 Var* detCoord = (Var*)LangElement::find(String::ToString("detCoord%d", idx)); 1635 1636 Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); 1637 Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); 1638 1639 meta->addStatement(new GenOp(" @ = max(@, @ + min(@, @.w));\r\n", 1640 normalMa, normalMa, detailH, detailBlend, detCoord)); 1641 } 1642 1643 meta->addStatement(new GenOp(" @ -= @;\r\n", 1644 normalMa, depth)); 1645 1646 meta->addStatement(new GenOp("\r\n")); 1647 1648 for (S32 idx = 0; idx < detailCount; ++idx) 1649 { 1650 Var* detCoord = (Var*)LangElement::find(String::ToString("detCoord%d", idx)); 1651 1652 Var* detailH = (Var*)LangElement::find(String::ToString("detailH%d", idx)); 1653 Var* detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", idx)); 1654 Var* normalDetailB = (Var*)LangElement::find(String::ToString("normalDetailB%d", idx)); 1655 if (!normalDetailB) 1656 { 1657 normalDetailB = new Var; 1658 normalDetailB->setType("float"); 1659 normalDetailB->setName(String::ToString("normalDetailB%d", idx)); 1660 1661 meta->addStatement(new GenOp(" @ = max(@ + min(@, @.w) - @, 0);\r\n", 1662 new DecOp(normalDetailB), detailH, detailBlend, detCoord, normalMa)); 1663 } 1664 } 1665 1666 // Compute normals 1667 Var* gbNormal = (Var*)LangElement::find("gbNormal"); 1668 if (!gbNormal) 1669 { 1670 gbNormal = new Var; 1671 gbNormal->setName("gbNormal"); 1672 gbNormal->setType("float3"); 1673 meta->addStatement(new GenOp(" @;\r\n", new DecOp(gbNormal))); 1674 } 1675 1676 if (gbNormal != NULL) 1677 { 1678 meta->addStatement(new GenOp(" @ = (", 1679 gbNormal)); 1680 1681 for (S32 idx = 0; idx < detailCount; ++idx) 1682 { 1683 Var* normalDetailB = (Var*)LangElement::find(String::ToString("normalDetailB%d", idx)); 1684 Var* bumpNormal = (Var*)LangElement::find(String::ToString("bumpNormal%d", idx)); 1685 Var* viewToTangent = getInViewToTangent(componentList); 1686 1687 1688 if (idx > 0) 1689 { 1690 meta->addStatement(new GenOp(" + ")); 1691 } 1692 1693 if (bumpNormal != NULL) 1694 { 1695 meta->addStatement(new GenOp("mul(@.xyz, @) * @", bumpNormal, viewToTangent, normalDetailB)); 1696 } 1697 else 1698 { 1699 meta->addStatement(new GenOp("@[2] * @", viewToTangent, normalDetailB)); 1700 } 1701 } 1702 1703 meta->addStatement(new GenOp(") / (")); 1704 1705 for (S32 idx = 0; idx < detailCount; ++idx) 1706 { 1707 Var* normalDetailB = (Var*)LangElement::find(String::ToString("normalDetailB%d", idx)); 1708 1709 if (idx > 0) 1710 { 1711 meta->addStatement(new GenOp(" + ")); 1712 } 1713 1714 meta->addStatement(new GenOp("@", normalDetailB)); 1715 } 1716 1717 1718 meta->addStatement(new GenOp(");\r\n")); 1719 } 1720 1721 1722 output = meta; 1723} 1724