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