shaderFeatureHLSL.cpp
Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp
Detailed Description
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 "shaderGen/HLSL/shaderFeatureHLSL.h" 26 27#include "shaderGen/langElement.h" 28#include "shaderGen/shaderOp.h" 29#include "shaderGen/shaderGenVars.h" 30#include "gfx/gfxDevice.h" 31#include "materials/matInstance.h" 32#include "materials/processedMaterial.h" 33#include "materials/materialFeatureTypes.h" 34#include "core/util/autoPtr.h" 35 36#include "lighting/advanced/advancedLightBinManager.h" 37#include "ts/tsShape.h" 38 39#include "shaderGen/shaderGen.h" 40 41LangElement * ShaderFeatureHLSL::setupTexSpaceMat( Vector<ShaderComponent*> &, // componentList 42 Var **texSpaceMat ) 43{ 44 Var *N = (Var*) LangElement::find( "normal" ); 45 Var *B = (Var*) LangElement::find( "B" ); 46 Var *T = (Var*) LangElement::find( "T" ); 47 48 Var *tangentW = (Var*) LangElement::find( "tangentW" ); 49 50 // setup matrix var 51 *texSpaceMat = new Var; 52 (*texSpaceMat)->setType( "float3x3" ); 53 (*texSpaceMat)->setName( "objToTangentSpace" ); 54 55 MultiLine *meta = new MultiLine; 56 meta->addStatement( new GenOp( " @;\r\n", new DecOp( *texSpaceMat ) ) ); 57 58 // Protect against missing normal and tangent. 59 if ( !N || !T ) 60 { 61 meta->addStatement( new GenOp( " @[0] = float3( 1, 0, 0 ); @[1] = float3( 0, 1, 0 ); @[2] = float3( 0, 0, 1 );\r\n", 62 *texSpaceMat, *texSpaceMat, *texSpaceMat ) ); 63 return meta; 64 } 65 66 meta->addStatement( new GenOp( " @[0] = @;\r\n", *texSpaceMat, T ) ); 67 if ( B ) 68 meta->addStatement( new GenOp( " @[1] = @;\r\n", *texSpaceMat, B ) ); 69 else 70 { 71 if(dStricmp((char*)T->type, "float4") == 0) 72 meta->addStatement( new GenOp( " @[1] = cross( @, normalize(@) ) * @.w;\r\n", *texSpaceMat, T, N, T ) ); 73 else if (tangentW) 74 meta->addStatement(new GenOp(" @[1] = cross( @, normalize(@) ) * @;\r\n", *texSpaceMat, <a href="/coding/group/group__engineapi__types/#group__engineapi__types_1ga16a0f7e7053a679c9bf4289b441a2be7">T</a>, N, tangentW)); 75 else 76 meta->addStatement( new GenOp( " @[1] = cross( @, normalize(@) );\r\n", *texSpaceMat, T, N ) ); 77 } 78 meta->addStatement( new GenOp( " @[2] = normalize(@);\r\n", *texSpaceMat, N ) ); 79 80 return meta; 81} 82 83LangElement* ShaderFeatureHLSL::assignColor( LangElement *elem, 84 Material::BlendOp blend, 85 LangElement *lerpElem, 86 ShaderFeature::OutputTarget outputTarget ) 87{ 88 89 // search for color var 90 Var *color = (Var*) LangElement::find( getOutputTargetVarName(outputTarget) ); 91 92 if ( !color ) 93 { 94 // create color var 95 color = new Var; 96 color->setType( "fragout" ); 97 color->setName( getOutputTargetVarName(outputTarget) ); 98 color->setStructName( "OUT" ); 99 100 return new GenOp( "@ = @", color, elem ); 101 } 102 103 LangElement *assign; 104 105 switch ( blend ) 106 { 107 case Material::Add: 108 assign = new GenOp( "@ += @", color, elem ); 109 break; 110 111 case Material::Sub: 112 assign = new GenOp( "@ -= @", color, elem ); 113 break; 114 115 case Material::Mul: 116 assign = new GenOp( "@ *= @", color, elem ); 117 break; 118 119 case Material::PreMul: 120 assign = new GenOp("@.rgb = @.rgb + (@.rgb*(1.0-@.a))", color, elem, color, elem); 121 break; 122 123 case Material::AddAlpha: 124 assign = new GenOp( "@ += @ * @.a", color, elem, elem ); 125 break; 126 127 case Material::LerpAlpha: 128 if ( !lerpElem ) 129 lerpElem = elem; 130 assign = new GenOp( "@.rgb = lerp( @.rgb, (@).rgb, (@).a )", color, color, elem, lerpElem ); 131 break; 132 133 case Material::ToneMap: 134 assign = new GenOp( "@ = 1.0 - exp(-1.0 * @ * @)", color, color, elem ); 135 break; 136 137 default: 138 AssertFatal(false, "Unrecognized color blendOp"); 139 // Fallthru 140 141 case Material::None: 142 assign = new GenOp( "@ = @", color, elem ); 143 break; 144 } 145 146 return assign; 147} 148 149 150LangElement *ShaderFeatureHLSL::expandNormalMap( LangElement *sampleNormalOp, 151 LangElement *normalDecl, 152 LangElement *normalVar, 153 const MaterialFeatureData &fd ) 154{ 155 MultiLine *meta = new MultiLine; 156 const bool hasBc3 = fd.features.hasFeature(MFT_IsBC3nm, getProcessIndex() ); 157 const bool hasBc5 = fd.features.hasFeature(MFT_IsBC5nm, getProcessIndex() ); 158 if ( hasBc3 || hasBc5 ) 159 { 160 if ( fd.features[MFT_ImposterVert] ) 161 { 162 // The imposter system uses object space normals and 163 // encodes them with the z axis in the alpha component. 164 meta->addStatement( new GenOp( " @ = float4( normalize( @.xyw * 2.0 - 1.0 ), 0.0 ); // Obj DXTnm\r\n", normalDecl, sampleNormalOp ) ); 165 } 166 else if( hasBc3 ) 167 { 168 // BC3 Swizzle trick 169 meta->addStatement( new GenOp( " @ = float4( @.ag * 2.0 - 1.0, 0.0, 0.0 ); // DXTnm\r\n", normalDecl, sampleNormalOp ) ); 170 meta->addStatement( new GenOp( " @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // DXTnm\r\n", normalVar, normalVar, normalVar ) ); 171 } 172 else if (hasBc5) 173 { 174 // BC5 175 meta->addStatement(new GenOp(" @ = float4( @.gr * 2.0 - 1.0, 0.0, 0.0 ); // bc5nm\r\n", normalDecl, sampleNormalOp ) ); 176 meta->addStatement(new GenOp(" @.z = sqrt( 1.0 - dot( @.xy, @.xy ) ); // bc5nm\r\n", normalVar, normalVar, normalVar )) ; 177 } 178 } 179 else 180 { 181 meta->addStatement( new GenOp( " @ = @;\r\n", normalDecl, sampleNormalOp ) ); 182 meta->addStatement( new GenOp( " @.xyz = @.xyz * 2.0 - 1.0;\r\n", normalVar, normalVar ) ); 183 } 184 185 return meta; 186} 187 188ShaderFeatureHLSL::ShaderFeatureHLSL() 189{ 190 output = NULL; 191} 192 193Var * ShaderFeatureHLSL::getVertTexCoord( const String &name ) 194{ 195 Var *inTex = NULL; 196 197 for( U32 i=0; i<LangElement::elementList.size(); i++ ) 198 { 199 if( !String::compare( (char*)LangElement::elementList[i]->name, name.c_str() ) ) 200 { 201 inTex = dynamic_cast<Var*>( LangElement::elementList[i] ); 202 if ( inTex ) 203 { 204 // NOTE: This used to do this check... 205 // 206 // String::compare( (char*)inTex->structName, "IN" ) 207 // 208 // ... to ensure that the var was from the input 209 // vertex structure, but this kept some features 210 // ( ie. imposter vert ) from decoding their own 211 // coords for other features to use. 212 // 213 // If we run into issues with collisions between 214 // IN vars and local vars we may need to revise. 215 216 break; 217 } 218 } 219 } 220 221 return inTex; 222} 223 224Var* ShaderFeatureHLSL::getOutObjToTangentSpace( Vector<ShaderComponent*> &componentList, 225 MultiLine *meta, 226 const MaterialFeatureData &fd ) 227{ 228 Var *outObjToTangentSpace = (Var*)LangElement::find( "objToTangentSpace" ); 229 if ( !outObjToTangentSpace ) 230 meta->addStatement( setupTexSpaceMat( componentList, &outObjToTangentSpace ) ); 231 232 return outObjToTangentSpace; 233} 234 235Var* ShaderFeatureHLSL::getOutWorldToTangent( Vector<ShaderComponent*> &componentList, 236 MultiLine *meta, 237 const MaterialFeatureData &fd ) 238{ 239 Var *outWorldToTangent = (Var*)LangElement::find( "outWorldToTangent" ); 240 if ( outWorldToTangent ) 241 return outWorldToTangent; 242 243 Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" ); 244 if ( !worldToTangent ) 245 { 246 Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd ); 247 248 if (!fd.features[MFT_ParticleNormal] ) 249 { 250 // turn obj->tangent into world->tangent 251 worldToTangent = new Var; 252 worldToTangent->setType( "float3x3" ); 253 worldToTangent->setName( "worldToTangent" ); 254 LangElement *worldToTangentDecl = new DecOp( worldToTangent ); 255 256 // Get the world->obj transform 257 Var *worldToObj = (Var*)LangElement::find( "worldToObj" ); 258 if ( !worldToObj ) 259 { 260 worldToObj = new Var; 261 worldToObj->setName( "worldToObj" ); 262 263 if ( fd.features[MFT_UseInstancing] ) 264 { 265 // We just use transpose to convert the 3x3 portion of 266 // the object transform to its inverse. 267 worldToObj->setType( "float3x3" ); 268 Var *objTrans = getObjTrans( componentList, true, meta ); 269 meta->addStatement( new GenOp( " @ = transpose( (float3x3)@ ); // Instancing!\r\n", new DecOp( worldToObj ), objTrans ) ); 270 } 271 else 272 { 273 worldToObj->setType( "float4x4" ); 274 worldToObj->uniform = true; 275 worldToObj->constSortPos = cspPrimitive; 276 } 277 } 278 279 // assign world->tangent transform 280 meta->addStatement( new GenOp( " @ = mul( @, (float3x3)@ );\r\n", worldToTangentDecl, texSpaceMat, worldToObj ) ); 281 } 282 else 283 { 284 // Assume particle normal generation has set this up in the proper space 285 worldToTangent = texSpaceMat; 286 } 287 } 288 289 // send transform to pixel shader 290 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 291 292 outWorldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); 293 outWorldToTangent->setName( "outWorldToTangent" ); 294 outWorldToTangent->setStructName( "OUT" ); 295 outWorldToTangent->setType( "float3x3" ); 296 meta->addStatement( new GenOp( " @ = @;\r\n", outWorldToTangent, worldToTangent ) ); 297 298 return outWorldToTangent; 299} 300 301Var* ShaderFeatureHLSL::getOutViewToTangent( Vector<ShaderComponent*> &componentList, 302 MultiLine *meta, 303 const MaterialFeatureData &fd ) 304{ 305 Var *outViewToTangent = (Var*)LangElement::find( "outViewToTangent" ); 306 if ( outViewToTangent ) 307 return outViewToTangent; 308 309 Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" ); 310 if ( !viewToTangent ) 311 { 312 313 Var *texSpaceMat = getOutObjToTangentSpace( componentList, meta, fd ); 314 315 if ( !fd.features[MFT_ParticleNormal] ) 316 { 317 // turn obj->tangent into world->tangent 318 viewToTangent = new Var; 319 viewToTangent->setType( "float3x3" ); 320 viewToTangent->setName( "viewToTangent" ); 321 LangElement *viewToTangentDecl = new DecOp( viewToTangent ); 322 323 // Get the view->obj transform 324 Var *viewToObj = getInvWorldView( componentList, fd.features[MFT_UseInstancing], meta ); 325 326 // assign world->tangent transform 327 meta->addStatement( new GenOp( " @ = mul( @, (float3x3)@ );\r\n", viewToTangentDecl, texSpaceMat, viewToObj ) ); 328 } 329 else 330 { 331 // Assume particle normal generation has set this up in the proper space 332 viewToTangent = texSpaceMat; 333 } 334 } 335 336 // send transform to pixel shader 337 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 338 339 outViewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); 340 outViewToTangent->setName( "outViewToTangent" ); 341 outViewToTangent->setStructName( "OUT" ); 342 outViewToTangent->setType( "float3x3" ); 343 meta->addStatement( new GenOp( " @ = @;\r\n", outViewToTangent, viewToTangent ) ); 344 345 return outViewToTangent; 346} 347 348Var* ShaderFeatureHLSL::getOutTexCoord( const char *name, 349 const char *type, 350 bool useTexAnim, 351 MultiLine *meta, 352 Vector<ShaderComponent*> &componentList ) 353{ 354 String outTexName = String::ToString( "out_%s", name ); 355 Var *texCoord = (Var*)LangElement::find( outTexName ); 356 if ( !texCoord ) 357 { 358 Var *inTex = getVertTexCoord( name ); 359 AssertFatal( inTex, "ShaderFeatureHLSL::getOutTexCoord - Unknown vertex input coord!" ); 360 361 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 362 363 texCoord = connectComp->getElement( RT_TEXCOORD ); 364 texCoord->setName( outTexName ); 365 texCoord->setStructName( "OUT" ); 366 texCoord->setType( type ); 367 368 if ( useTexAnim ) 369 { 370 inTex->setType( "float2" ); 371 372 // create texture mat var 373 Var *texMat = new Var; 374 texMat->setType( "float4x4" ); 375 texMat->setName( "texMat" ); 376 texMat->uniform = true; 377 texMat->constSortPos = cspPass; 378 379 // Statement allows for casting of different types which 380 // eliminates vector truncation problems. 381 String statement = String::ToString(" @ = (%s)mul(@, float4(@,1,1));\r\n", type); 382 meta->addStatement( new GenOp( statement, texCoord, texMat, inTex ) ); 383 } 384 else 385 { 386 // Statement allows for casting of different types which 387 // eliminates vector truncation problems. 388 String statement = String::ToString( " @ = (%s)@;\r\n", type ); 389 meta->addStatement( new GenOp( statement, texCoord, inTex ) ); 390 } 391 } 392 393 AssertFatal( String::compare( type, (const char*)texCoord->type ) == 0, 394 "ShaderFeatureHLSL::getOutTexCoord - Type mismatch!" ); 395 396 return texCoord; 397} 398 399Var* ShaderFeatureHLSL::getInTexCoord( const char *name, 400 const char *type, 401 Vector<ShaderComponent*> &componentList ) 402{ 403 Var* texCoord = (Var*)LangElement::find( name ); 404 if ( !texCoord ) 405 { 406 ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] ); 407 texCoord = connectComp->getElement( RT_TEXCOORD ); 408 texCoord->setName( name ); 409 texCoord->setStructName( "IN" ); 410 texCoord->setType( type ); 411 } 412 413 AssertFatal( String::compare( type, (const char*)texCoord->type ) == 0, 414 "ShaderFeatureHLSL::getInTexCoord - Type mismatch!" ); 415 416 return texCoord; 417} 418 419Var* ShaderFeatureHLSL::getInColor( const char *name, 420 const char *type, 421 Vector<ShaderComponent*> &componentList ) 422{ 423 Var *inColor = (Var*)LangElement::find( name ); 424 if ( !inColor ) 425 { 426 ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>( componentList[C_CONNECTOR] ); 427 inColor = connectComp->getElement( RT_COLOR ); 428 inColor->setName( name ); 429 inColor->setStructName( "IN" ); 430 inColor->setType( type ); 431 } 432 433 AssertFatal( String::compare( type, (const char*)inColor->type ) == 0, 434 "ShaderFeatureHLSL::getInColor - Type mismatch!" ); 435 436 return inColor; 437} 438 439Var* ShaderFeatureHLSL::addOutVpos( MultiLine *meta, 440 Vector<ShaderComponent*> &componentList ) 441{ 442 // Nothing to do if we're on SM 3.0... we use the real vpos. 443 if ( GFX->getPixelShaderVersion() >= 3.0f ) 444 return NULL; 445 446 // For SM 2.x we need to generate the vpos in the vertex shader 447 // and pass it as a texture coord to the pixel shader. 448 449 Var *outVpos = (Var*)LangElement::find( "outVpos" ); 450 if ( !outVpos ) 451 { 452 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 453 454 outVpos = connectComp->getElement( RT_TEXCOORD ); 455 outVpos->setName( "outVpos" ); 456 outVpos->setStructName( "OUT" ); 457 outVpos->setType( "float4" ); 458 459 Var *outPosition = (Var*) LangElement::find( "hpos" ); 460 AssertFatal( outPosition, "ShaderFeatureHLSL::addOutVpos - Didn't find the output position." ); 461 462 meta->addStatement( new GenOp( " @ = @;\r\n", outVpos, outPosition ) ); 463 } 464 465 return outVpos; 466} 467 468Var* ShaderFeatureHLSL::getInVpos( MultiLine *meta, 469 Vector<ShaderComponent*> &componentList ) 470{ 471 Var *inVpos = (Var*)LangElement::find( "vpos" ); 472 if ( inVpos ) 473 return inVpos; 474 475 ShaderConnector *connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]); 476 477 inVpos = connectComp->getElement( RT_SVPOSITION ); 478 inVpos->setName( "vpos" ); 479 inVpos->setStructName( "IN" ); 480 inVpos->setType( "float4" ); 481 return inVpos; 482} 483 484Var* ShaderFeatureHLSL::getInWorldToTangent( Vector<ShaderComponent*> &componentList ) 485{ 486 Var *worldToTangent = (Var*)LangElement::find( "worldToTangent" ); 487 if ( !worldToTangent ) 488 { 489 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 490 worldToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); 491 worldToTangent->setName( "worldToTangent" ); 492 worldToTangent->setStructName( "IN" ); 493 worldToTangent->setType( "float3x3" ); 494 } 495 496 return worldToTangent; 497} 498 499Var* ShaderFeatureHLSL::getInViewToTangent( Vector<ShaderComponent*> &componentList ) 500{ 501 Var *viewToTangent = (Var*)LangElement::find( "viewToTangent" ); 502 if ( !viewToTangent ) 503 { 504 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 505 viewToTangent = connectComp->getElement( RT_TEXCOORD, 1, 3 ); 506 viewToTangent->setName( "viewToTangent" ); 507 viewToTangent->setStructName( "IN" ); 508 viewToTangent->setType( "float3x3" ); 509 } 510 511 return viewToTangent; 512} 513 514Var* ShaderFeatureHLSL::getNormalMapTex() 515{ 516 Var *normalMap = (Var*)LangElement::find("bumpMap"); 517 if (!normalMap) 518 { 519 normalMap = new Var; 520 normalMap->setType("SamplerState"); 521 normalMap->setName("bumpMap"); 522 normalMap->uniform = true; 523 normalMap->sampler = true; 524 normalMap->constNum = Var::getTexUnitNum(); 525 526 Var* normalMapTex = new Var; 527 normalMapTex->setName("bumpMapTex"); 528 normalMapTex->setType("Texture2D"); 529 normalMapTex->uniform = true; 530 normalMapTex->texture = true; 531 normalMapTex->constNum = normalMap->constNum; 532 } 533 534 return normalMap; 535} 536 537Var* ShaderFeatureHLSL::getObjTrans( Vector<ShaderComponent*> &componentList, 538 bool useInstancing, 539 MultiLine *meta ) 540{ 541 Var *objTrans = (Var*)LangElement::find( "objTrans" ); 542 if ( objTrans ) 543 return objTrans; 544 545 if ( useInstancing ) 546 { 547 ShaderConnector *vertStruct = dynamic_cast<ShaderConnector *>( componentList[C_VERT_STRUCT] ); 548 Var *instObjTrans = vertStruct->getElement( RT_TEXCOORD, 4, 4 ); 549 instObjTrans->setStructName( "IN" ); 550 instObjTrans->setName( "inst_objectTrans" ); 551 552 mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+0 ); 553 mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+1 ); 554 mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+2 ); 555 mInstancingFormat->addElement( "objTrans", GFXDeclType_Float4, instObjTrans->constNum+3 ); 556 557 objTrans = new Var; 558 objTrans->setType( "float4x4" ); 559 objTrans->setName( "objTrans" ); 560 meta->addStatement( new GenOp( " @ = { // Instancing!\r\n", new DecOp( objTrans ), instObjTrans ) ); 561 meta->addStatement( new GenOp( " @[0],\r\n", instObjTrans ) ); 562 meta->addStatement( new GenOp( " @[1],\r\n", instObjTrans ) ); 563 meta->addStatement( new GenOp( " @[2],\r\n",instObjTrans ) ); 564 meta->addStatement( new GenOp( " @[3] };\r\n", instObjTrans ) ); 565 } 566 else 567 { 568 objTrans = new Var; 569 objTrans->setType( "float4x4" ); 570 objTrans->setName( "objTrans" ); 571 objTrans->uniform = true; 572 objTrans->constSortPos = cspPrimitive; 573 } 574 575 return objTrans; 576} 577 578Var* ShaderFeatureHLSL::getModelView( Vector<ShaderComponent*> &componentList, 579 bool useInstancing, 580 MultiLine *meta ) 581{ 582 Var *modelview = (Var*)LangElement::find( "modelview" ); 583 if ( modelview ) 584 return modelview; 585 586 if ( useInstancing ) 587 { 588 Var *objTrans = getObjTrans( componentList, useInstancing, meta ); 589 590 Var *viewProj = (Var*)LangElement::find( "viewProj" ); 591 if ( !viewProj ) 592 { 593 viewProj = new Var; 594 viewProj->setType( "float4x4" ); 595 viewProj->setName( "viewProj" ); 596 viewProj->uniform = true; 597 viewProj->constSortPos = cspPass; 598 } 599 600 modelview = new Var; 601 modelview->setType( "float4x4" ); 602 modelview->setName( "modelview" ); 603 meta->addStatement( new GenOp( " @ = mul( @, @ ); // Instancing!\r\n", new DecOp( modelview ), viewProj, objTrans ) ); 604 } 605 else 606 { 607 modelview = new Var; 608 modelview->setType( "float4x4" ); 609 modelview->setName( "modelview" ); 610 modelview->uniform = true; 611 modelview->constSortPos = cspPrimitive; 612 } 613 614 return modelview; 615} 616 617Var* ShaderFeatureHLSL::getWorldView( Vector<ShaderComponent*> &componentList, 618 bool useInstancing, 619 MultiLine *meta ) 620{ 621 Var *worldView = (Var*)LangElement::find( "worldViewOnly" ); 622 if ( worldView ) 623 return worldView; 624 625 if ( useInstancing ) 626 { 627 Var *objTrans = getObjTrans( componentList, useInstancing, meta ); 628 629 Var *worldToCamera = (Var*)LangElement::find( "worldToCamera" ); 630 if ( !worldToCamera ) 631 { 632 worldToCamera = new Var; 633 worldToCamera->setType( "float4x4" ); 634 worldToCamera->setName( "worldToCamera" ); 635 worldToCamera->uniform = true; 636 worldToCamera->constSortPos = cspPass; 637 } 638 639 worldView = new Var; 640 worldView->setType( "float4x4" ); 641 worldView->setName( "worldViewOnly" ); 642 643 meta->addStatement( new GenOp( " @ = mul( @, @ ); // Instancing!\r\n", new DecOp( worldView ), worldToCamera, objTrans ) ); 644 } 645 else 646 { 647 worldView = new Var; 648 worldView->setType( "float4x4" ); 649 worldView->setName( "worldViewOnly" ); 650 worldView->uniform = true; 651 worldView->constSortPos = cspPrimitive; 652 } 653 654 return worldView; 655} 656 657 658Var* ShaderFeatureHLSL::getInvWorldView( Vector<ShaderComponent*> &componentList, 659 bool useInstancing, 660 MultiLine *meta ) 661{ 662 Var *viewToObj = (Var*)LangElement::find( "viewToObj" ); 663 if ( viewToObj ) 664 return viewToObj; 665 666 if ( useInstancing ) 667 { 668 Var *worldView = getWorldView( componentList, useInstancing, meta ); 669 670 viewToObj = new Var; 671 viewToObj->setType( "float3x3" ); 672 viewToObj->setName( "viewToObj" ); 673 674 // We just use transpose to convert the 3x3 portion 675 // of the world view transform into its inverse. 676 677 meta->addStatement( new GenOp( " @ = transpose( (float3x3)@ ); // Instancing!\r\n", new DecOp( viewToObj ), worldView ) ); 678 } 679 else 680 { 681 viewToObj = new Var; 682 viewToObj->setType( "float4x4" ); 683 viewToObj->setName( "viewToObj" ); 684 viewToObj->uniform = true; 685 viewToObj->constSortPos = cspPrimitive; 686 } 687 688 return viewToObj; 689} 690 691void ShaderFeatureHLSL::getWsPosition( Vector<ShaderComponent*> &componentList, 692 bool useInstancing, 693 MultiLine *meta, 694 LangElement *wsPosition ) 695{ 696 Var *inPosition = (Var*)LangElement::find( "wsPosition" ); 697 if ( inPosition ) 698 { 699 meta->addStatement( new GenOp( " @ = @.xyz;\r\n", 700 wsPosition, inPosition ) ); 701 return; 702 } 703 704 // Get the input position. 705 inPosition = (Var*)LangElement::find( "inPosition" ); 706 if ( !inPosition ) 707 inPosition = (Var*)LangElement::find( "position" ); 708 709 AssertFatal( inPosition, "ShaderFeatureHLSL::getWsPosition - The vertex position was not found!" ); 710 711 Var *objTrans = getObjTrans( componentList, useInstancing, meta ); 712 713 meta->addStatement( new GenOp( " @ = mul( @, float4( @.xyz, 1 ) ).xyz;\r\n", 714 wsPosition, objTrans, inPosition ) ); 715} 716 717Var* ShaderFeatureHLSL::addOutWsPosition( Vector<ShaderComponent*> &componentList, 718 bool useInstancing, 719 MultiLine *meta ) 720{ 721 Var *outWsPosition = (Var*)LangElement::find( "outWsPosition" ); 722 if ( !outWsPosition ) 723 { 724 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 725 outWsPosition = connectComp->getElement( RT_TEXCOORD ); 726 outWsPosition->setName( "outWsPosition" ); 727 outWsPosition->setStructName( "OUT" ); 728 outWsPosition->setType( "float3" ); 729 730 getWsPosition( componentList, useInstancing, meta, outWsPosition ); 731 } 732 733 return outWsPosition; 734} 735 736Var* ShaderFeatureHLSL::getInWsPosition( Vector<ShaderComponent*> &componentList ) 737{ 738 Var *wsPosition = (Var*)LangElement::find( "wsPosition" ); 739 if ( !wsPosition ) 740 { 741 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 742 wsPosition = connectComp->getElement( RT_TEXCOORD ); 743 wsPosition->setName( "wsPosition" ); 744 wsPosition->setStructName( "IN" ); 745 wsPosition->setType( "float3" ); 746 } 747 748 return wsPosition; 749} 750 751Var* ShaderFeatureHLSL::getWsView( Var *wsPosition, MultiLine *meta ) 752{ 753 Var *wsView = (Var*)LangElement::find( "wsView" ); 754 if ( !wsView ) 755 { 756 wsView = new Var( "wsView", "float3" ); 757 758 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 759 if ( !eyePos ) 760 { 761 eyePos = new Var; 762 eyePos->setType( "float3" ); 763 eyePos->setName( "eyePosWorld" ); 764 eyePos->uniform = true; 765 eyePos->constSortPos = cspPass; 766 } 767 768 meta->addStatement( new GenOp( " @ = normalize( @ - @ );\r\n", 769 new DecOp( wsView ), eyePos, wsPosition ) ); 770 } 771 772 return wsView; 773} 774 775Var* ShaderFeatureHLSL::getInWorldNormal(Vector<ShaderComponent*>& componentList) 776{ 777 Var* wsNormal = (Var*)LangElement::find("wsNormal"); 778 if (!wsNormal) 779 { 780 ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]); 781 wsNormal = connectComp->getElement(RT_TEXCOORD); 782 wsNormal->setName("wsNormal"); 783 wsNormal->setStructName("IN"); 784 wsNormal->setType("float3"); 785 } 786 787 return wsNormal; 788} 789 790Var* ShaderFeatureHLSL::addOutDetailTexCoord( Vector<ShaderComponent*> &componentList, 791 MultiLine *meta, 792 bool useTexAnim, 793 bool useFoliageTexCoord) 794{ 795 // Check if its already added. 796 Var *outTex = (Var*)LangElement::find( "detCoord" ); 797 if ( outTex ) 798 return outTex; 799 800 // Grab incoming texture coords. 801 Var *inTex = getVertTexCoord( "texCoord" ); 802 803 if (useFoliageTexCoord) 804 inTex->setType("float4"); 805 else 806 inTex->setType("float2"); 807 808 // create detail variable 809 Var *detScale = new Var; 810 detScale->setType( "float2" ); 811 detScale->setName( "detailScale" ); 812 detScale->uniform = true; 813 detScale->constSortPos = cspPotentialPrimitive; 814 815 // grab connector texcoord register 816 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 817 outTex = connectComp->getElement( RT_TEXCOORD ); 818 outTex->setName( "detCoord" ); 819 outTex->setStructName( "OUT" ); 820 outTex->setType( "float2" ); 821 822 if ( useTexAnim ) 823 { 824 // Find or create the texture matrix. 825 Var *texMat = (Var*)LangElement::find( "texMat" ); 826 if ( !texMat ) 827 { 828 texMat = new Var; 829 texMat->setType( "float4x4" ); 830 texMat->setName( "texMat" ); 831 texMat->uniform = true; 832 texMat->constSortPos = cspPass; 833 } 834 835 meta->addStatement(new GenOp(" @ = mul(@, float4(@.xy,1,1)).xy * @;\r\n", outTex, texMat, inTex, detScale)); 836 } 837 else 838 { 839 // setup output to mul texCoord by detail scale 840 meta->addStatement( new GenOp( " @ = @.xy * @;\r\n", outTex, inTex, detScale ) ); 841 } 842 843 return outTex; 844} 845 846Var* ShaderFeatureHLSL::getSurface(Vector<ShaderComponent*>& componentList, MultiLine* meta, const MaterialFeatureData& fd) 847{ 848 ShaderConnector* connectComp = dynamic_cast<ShaderConnector*>(componentList[C_CONNECTOR]); 849 850 Var* diffuseColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); 851 852 Var* ormConfig = (Var*)LangElement::find("ORMConfig"); 853 if (!ormConfig) 854 { 855 Var* metalness = (Var*)LangElement::find("metalness"); 856 if (!metalness) 857 { 858 metalness = new Var("metalness", "float"); 859 metalness->uniform = true; 860 metalness->constSortPos = cspPotentialPrimitive; 861 } 862 863 Var* roughness = (Var*)LangElement::find("roughness"); 864 if (!roughness) 865 { 866 roughness = new Var("roughness", "float"); 867 roughness->uniform = true; 868 roughness->constSortPos = cspPotentialPrimitive; 869 } 870 871 ormConfig = new Var("ORMConfig", "float4"); 872 LangElement* colorDecl = new DecOp(ormConfig); 873 meta->addStatement(new GenOp(" @ = float4(0.0,1.0,@,@);\r\n", colorDecl, roughness, metalness)); //reconstruct matinfo, no ao darkening 874 } 875 876 Var* normal = (Var*)LangElement::find("normal"); 877 if (!normal) 878 { 879 normal = new Var("normal", "float3"); 880 meta->addStatement(new GenOp(" @;\r\n\n", new DecOp(normal))); 881 882 Var* wsNormal = (Var*)LangElement::find("wsNormal"); 883 884 if (!fd.features[MFT_NormalMap]) 885 { 886 if (!wsNormal) 887 wsNormal = getInWorldNormal(componentList); 888 889 meta->addStatement(new GenOp(" @ = normalize( @ );\r\n\n", normal, wsNormal)); 890 } 891 else 892 { 893 meta->addStatement(new GenOp(" @ = normalize( @ );\r\n", normal, wsNormal)); 894 } 895 } 896 897 Var* wsEyePos = (Var*)LangElement::find("eyePosWorld"); 898 Var* wsPosition = getInWsPosition(componentList); 899 Var* wsView = getWsView(wsPosition, meta); 900 901 Var* surface = (Var*)LangElement::find("surface"); 902 903 if (!surface) 904 { 905 surface = new Var("surface", "Surface"); 906 meta->addStatement(new GenOp(" @ = createForwardSurface(@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, normal, ormConfig, 907 wsPosition, wsEyePos, wsView)); 908 } 909 910 return surface; 911} 912//**************************************************************************** 913// Base Texture 914//**************************************************************************** 915 916DiffuseMapFeatHLSL::DiffuseMapFeatHLSL() 917: mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl")) 918{ 919 addDependency(&mTorqueDep); 920} 921 922void DiffuseMapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 923 const MaterialFeatureData &fd ) 924{ 925 MultiLine *meta = new MultiLine; 926 getOutTexCoord( "texCoord", 927 "float2", 928 fd.features[MFT_TexAnim], 929 meta, 930 componentList ); 931 output = meta; 932} 933 934U32 DiffuseMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const 935{ 936 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; 937} 938 939void DiffuseMapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 940 const MaterialFeatureData &fd ) 941{ 942 // grab connector texcoord register 943 Var *inTex = getInTexCoord( "texCoord", "float2", componentList ); 944 945 //determine output target 946 ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget; 947 if (fd.features[MFT_isDeferred]) 948 targ = ShaderFeature::RenderTarget1; 949 950 // create texture var 951 Var *diffuseMap = new Var; 952 diffuseMap->setType( "SamplerState" ); 953 diffuseMap->setName( "diffuseMap" ); 954 diffuseMap->uniform = true; 955 diffuseMap->sampler = true; 956 diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 957 958 Var* diffuseMapTex = new Var; 959 diffuseMapTex->setName("diffuseMapTex"); 960 diffuseMapTex->setType("Texture2D"); 961 diffuseMapTex->uniform = true; 962 diffuseMapTex->texture = true; 963 diffuseMapTex->constNum = diffuseMap->constNum; 964 965 // create sample color 966 Var *diffColor = new Var; 967 diffColor->setType("float4"); 968 diffColor->setName("diffuseColor"); 969 LangElement *colorDecl = new DecOp(diffColor); 970 971 MultiLine * meta = new MultiLine; 972 output = meta; 973 974 if ( fd.features[MFT_CubeMap] ) 975 { 976 meta->addStatement(new GenOp(" @ = @.Sample(@, @);\r\n", colorDecl, diffuseMapTex, diffuseMap, inTex)); 977 meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ))); 978 } 979 else if(fd.features[MFT_DiffuseMapAtlas]) 980 { 981 // Handle atlased textures 982 // http://www.infinity-universe.com/Infinity/index.php?option=com_content&task=view&id=65&Itemid=47 983 984 Var *atlasedTex = new Var; 985 atlasedTex->setName("atlasedTexCoord"); 986 atlasedTex->setType("float2"); 987 LangElement *atDecl = new DecOp(atlasedTex); 988 989 // Parameters of the texture atlas 990 Var *atParams = new Var; 991 atParams->setType("float4"); 992 atParams->setName("diffuseAtlasParams"); 993 atParams->uniform = true; 994 atParams->constSortPos = cspPotentialPrimitive; 995 996 // Parameters of the texture (tile) this object is using in the atlas 997 Var *tileParams = new Var; 998 tileParams->setType("float4"); 999 tileParams->setName("diffuseAtlasTileParams"); 1000 tileParams->uniform = true; 1001 tileParams->constSortPos = cspPotentialPrimitive; 1002 1003 const bool is_sm3 = (GFX->getPixelShaderVersion() > 2.0f); 1004 if(is_sm3) 1005 { 1006 // Figure out the mip level 1007 meta->addStatement(new GenOp(" float2 _dx = ddx(@ * @.z);\r\n", inTex, atParams)); 1008 meta->addStatement(new GenOp(" float2 _dy = ddy(@ * @.z);\r\n", inTex, atParams)); 1009 meta->addStatement(new GenOp(" float mipLod = 0.5 * log2(max(dot(_dx, _dx), dot(_dy, _dy)));\r\n")); 1010 meta->addStatement(new GenOp(" mipLod = clamp(mipLod, 0.0, @.w);\r\n", atParams)); 1011 1012 // And the size of the mip level 1013 meta->addStatement(new GenOp(" float mipPixSz = pow(2.0, @.w - mipLod);\r\n", atParams)); 1014 meta->addStatement(new GenOp(" float2 mipSz = mipPixSz / @.xy;\r\n", atParams)); 1015 } 1016 else 1017 { 1018 meta->addStatement(new GenOp(" float2 mipSz = float2(1.0, 1.0);\r\n")); 1019 } 1020 1021 // Tiling mode 1022 // TODO: Select wrap or clamp somehow 1023 if( true ) // Wrap 1024 meta->addStatement(new GenOp(" @ = frac(@);\r\n", atDecl, inTex)); 1025 else // Clamp 1026 meta->addStatement(new GenOp(" @ = saturate(@);\r\n", atDecl, inTex)); 1027 1028 // Finally scale/offset, and correct for filtering 1029 meta->addStatement(new GenOp(" @ = @ * ((mipSz * @.xy - 1.0) / mipSz) + 0.5 / mipSz + @.xy * @.xy;\r\n", 1030 atlasedTex, atlasedTex, atParams, atParams, tileParams)); 1031 1032 // Add a newline 1033 meta->addStatement(new GenOp( "\r\n")); 1034 1035 // For the rest of the feature... 1036 inTex = atlasedTex; 1037 1038 // To dump out UV coords... 1039//#define DEBUG_ATLASED_UV_COORDS 1040#ifdef DEBUG_ATLASED_UV_COORDS 1041 if(!fd.features[MFT_DeferredConditioner]) 1042 { 1043 meta->addStatement(new GenOp(" @ = float4(@.xy, mipLod / @.w, 1.0);\r\n", new DecOp(diffColor), inTex, atParams)); 1044 meta->addStatement(new GenOp(" @; return OUT;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) ); 1045 return; 1046 } 1047#endif 1048 meta->addStatement(new GenOp(" @ = @.SampleLevel(@,@,mipLod);\r\n", 1049 new DecOp(diffColor), diffuseMapTex, diffuseMap, inTex)); 1050 1051 meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ) ) ); 1052 } 1053 else 1054 { 1055 meta->addStatement(new GenOp("@ = @.Sample(@, @);\r\n", colorDecl, diffuseMapTex, diffuseMap, inTex)); 1056 1057 meta->addStatement(new GenOp(" @;\r\n", assignColor(diffColor, Material::Mul, NULL, targ))); 1058 } 1059} 1060 1061ShaderFeature::Resources DiffuseMapFeatHLSL::getResources( const MaterialFeatureData &fd ) 1062{ 1063 Resources res; 1064 res.numTex = 1; 1065 res.numTexReg = 1; 1066 1067 return res; 1068} 1069 1070void DiffuseMapFeatHLSL::setTexData( Material::StageData &stageDat, 1071 const MaterialFeatureData &fd, 1072 RenderPassData &passData, 1073 U32 &texIndex ) 1074{ 1075 GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap ); 1076 if ( tex ) 1077 { 1078 passData.mSamplerNames[ texIndex ] = "diffuseMap"; 1079 passData.mTexSlot[ texIndex++ ].texObject = tex; 1080 } 1081} 1082 1083 1084//**************************************************************************** 1085// Overlay Texture 1086//**************************************************************************** 1087 1088void OverlayTexFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 1089 const MaterialFeatureData &fd ) 1090{ 1091 Var *inTex = getVertTexCoord( "texCoord2" ); 1092 AssertFatal( inTex, "OverlayTexFeatHLSL::processVert() - The second UV set was not found!" ); 1093 1094 // grab connector texcoord register 1095 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1096 Var *outTex = connectComp->getElement( RT_TEXCOORD ); 1097 outTex->setName( "outTexCoord2" ); 1098 outTex->setStructName( "OUT" ); 1099 outTex->setType( "float2" ); 1100 1101 if( fd.features[MFT_TexAnim] ) 1102 { 1103 inTex->setType( "float4" ); 1104 1105 // Find or create the texture matrix. 1106 Var *texMat = (Var*)LangElement::find( "texMat" ); 1107 if ( !texMat ) 1108 { 1109 texMat = new Var; 1110 texMat->setType( "float4x4" ); 1111 texMat->setName( "texMat" ); 1112 texMat->uniform = true; 1113 texMat->constSortPos = cspPass; 1114 } 1115 1116 output = new GenOp( " @ = mul(@, @);\r\n", outTex, texMat, inTex ); 1117 return; 1118 } 1119 1120 // setup language elements to output incoming tex coords to output 1121 output = new GenOp( " @ = @;\r\n", outTex, inTex ); 1122} 1123 1124void OverlayTexFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 1125 const MaterialFeatureData &fd ) 1126{ 1127 1128 // grab connector texcoord register 1129 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1130 Var *inTex = connectComp->getElement( RT_TEXCOORD ); 1131 inTex->setName( "texCoord2" ); 1132 inTex->setStructName( "IN" ); 1133 inTex->setType( "float2" ); 1134 1135 // create texture var 1136 Var *diffuseMap = new Var; 1137 diffuseMap->setType( "SamplerState" ); 1138 diffuseMap->setName( "overlayMap" ); 1139 diffuseMap->uniform = true; 1140 diffuseMap->sampler = true; 1141 diffuseMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 1142 1143 Var* diffuseMapTex = new Var; 1144 diffuseMapTex->setName("overlayMapTex"); 1145 diffuseMapTex->setType("Texture2D"); 1146 diffuseMapTex->uniform = true; 1147 diffuseMapTex->texture = true; 1148 diffuseMapTex->constNum = diffuseMap->constNum; 1149 1150 LangElement *statement = new GenOp("@.Sample(@, @)", diffuseMapTex, diffuseMap, inTex); 1151 1152 output = new GenOp( " @;\r\n", assignColor( statement, Material::LerpAlpha ) ); 1153} 1154 1155ShaderFeature::Resources OverlayTexFeatHLSL::getResources( const MaterialFeatureData &fd ) 1156{ 1157 Resources res; 1158 res.numTex = 1; 1159 res.numTexReg = 1; 1160 return res; 1161} 1162 1163void OverlayTexFeatHLSL::setTexData( Material::StageData &stageDat, 1164 const MaterialFeatureData &fd, 1165 RenderPassData &passData, 1166 U32 &texIndex ) 1167{ 1168 GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap ); 1169 if ( tex ) 1170 { 1171 passData.mSamplerNames[texIndex] = "overlayMap"; 1172 passData.mTexSlot[ texIndex++ ].texObject = tex; 1173 } 1174} 1175 1176 1177//**************************************************************************** 1178// Diffuse color 1179//**************************************************************************** 1180 1181U32 DiffuseFeatureHLSL::getOutputTargets(const MaterialFeatureData &fd) const 1182{ 1183 return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget1 : ShaderFeature::DefaultTarget; 1184} 1185 1186void DiffuseFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList, 1187 const MaterialFeatureData &fd ) 1188{ 1189 Var *diffuseMaterialColor = new Var; 1190 diffuseMaterialColor->setType( "float4" ); 1191 diffuseMaterialColor->setName( "diffuseMaterialColor" ); 1192 diffuseMaterialColor->uniform = true; 1193 diffuseMaterialColor->constSortPos = cspPotentialPrimitive; 1194 1195 MultiLine* meta = new MultiLine; 1196 Var *col = (Var*)LangElement::find("col"); 1197 ShaderFeature::OutputTarget targ = ShaderFeature::DefaultTarget; 1198 if (fd.features[MFT_isDeferred]) 1199 { 1200 targ = ShaderFeature::RenderTarget1; 1201 1202 col = (Var*)LangElement::find("col1"); 1203 if (!col) 1204 { 1205 // create color var 1206 col = new Var; 1207 col->setType("fragout"); 1208 col->setName(getOutputTargetVarName(targ)); 1209 col->setStructName("OUT"); 1210 meta->addStatement(new GenOp(" @ = float4(1.0,1.0,1.0,1.0);\r\n", col)); 1211 } 1212 } 1213 1214 Material::BlendOp op; 1215 1216 if (fd.features[MFT_DiffuseMap]) 1217 op = Material::Mul; 1218 else 1219 op = Material::None; 1220 1221 meta->addStatement( new GenOp( " @;\r\n", assignColor( diffuseMaterialColor, op, NULL, targ ) ) ); 1222 output = meta; 1223} 1224 1225 1226//**************************************************************************** 1227// Diffuse vertex color 1228//**************************************************************************** 1229 1230void DiffuseVertColorFeatureHLSL::processVert( Vector< ShaderComponent*>& componentList, 1231 const MaterialFeatureData& fd ) 1232{ 1233 // Create vertex color connector if it doesn't exist. 1234 1235 Var* outColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) ); 1236 if( !outColor ) 1237 { 1238 // Search for vert color. 1239 1240 Var* inColor = dynamic_cast< Var* >( LangElement::find( "diffuse" ) ); 1241 if( !inColor ) 1242 { 1243 output = NULL; 1244 return; 1245 } 1246 1247 // Create connector. 1248 1249 ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] ); 1250 AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); 1251 outColor = connectComp->getElement( RT_COLOR ); 1252 outColor->setName( "vertColor" ); 1253 outColor->setStructName( "OUT" ); 1254 outColor->setType( "float4" ); 1255 1256 output = new GenOp( " @ = @.bgra;\r\n", outColor, inColor ); 1257 } 1258 else 1259 output = NULL; // Nothing we need to do. 1260} 1261 1262void DiffuseVertColorFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList, 1263 const MaterialFeatureData &fd ) 1264{ 1265 Var* vertColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) ); 1266 if( !vertColor ) 1267 { 1268 ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] ); 1269 AssertFatal( connectComp, "DiffuseVertColorFeatureGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); 1270 vertColor = connectComp->getElement( RT_COLOR ); 1271 vertColor->setName( "vertColor" ); 1272 vertColor->setStructName( "IN" ); 1273 vertColor->setType( "float4" ); 1274 } 1275 1276 MultiLine* meta = new MultiLine; 1277 if (fd.features[MFT_isDeferred]) 1278 meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1))); 1279 else 1280 meta->addStatement(new GenOp(" @;\r\n", assignColor(vertColor, Material::Mul))); 1281 output = meta; 1282} 1283 1284 1285//**************************************************************************** 1286// Lightmap 1287//**************************************************************************** 1288 1289void LightmapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 1290 const MaterialFeatureData &fd ) 1291{ 1292 // grab tex register from incoming vert 1293 Var *inTex = getVertTexCoord( "texCoord2" ); 1294 1295 // grab connector texcoord register 1296 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1297 Var *outTex = connectComp->getElement( RT_TEXCOORD ); 1298 outTex->setName( "texCoord2" ); 1299 outTex->setStructName( "OUT" ); 1300 outTex->setType( "float2" ); 1301 1302 // setup language elements to output incoming tex coords to output 1303 output = new GenOp( " @ = @;\r\n", outTex, inTex ); 1304} 1305 1306void LightmapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 1307 const MaterialFeatureData &fd ) 1308{ 1309 // grab connector texcoord register 1310 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1311 Var *inTex = connectComp->getElement( RT_TEXCOORD ); 1312 inTex->setName( "texCoord2" ); 1313 inTex->setStructName( "IN" ); 1314 inTex->setType( "float2" ); 1315 1316 // create texture var 1317 Var *lightMap = new Var; 1318 lightMap->setType( "SamplerState" ); 1319 lightMap->setName( "lightMap" ); 1320 lightMap->uniform = true; 1321 lightMap->sampler = true; 1322 lightMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 1323 1324 Var *lightMapTex = new Var; 1325 lightMapTex->setName("lightMapTex"); 1326 lightMapTex->setType("Texture2D"); 1327 lightMapTex->uniform = true; 1328 lightMapTex->texture = true; 1329 lightMapTex->constNum = lightMap->constNum; 1330 1331 // argh, ORMConfigMap should prob use this too 1332 if( fd.features[MFT_NormalMap] ) 1333 { 1334 Var *lmColor = new Var; 1335 lmColor->setName( "lmColor" ); 1336 lmColor->setType( "float4" ); 1337 LangElement *lmColorDecl = new DecOp( lmColor ); 1338 1339 output = new GenOp(" @ = @.Sample(@, @);\r\n", lmColorDecl, lightMapTex, lightMap, inTex); 1340 1341 return; 1342 } 1343 1344 // Add realtime lighting, if it is available 1345 LangElement *statement = NULL; 1346 if( fd.features[MFT_RTLighting] ) 1347 { 1348 // Advanced lighting is the only dynamic lighting supported right now 1349 Var *inColor = (Var*) LangElement::find( "d_lightcolor" ); 1350 if(inColor != NULL) 1351 { 1352 // Find out if RTLighting should be added or substituted 1353 bool bPreProcessedLighting = false; 1354 AdvancedLightBinManager *lightBin; 1355 if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) 1356 bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred(); 1357 1358 // Lightmap has already been included in the advanced light bin, so 1359 // no need to do any sampling or anything 1360 if (bPreProcessedLighting) 1361 statement = new GenOp("float4(@, 1.0)", inColor); 1362 else 1363 { 1364 statement = new GenOp("@.Sample(@, @) + float4(@.rgb, 0.0)", lightMapTex, lightMap, inTex, inColor); 1365 } 1366 } 1367 } 1368 1369 // If we still don't have it... then just sample the lightmap. 1370 if (!statement) 1371 { 1372 statement = new GenOp("@.Sample(@, @)", lightMapTex, lightMap, inTex); 1373 } 1374 1375 // Assign to proper render target 1376 MultiLine *meta = new MultiLine; 1377 if( fd.features[MFT_LightbufferMRT] ) 1378 { 1379 meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); 1380 meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); 1381 } 1382 else 1383 meta->addStatement( new GenOp( " @;\r\n", assignColor( statement, Material::Mul ) ) ); 1384 1385 output = meta; 1386} 1387 1388ShaderFeature::Resources LightmapFeatHLSL::getResources( const MaterialFeatureData &fd ) 1389{ 1390 Resources res; 1391 res.numTex = 1; 1392 res.numTexReg = 1; 1393 1394 return res; 1395} 1396 1397void LightmapFeatHLSL::setTexData( Material::StageData &stageDat, 1398 const MaterialFeatureData &fd, 1399 RenderPassData &passData, 1400 U32 &texIndex ) 1401{ 1402 GFXTextureObject *tex = stageDat.getTex( MFT_LightMap ); 1403 passData.mSamplerNames[ texIndex ] = "lightMap"; 1404 if ( tex ) 1405 passData.mTexSlot[ texIndex++ ].texObject = tex; 1406 else 1407 passData.mTexType[ texIndex++ ] = Material::Lightmap; 1408} 1409 1410U32 LightmapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const 1411{ 1412 return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; 1413} 1414 1415//**************************************************************************** 1416// Tonemap 1417//**************************************************************************** 1418 1419void TonemapFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 1420 const MaterialFeatureData &fd ) 1421{ 1422 // Grab the connector 1423 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1424 1425 // Set up the second set of texCoords 1426 Var *inTex2 = getVertTexCoord( "texCoord2" ); 1427 1428 if ( inTex2 ) 1429 { 1430 Var *outTex2 = connectComp->getElement( RT_TEXCOORD ); 1431 outTex2->setName( "texCoord2" ); 1432 outTex2->setStructName( "OUT" ); 1433 outTex2->setType( "float2" ); 1434 1435 output = new GenOp( " @ = @;\r\n", outTex2, inTex2 ); 1436 } 1437} 1438 1439void TonemapFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 1440 const MaterialFeatureData &fd ) 1441{ 1442 // Grab connector 1443 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1444 1445 Var *inTex2 = connectComp->getElement( RT_TEXCOORD ); 1446 inTex2->setName( "texCoord2" ); 1447 inTex2->setStructName( "IN" ); 1448 inTex2->setType( "float2" ); 1449 1450 // create texture var 1451 Var *toneMap = new Var; 1452 toneMap->setType( "SamplerState" ); 1453 toneMap->setName( "toneMap" ); 1454 toneMap->uniform = true; 1455 toneMap->sampler = true; 1456 toneMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 1457 1458 Var *toneMapTex = new Var; 1459 toneMapTex->setName("toneMapTex"); 1460 toneMapTex->setType("Texture2D"); 1461 toneMapTex->uniform = true; 1462 toneMapTex->texture = true; 1463 toneMapTex->constNum = toneMap->constNum; 1464 1465 MultiLine * meta = new MultiLine; 1466 1467 // First get the toneMap color 1468 Var *toneMapColor = new Var; 1469 toneMapColor->setType( "float4" ); 1470 toneMapColor->setName( "toneMapColor" ); 1471 LangElement *toneMapColorDecl = new DecOp( toneMapColor ); 1472 1473 meta->addStatement(new GenOp(" @ = @.Sample(@, @);\r\n", toneMapColorDecl, toneMapTex, toneMap, inTex2)); 1474 1475 // We do a different calculation if there is a diffuse map or not 1476 Material::BlendOp blendOp = Material::Mul; 1477 if ( fd.features[MFT_DiffuseMap] ) 1478 { 1479 // Reverse the tonemap 1480 meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", toneMapColor, toneMapColor ) ); 1481 1482 // Re-tonemap with the current color factored in 1483 blendOp = Material::ToneMap; 1484 } 1485 1486 // Find out if RTLighting should be added 1487 bool bPreProcessedLighting = false; 1488 AdvancedLightBinManager *lightBin; 1489 if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) 1490 bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred(); 1491 1492 // Add in the realtime lighting contribution 1493 if ( fd.features[MFT_RTLighting] ) 1494 { 1495 // Right now, only Advanced Lighting is supported 1496 Var *inColor = (Var*) LangElement::find( "d_lightcolor" ); 1497 if(inColor != NULL) 1498 { 1499 // Assign value in d_lightcolor to toneMapColor if it exists. This is 1500 // the dynamic light buffer, and it already has the tonemap included 1501 if(bPreProcessedLighting) 1502 meta->addStatement( new GenOp( " @.rgb = @;\r\n", toneMapColor, inColor ) ); 1503 else 1504 meta->addStatement( new GenOp( " @.rgb += @.rgb;\r\n", toneMapColor, inColor ) ); 1505 } 1506 } 1507 1508 // Assign to proper render target 1509 if( fd.features[MFT_LightbufferMRT] ) 1510 { 1511 meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); 1512 meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); 1513 } 1514 else 1515 meta->addStatement( new GenOp( " @;\r\n", assignColor( toneMapColor, blendOp ) ) ); 1516 1517 output = meta; 1518} 1519 1520ShaderFeature::Resources TonemapFeatHLSL::getResources( const MaterialFeatureData &fd ) 1521{ 1522 Resources res; 1523 res.numTex = 1; 1524 res.numTexReg = 1; 1525 1526 return res; 1527} 1528 1529void TonemapFeatHLSL::setTexData( Material::StageData &stageDat, 1530 const MaterialFeatureData &fd, 1531 RenderPassData &passData, 1532 U32 &texIndex ) 1533{ 1534 GFXTextureObject *tex = stageDat.getTex( MFT_ToneMap ); 1535 if ( tex ) 1536 { 1537 passData.mTexType[ texIndex ] = Material::ToneMapTex; 1538 passData.mSamplerNames[ texIndex ] = "toneMap"; 1539 passData.mTexSlot[ texIndex++ ].texObject = tex; 1540 } 1541} 1542 1543U32 TonemapFeatHLSL::getOutputTargets( const MaterialFeatureData &fd ) const 1544{ 1545 return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; 1546} 1547 1548//**************************************************************************** 1549// pureLIGHT Lighting 1550//**************************************************************************** 1551 1552void VertLitHLSL::processVert( Vector<ShaderComponent*> &componentList, 1553 const MaterialFeatureData &fd ) 1554{ 1555 // If we have a lightMap or toneMap then our lighting will be 1556 // handled by the MFT_LightMap or MFT_ToneNamp feature instead 1557 if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] ) 1558 { 1559 output = NULL; 1560 return; 1561 } 1562 1563 // Create vertex color connector if it doesn't exist. 1564 1565 Var* outColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) ); 1566 if( !outColor ) 1567 { 1568 // Search for vert color 1569 Var *inColor = (Var*) LangElement::find( "diffuse" ); 1570 1571 // If there isn't a vertex color then we can't do anything 1572 if( !inColor ) 1573 { 1574 output = NULL; 1575 return; 1576 } 1577 1578 // Grab the connector color 1579 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1580 outColor = connectComp->getElement( RT_COLOR ); 1581 outColor->setName( "vertColor" ); 1582 outColor->setStructName( "OUT" ); 1583 outColor->setType( "float4" ); 1584 1585 output = new GenOp( " @ = @;\r\n", outColor, inColor ); 1586 } 1587 else 1588 output = NULL; // Nothing we need to do. 1589} 1590 1591void VertLitHLSL::processPix( Vector<ShaderComponent*> &componentList, 1592 const MaterialFeatureData &fd ) 1593{ 1594 // If we have a lightMap or toneMap then our lighting will be 1595 // handled by the MFT_LightMap or MFT_ToneNamp feature instead 1596 if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] ) 1597 { 1598 output = NULL; 1599 return; 1600 } 1601 1602 // Grab the connector color register 1603 Var* vertColor = dynamic_cast< Var* >( LangElement::find( "vertColor" ) ); 1604 if( !vertColor ) 1605 { 1606 ShaderConnector* connectComp = dynamic_cast< ShaderConnector* >( componentList[ C_CONNECTOR ] ); 1607 AssertFatal( connectComp, "VertLitGLSL::processVert - C_CONNECTOR is not a ShaderConnector" ); 1608 vertColor = connectComp->getElement( RT_COLOR ); 1609 vertColor->setName( "vertColor" ); 1610 vertColor->setStructName( "IN" ); 1611 vertColor->setType( "float4" ); 1612 } 1613 1614 MultiLine * meta = new MultiLine; 1615 1616 // Defaults (no diffuse map) 1617 Material::BlendOp blendOp = Material::Mul; 1618 LangElement *outColor = vertColor; 1619 1620 // We do a different calculation if there is a diffuse map or not 1621 if ( fd.features[MFT_DiffuseMap] || fd.features[MFT_VertLitTone] ) 1622 { 1623 Var * finalVertColor = new Var; 1624 finalVertColor->setName( "finalVertColor" ); 1625 finalVertColor->setType( "float4" ); 1626 LangElement *finalVertColorDecl = new DecOp( finalVertColor ); 1627 1628 // Reverse the tonemap 1629 meta->addStatement( new GenOp( " @ = -1.0f * log(1.0f - @);\r\n", finalVertColorDecl, vertColor ) ); 1630 1631 // Set the blend op to tonemap 1632 blendOp = Material::ToneMap; 1633 outColor = finalVertColor; 1634 } 1635 1636 // Add in the realtime lighting contribution, if applicable 1637 if ( fd.features[MFT_RTLighting] ) 1638 { 1639 Var *rtLightingColor = (Var*) LangElement::find( "d_lightcolor" ); 1640 if(rtLightingColor != NULL) 1641 { 1642 bool bPreProcessedLighting = false; 1643 AdvancedLightBinManager *lightBin; 1644 if ( Sim::findObject( "AL_LightBinMgr", lightBin ) ) 1645 bPreProcessedLighting = lightBin->MRTLightmapsDuringDeferred(); 1646 1647 // Assign value in d_lightcolor to toneMapColor if it exists. This is 1648 // the dynamic light buffer, and it already has the baked-vertex-color 1649 // included in it 1650 if(bPreProcessedLighting) 1651 outColor = new GenOp( "float4(@.rgb, 1.0)", rtLightingColor ); 1652 else 1653 outColor = new GenOp( "float4(@.rgb + @.rgb, 1.0)", rtLightingColor, outColor ); 1654 } 1655 } 1656 1657 // Output the color 1658 if ( fd.features[MFT_LightbufferMRT] ) 1659 { 1660 meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, Material::None, NULL, ShaderFeature::RenderTarget3 ) ) ); 1661 meta->addStatement( new GenOp( " @.a = 0.0001;\r\n", LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget3) ) ) ); 1662 } 1663 else 1664 meta->addStatement( new GenOp( " @;\r\n", assignColor( outColor, blendOp ) ) ); 1665 1666 output = meta; 1667} 1668 1669U32 VertLitHLSL::getOutputTargets( const MaterialFeatureData &fd ) const 1670{ 1671 return fd.features[MFT_LightbufferMRT] ? ShaderFeature::RenderTarget3 : ShaderFeature::DefaultTarget; 1672} 1673 1674//**************************************************************************** 1675// Detail map 1676//**************************************************************************** 1677 1678void DetailFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 1679 const MaterialFeatureData &fd ) 1680{ 1681 MultiLine *meta = new MultiLine; 1682 addOutDetailTexCoord( componentList, 1683 meta, 1684 fd.features[MFT_TexAnim], fd.features[MFT_Foliage] ); 1685 output = meta; 1686} 1687 1688void DetailFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 1689 const MaterialFeatureData &fd ) 1690{ 1691 // Get the detail texture coord. 1692 Var *inTex = getInTexCoord( "detCoord", "float2", componentList ); 1693 1694 // create texture var 1695 Var *detailMap = new Var; 1696 detailMap->setType( "SamplerState" ); 1697 detailMap->setName( "detailMap" ); 1698 detailMap->uniform = true; 1699 detailMap->sampler = true; 1700 detailMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 1701 1702 Var* detailMapTex = new Var; 1703 detailMapTex->setName("detailMapTex"); 1704 detailMapTex->setType("Texture2D"); 1705 detailMapTex->uniform = true; 1706 detailMapTex->texture = true; 1707 detailMapTex->constNum = detailMap->constNum; 1708 1709 // We're doing the standard greyscale detail map 1710 // technique which can darken and lighten the 1711 // diffuse texture. 1712 1713 // TODO: We could add a feature to toggle between this 1714 // and a simple multiplication with the detail map. 1715 1716 LangElement *statement = new GenOp("( @.Sample(@, @) * 2.0 ) - 1.0", detailMapTex, detailMap, inTex); 1717 1718 if ( fd.features[MFT_isDeferred]) 1719 output = new GenOp( " @;\r\n", assignColor( statement, Material::Add, NULL, ShaderFeature::RenderTarget1 ) ); 1720 else 1721 output = new GenOp( " @;\r\n", assignColor( statement, Material::Add ) ); 1722} 1723 1724ShaderFeature::Resources DetailFeatHLSL::getResources( const MaterialFeatureData &fd ) 1725{ 1726 Resources res; 1727 res.numTex = 1; 1728 res.numTexReg = 1; 1729 1730 return res; 1731} 1732 1733void DetailFeatHLSL::setTexData( Material::StageData &stageDat, 1734 const MaterialFeatureData &fd, 1735 RenderPassData &passData, 1736 U32 &texIndex ) 1737{ 1738 GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); 1739 if ( tex ) 1740 { 1741 passData.mSamplerNames[texIndex] = "detailMap"; 1742 passData.mTexSlot[ texIndex++ ].texObject = tex; 1743 } 1744} 1745 1746 1747//**************************************************************************** 1748// Vertex position 1749//**************************************************************************** 1750 1751void VertPositionHLSL::determineFeature( Material *material, 1752 const GFXVertexFormat *vertexFormat, 1753 U32 stageNum, 1754 const FeatureType &type, 1755 const FeatureSet &features, 1756 MaterialFeatureData *outFeatureData ) 1757{ 1758 // This feature is always on! 1759 outFeatureData->features.addFeature( type ); 1760} 1761 1762void VertPositionHLSL::processVert( Vector<ShaderComponent*> &componentList, 1763 const MaterialFeatureData &fd ) 1764{ 1765 // First check for an input position from a previous feature 1766 // then look for the default vertex position. 1767 Var *inPosition = (Var*)LangElement::find( "inPosition" ); 1768 if ( !inPosition ) 1769 inPosition = (Var*)LangElement::find( "position" ); 1770 1771 // grab connector position 1772 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1773 Var *outPosition = connectComp->getElement(RT_SVPOSITION); 1774 1775 outPosition->setName( "hpos" ); 1776 outPosition->setStructName( "OUT" ); 1777 1778 MultiLine *meta = new MultiLine; 1779 1780 Var *modelview = getModelView( componentList, fd.features[MFT_UseInstancing], meta ); 1781 1782 meta->addStatement( new GenOp( " @ = mul(@, float4(@.xyz,1));\r\n", 1783 outPosition, modelview, inPosition ) ); 1784 1785 if (fd.materialFeatures[MFT_isBackground]) 1786 { 1787 meta->addStatement(new GenOp(" @ = @.xyww;\r\n", outPosition, outPosition)); 1788 } 1789 1790 output = meta; 1791} 1792 1793void VertPositionHLSL::processPix( Vector<ShaderComponent*> &componentList, 1794 const MaterialFeatureData &fd) 1795{ 1796 // grab connector position 1797 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]); 1798 Var *outPosition = connectComp->getElement(RT_SVPOSITION); 1799 outPosition->setName("vpos"); 1800 outPosition->setStructName("IN"); 1801} 1802 1803 1804//**************************************************************************** 1805// Reflect Cubemap 1806//**************************************************************************** 1807 1808void ReflectCubeFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 1809 const MaterialFeatureData &fd ) 1810{ 1811 // search for vert normal 1812 Var *inNormal = (Var*) LangElement::find( "normal" ); 1813 if ( !inNormal ) 1814 return; 1815 1816 MultiLine * meta = new MultiLine; 1817 1818 // If a base or bump tex is present in the material, but not in the 1819 // current pass - we need to add one to the current pass to use 1820 // its alpha channel as a gloss map. Here we just need the tex coords. 1821 if( !fd.features[MFT_DiffuseMap] && 1822 !fd.features[MFT_NormalMap] ) 1823 { 1824 if( fd.materialFeatures[MFT_DiffuseMap] || 1825 fd.materialFeatures[MFT_NormalMap] ) 1826 { 1827 // find incoming texture var 1828 Var *inTex = getVertTexCoord( "texCoord" ); 1829 1830 // grab connector texcoord register 1831 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1832 Var *outTex = connectComp->getElement( RT_TEXCOORD ); 1833 outTex->setName( "texCoord" ); 1834 outTex->setStructName( "OUT" ); 1835 outTex->setType( "float2" ); 1836 1837 // setup language elements to output incoming tex coords to output 1838 meta->addStatement( new GenOp( " @ = @;\r\n", outTex, inTex ) ); 1839 } 1840 } 1841 1842 // create cubeTrans 1843 bool useInstancing = fd.features[MFT_UseInstancing]; 1844 Var *cubeTrans = getObjTrans( componentList, useInstancing, meta ); 1845 1846 // cube vert position 1847 Var * cubeVertPos = new Var; 1848 cubeVertPos->setName( "cubeVertPos" ); 1849 cubeVertPos->setType( "float3" ); 1850 LangElement *cubeVertPosDecl = new DecOp( cubeVertPos ); 1851 1852 meta->addStatement( new GenOp( " @ = mul(@, float4(@,1)).xyz;\r\n", 1853 cubeVertPosDecl, cubeTrans, LangElement::find( "position" ) ) ); 1854 1855 // cube normal 1856 Var * cubeNormal = new Var; 1857 cubeNormal->setName( "cubeNormal" ); 1858 cubeNormal->setType( "float3" ); 1859 LangElement *cubeNormDecl = new DecOp( cubeNormal ); 1860 1861 meta->addStatement(new GenOp(" @ = ( mul( (@), float4(@, 0) ) ).xyz;\r\n", 1862 cubeNormDecl, cubeTrans, inNormal)); 1863 1864 meta->addStatement(new GenOp(" @ = bool(length(@)) ? normalize(@) : @;\r\n", 1865 cubeNormal, cubeNormal, cubeNormal, cubeNormal)); 1866 1867 // grab the eye position 1868 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 1869 if ( !eyePos ) 1870 { 1871 eyePos = new Var( "eyePosWorld", "float3" ); 1872 eyePos->uniform = true; 1873 eyePos->constSortPos = cspPass; 1874 } 1875 1876 // eye to vert 1877 Var * eyeToVert = new Var; 1878 eyeToVert->setName( "eyeToVert" ); 1879 eyeToVert->setType( "float3" ); 1880 LangElement *e2vDecl = new DecOp( eyeToVert ); 1881 1882 meta->addStatement( new GenOp( " @ = @ - @;\r\n", 1883 e2vDecl, cubeVertPos, eyePos ) ); 1884 1885 // grab connector texcoord register 1886 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1887 Var *reflectVec = connectComp->getElement( RT_TEXCOORD ); 1888 reflectVec->setName( "reflectVec" ); 1889 reflectVec->setStructName( "OUT" ); 1890 reflectVec->setType( "float3" ); 1891 1892 meta->addStatement( new GenOp( " @ = reflect(@, @);\r\n", reflectVec, eyeToVert, cubeNormal ) ); 1893 1894 output = meta; 1895} 1896 1897void ReflectCubeFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 1898 const MaterialFeatureData &fd ) 1899{ 1900 MultiLine * meta = new MultiLine; 1901 Var *glossColor = NULL; 1902 1903 // If a base or bump tex is present in the material, but not in the 1904 // current pass - we need to add one to the current pass to use 1905 // its alpha channel as a gloss map. 1906 if( !fd.features[MFT_DiffuseMap] && 1907 !fd.features[MFT_NormalMap]) 1908 { 1909 if( fd.materialFeatures[MFT_DiffuseMap] || 1910 fd.materialFeatures[MFT_NormalMap]) 1911 { 1912 // grab connector texcoord register 1913 Var *inTex = getInTexCoord("texCoord", "float2", componentList); 1914 1915 // create texture var 1916 Var *newMap = new Var; 1917 newMap->setType( "SamplerState" ); 1918 newMap->setName( "glossMap" ); 1919 newMap->uniform = true; 1920 newMap->sampler = true; 1921 newMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 1922 1923 Var* glowMapTex = new Var; 1924 glowMapTex->setName("glowMapTex"); 1925 glowMapTex->setType("Texture2D"); 1926 glowMapTex->uniform = true; 1927 glowMapTex->texture = true; 1928 glowMapTex->constNum = newMap->constNum; 1929 1930 // create sample color 1931 Var *color = new Var; 1932 color->setType( "float4" ); 1933 color->setName( "diffuseColor" ); 1934 LangElement *colorDecl = new DecOp( color ); 1935 1936 glossColor = color; 1937 1938 meta->addStatement(new GenOp(" @ = @.Sample( @, @ );\r\n", colorDecl, glowMapTex, newMap, inTex)); 1939 } 1940 } 1941 if (!glossColor) 1942 { 1943 if (fd.features[MFT_isDeferred]) 1944 glossColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget1)); 1945 if (!glossColor) 1946 glossColor = (Var*)LangElement::find("diffuseColor"); 1947 if (!glossColor) 1948 glossColor = (Var*)LangElement::find("bumpNormal"); 1949 } 1950 1951 // grab connector texcoord register 1952 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 1953 Var *reflectVec = connectComp->getElement( RT_TEXCOORD ); 1954 reflectVec->setName( "reflectVec" ); 1955 reflectVec->setStructName( "IN" ); 1956 reflectVec->setType( "float3" ); 1957 1958 // create cubemap var 1959 Var *cubeMap = new Var; 1960 cubeMap->setType( "SamplerState" ); 1961 cubeMap->setName( "cubeMap" ); 1962 cubeMap->uniform = true; 1963 cubeMap->sampler = true; 1964 cubeMap->constNum = Var::getTexUnitNum(); // used as texture unit num here 1965 1966 Var* cubeMapTex = new Var; 1967 cubeMapTex->setName("cubeMapTex"); 1968 cubeMapTex->setType("TextureCube"); // cubeMapTex->setType("TextureCube"); 1969 cubeMapTex->uniform = true; 1970 cubeMapTex->texture = true; 1971 cubeMapTex->constNum = cubeMap->constNum; 1972 1973 Var *cubeMips = new Var; 1974 cubeMips->setType("float"); 1975 cubeMips->setName("cubeMips"); 1976 cubeMips->uniform = true; 1977 cubeMips->constSortPos = cspPotentialPrimitive; 1978 1979 // TODO: Restore the lighting attenuation here! 1980 Var *attn = NULL; 1981 //if ( fd.materialFeatures[MFT_DynamicLight] ) 1982 //attn = (Var*)LangElement::find("attn"); 1983 //else 1984 if ( fd.materialFeatures[MFT_RTLighting] ) 1985 attn =(Var*)LangElement::find("d_NL_Att"); 1986 1987 LangElement *texCube = NULL; 1988 Var* matinfo = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) ); 1989 Var *roughness = (Var*)LangElement::find("roughness"); 1990 1991 if (roughness) //try to grab roughness directly 1992 { 1993 texCube = new GenOp("@.SampleLevel( @, float3(@).rgb, min((1.0 - @)*@ + 1.0, @))", cubeMapTex, cubeMap, reflectVec, roughness, cubeMips, cubeMips); 1994 } 1995 else if (glossColor)//failing that, try and find color data 1996 { 1997 texCube = new GenOp("@.SampleLevel( @, float3(@).rgb, min((1.0 - @.b)*@ + 1.0, @))", cubeMapTex, cubeMap, reflectVec, glossColor, cubeMips, cubeMips); 1998 } 1999 else //failing *that*, just draw the cubemap 2000 { 2001 texCube = new GenOp("@.Sample( @, @ )", cubeMapTex, cubeMap, reflectVec); 2002 } 2003 2004 LangElement *lerpVal = NULL; 2005 Material::BlendOp blendOp = Material::LerpAlpha; 2006 2007 // Note that the lerpVal needs to be a float4 so that 2008 // it will work with the LerpAlpha blend. 2009 2010 if (matinfo) 2011 { 2012 if (attn) 2013 lerpVal = new GenOp("@ * saturate( @ )", matinfo, attn); 2014 else 2015 lerpVal = new GenOp("@", matinfo); 2016 } 2017 else if ( glossColor ) 2018 { 2019 if ( attn ) 2020 lerpVal = new GenOp( "@ * saturate( @ )", glossColor, attn ); 2021 else 2022 lerpVal = glossColor; 2023 } 2024 else 2025 { 2026 if ( attn ) 2027 lerpVal = new GenOp( "saturate( @ ).xxxx", attn ); 2028 else 2029 blendOp = Material::Mul; 2030 } 2031 2032 Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget3)); 2033 if (fd.features[MFT_isDeferred]) 2034 { 2035 //metalness: black(0) = color, white(1) = reflection 2036 if (fd.features[MFT_ToneMap]) 2037 meta->addStatement(new GenOp(" @ *= @;\r\n", targ, texCube)); 2038 else 2039 meta->addStatement(new GenOp(" @ = @;\r\n", targ, texCube)); 2040 } 2041 else 2042 { 2043 meta->addStatement(new GenOp(" //forward lit cubemapping\r\n")); 2044 targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); 2045 2046 Var *metalness = (Var*)LangElement::find("metalness"); 2047 if (metalness) 2048 { 2049 Var *dColor = new Var("dColor", "float3"); 2050 Var *reflectColor = new Var("reflectColor", "float3"); 2051 meta->addStatement(new GenOp(" @ = @.rgb - (@.rgb * @);\r\n", new DecOp(dColor), targ, targ, metalness)); 2052 meta->addStatement(new GenOp(" @ = @.rgb*(@).rgb*@;\r\n", new DecOp(reflectColor), targ, texCube, metalness)); 2053 meta->addStatement(new GenOp(" @.rgb = @+@;\r\n", targ, dColor, reflectColor)); 2054 } 2055 else if (lerpVal) 2056 meta->addStatement(new GenOp(" @ *= float4(@.rgb*@.a, @.a);\r\n", targ, texCube, lerpVal, targ)); 2057 else 2058 meta->addStatement(new GenOp(" @.rgb *= @.rgb;\r\n", targ, texCube)); 2059 } 2060 output = meta; 2061} 2062 2063ShaderFeature::Resources ReflectCubeFeatHLSL::getResources( const MaterialFeatureData &fd ) 2064{ 2065 Resources res; 2066 2067 if( fd.features[MFT_DiffuseMap] || 2068 fd.features[MFT_NormalMap] ) 2069 { 2070 res.numTex = 1; 2071 res.numTexReg = 1; 2072 } 2073 else 2074 { 2075 res.numTex = 2; 2076 res.numTexReg = 2; 2077 } 2078 2079 return res; 2080} 2081 2082void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat, 2083 const MaterialFeatureData &stageFeatures, 2084 RenderPassData &passData, 2085 U32 &texIndex ) 2086{ 2087 // set up a gloss map if one is not present in the current pass 2088 // but is present in the current material stage 2089 if( !passData.mFeatureData.features[MFT_DiffuseMap] && 2090 !passData.mFeatureData.features[MFT_NormalMap] ) 2091 { 2092 GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); 2093 if ( tex && stageFeatures.features[MFT_DiffuseMap] ) 2094 { 2095 passData.mSamplerNames[ texIndex ] = "diffuseMap"; 2096 passData.mTexSlot[ texIndex++ ].texObject = tex; 2097 } 2098 else 2099 { 2100 tex = stageDat.getTex( MFT_NormalMap ); 2101 2102 if ( tex && stageFeatures.features[ MFT_NormalMap ] ) 2103 { 2104 passData.mSamplerNames[ texIndex ] = "bumpMap"; 2105 passData.mTexSlot[ texIndex++ ].texObject = tex; 2106 } 2107 } 2108 } 2109 2110 if( stageDat.getCubemap() ) 2111 { 2112 passData.mCubeMap = stageDat.getCubemap(); 2113 passData.mSamplerNames[texIndex] = "cubeMap"; 2114 passData.mTexType[texIndex++] = Material::Cube; 2115 } 2116 else 2117 { 2118 if( stageFeatures.features[MFT_CubeMap] ) 2119 { 2120 // assuming here that it is a scenegraph cubemap 2121 passData.mSamplerNames[texIndex] = "cubeMap"; 2122 passData.mTexType[texIndex++] = Material::SGCube; 2123 } 2124 } 2125 2126} 2127 2128 2129//**************************************************************************** 2130// RTLighting 2131//**************************************************************************** 2132 2133RTLightingFeatHLSL::RTLightingFeatHLSL() 2134 : mDep(ShaderGen::smCommonShaderPath + String("/lighting.hlsl" )) 2135{ 2136 addDependency( &mDep ); 2137} 2138 2139void RTLightingFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 2140 const MaterialFeatureData &fd ) 2141{ 2142 MultiLine *meta = new MultiLine; 2143 2144 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2145 getOutWorldToTangent(componentList, meta, fd); 2146 2147 // Special case for lighting imposters. We dont have a vert normal and may not 2148 // have a normal map. Generate and pass the normal data the pixel shader needs. 2149 if ( fd.features[MFT_ImposterVert] ) 2150 { 2151 2152 if ( !fd.features[MFT_NormalMap] ) 2153 { 2154 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 2155 if ( !eyePos ) 2156 { 2157 eyePos = new Var( "eyePosWorld", "float3" ); 2158 eyePos->uniform = true; 2159 eyePos->constSortPos = cspPass; 2160 } 2161 2162 //Temporarily disabled while we figure out how to better handle normals without a normal map 2163 /*Var *inPosition = (Var*)LangElement::find( "position" ); 2164 2165 Var *outNormal = connectComp->getElement( RT_TEXCOORD ); 2166 outNormal->setName( "wsNormal" ); 2167 outNormal->setStructName( "OUT" ); 2168 outNormal->setType( "float3" ); 2169 2170 // Transform the normal to world space. 2171 meta->addStatement( new GenOp( " @ = normalize( @ - @.xyz );\r\n", outNormal, eyePos, inPosition ) );*/ 2172 } 2173 2174 addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); 2175 2176 output = meta; 2177 2178 return; 2179 } 2180 2181 // Find the incoming vertex normal. 2182 Var *inNormal = (Var*)LangElement::find( "normal" ); 2183 2184 // Skip out on realtime lighting if we don't have a normal 2185 // or we're doing some sort of baked lighting. 2186 if ( !inNormal || 2187 fd.features[MFT_LightMap] || 2188 fd.features[MFT_ToneMap] || 2189 fd.features[MFT_VertLit] ) 2190 return; 2191 2192 // If there isn't a normal map then we need to pass 2193 // the world space normal to the pixel shader ourselves. 2194 //Temporarily disabled while we figure out how to better handle normals without a normal map 2195 if ( !fd.features[MFT_NormalMap] ) 2196 { 2197 Var *outNormal = connectComp->getElement( RT_TEXCOORD ); 2198 outNormal->setName( "wsNormal" ); 2199 outNormal->setStructName( "OUT" ); 2200 outNormal->setType( "float3" ); 2201 2202 // Get the transform to world space. 2203 Var *objTrans = getObjTrans( componentList, fd.features[MFT_UseInstancing], meta ); 2204 2205 // Transform the normal to world space. 2206 meta->addStatement( new GenOp( " @ = mul( @, float4( normalize( @ ), 0.0 ) ).xyz;\r\n", outNormal, objTrans, inNormal ) ); 2207 } 2208 2209 addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); 2210 2211 output = meta; 2212} 2213 2214void RTLightingFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 2215 const MaterialFeatureData &fd ) 2216{ 2217 // Skip out on realtime lighting if we don't have a normal 2218 // or we're doing some sort of baked lighting. 2219 // 2220 // TODO: We can totally detect for this in the material 2221 // feature setup... we should move it out of here! 2222 // 2223 if ( fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit] ) 2224 return; 2225 2226 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2227 2228 MultiLine *meta = new MultiLine; 2229 2230 // Now the wsPosition and wsView. 2231 Var* worldToTangent = getInWorldToTangent(componentList); 2232 Var* wsNormal = getInWorldNormal(componentList); 2233 Var *wsPosition = getInWsPosition( componentList ); 2234 2235 Var *wsView = getWsView( wsPosition, meta ); 2236 2237 // Look for a light mask generated from a previous 2238 // feature (this is done for BL terrain lightmaps). 2239 LangElement *lightMask = LangElement::find( "lightMask" ); 2240 if ( !lightMask ) 2241 lightMask = new GenOp( "float4( 1, 1, 1, 1 )" ); 2242 2243 // Get all the light constants. 2244 Var *inLightPos = new Var( "inLightPos", "float4" ); 2245 inLightPos->uniform = true; 2246 inLightPos->arraySize = 4; 2247 inLightPos->constSortPos = cspPotentialPrimitive; 2248 2249 Var * inLightConfigData = new Var( "inLightConfigData", "float4" ); 2250 inLightConfigData->uniform = true; 2251 inLightConfigData->arraySize = 4; 2252 inLightConfigData->constSortPos = cspPotentialPrimitive; 2253 2254 Var *inLightColor = new Var( "inLightColor", "float4" ); 2255 inLightColor->uniform = true; 2256 inLightColor->arraySize = 4; 2257 inLightColor->constSortPos = cspPotentialPrimitive; 2258 2259 Var *inLightSpotDir = new Var( "inLightSpotDir", "float4" ); 2260 inLightSpotDir->uniform = true; 2261 inLightSpotDir->arraySize = 4; 2262 inLightSpotDir->constSortPos = cspPotentialPrimitive; 2263 2264 Var * lightSpotParams = new Var( "lightSpotParams", "float2" ); 2265 lightSpotParams->uniform = true; 2266 lightSpotParams->arraySize = 4; 2267 lightSpotParams->constSortPos = cspPotentialPrimitive; 2268 2269 Var* hasVectorLight = new Var("hasVectorLight", "int"); 2270 hasVectorLight->uniform = true; 2271 hasVectorLight->constSortPos = cspPotentialPrimitive; 2272 2273 Var* vectorLightDirection = new Var("vectorLightDirection", "float4"); 2274 vectorLightDirection->uniform = true; 2275 vectorLightDirection->constSortPos = cspPotentialPrimitive; 2276 2277 Var* vectorLightColor = new Var("vectorLightColor", "float4"); 2278 vectorLightColor->uniform = true; 2279 vectorLightColor->constSortPos = cspPotentialPrimitive; 2280 2281 Var* vectorLightBrightness = new Var("vectorLightBrightness", "float"); 2282 vectorLightBrightness->uniform = true; 2283 vectorLightBrightness->constSortPos = cspPotentialPrimitive; 2284 2285 Var* surface = getSurface(componentList, meta, fd); 2286 if (!surface) 2287 { 2288 Con::errorf("ShaderGen::RTLightingFeatHLSL() - failed to generate surface!"); 2289 return; 2290 } 2291 Var *roughness = (Var*)LangElement::find("roughness"); 2292 2293 Var *metalness = (Var*)LangElement::find("metalness"); 2294 2295 Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); 2296 2297 Var *ambient = new Var( "ambient", "float4" ); 2298 ambient->uniform = true; 2299 ambient->constSortPos = cspPass; 2300 2301 Var* lighting = new Var("lighting", "float4"); 2302 meta->addStatement(new GenOp(" @ = compute4Lights( @, @, @, @,\r\n" 2303 " @, @, @, @, @, @, @);\r\n", 2304 new DecOp(lighting), surface, lightMask, inLightPos, inLightConfigData, inLightColor, inLightSpotDir, lightSpotParams, 2305 hasVectorLight, vectorLightDirection, vectorLightColor, vectorLightBrightness)); 2306 2307 meta->addStatement(new GenOp(" @.rgb += @.rgb;\r\n", curColor, lighting)); 2308 2309 output = meta; 2310} 2311 2312ShaderFeature::Resources RTLightingFeatHLSL::getResources( const MaterialFeatureData &fd ) 2313{ 2314 Resources res; 2315 2316 // These features disable realtime lighting. 2317 if ( !fd.features[MFT_LightMap] && 2318 !fd.features[MFT_ToneMap] && 2319 !fd.features[MFT_VertLit] ) 2320 { 2321 // If enabled we pass the position. 2322 res.numTexReg = 1; 2323 2324 // If there isn't a bump map then we pass the 2325 // world space normal as well. 2326 if ( !fd.features[MFT_NormalMap] ) 2327 res.numTexReg++; 2328 } 2329 2330 return res; 2331} 2332 2333 2334//**************************************************************************** 2335// Fog 2336//**************************************************************************** 2337 2338FogFeatHLSL::FogFeatHLSL() 2339 : mFogDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" )) 2340{ 2341 addDependency( &mFogDep ); 2342} 2343 2344void FogFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 2345 const MaterialFeatureData &fd ) 2346{ 2347 MultiLine *meta = new MultiLine; 2348 2349 const bool vertexFog = Con::getBoolVariable( "$useVertexFog", false ); 2350 if ( vertexFog || GFX->getPixelShaderVersion() < 3.0 ) 2351 { 2352 // Grab the eye position. 2353 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 2354 if ( !eyePos ) 2355 { 2356 eyePos = new Var( "eyePosWorld", "float3" ); 2357 eyePos->uniform = true; 2358 eyePos->constSortPos = cspPass; 2359 } 2360 2361 Var *fogData = new Var( "fogData", "float3" ); 2362 fogData->uniform = true; 2363 fogData->constSortPos = cspPass; 2364 2365 Var *wsPosition = new Var( "fogPos", "float3" ); 2366 getWsPosition( componentList, 2367 fd.features[MFT_UseInstancing], 2368 meta, 2369 new DecOp( wsPosition ) ); 2370 2371 // We pass the fog amount to the pixel shader. 2372 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2373 Var *fogAmount = connectComp->getElement( RT_TEXCOORD ); 2374 fogAmount->setName( "fogAmount" ); 2375 fogAmount->setStructName( "OUT" ); 2376 fogAmount->setType( "float" ); 2377 2378 meta->addStatement( new GenOp( " @ = saturate( computeSceneFog( @, @, @.r, @.g, @.b ) );\r\n", 2379 fogAmount, eyePos, wsPosition, fogData, fogData, fogData ) ); 2380 } 2381 else 2382 { 2383 // We fog in world space... make sure the world space 2384 // position is passed to the pixel shader. This is 2385 // often already passed for lighting, so it takes up 2386 // no extra output registers. 2387 addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); 2388 } 2389 2390 output = meta; 2391} 2392 2393void FogFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 2394 const MaterialFeatureData &fd ) 2395{ 2396 MultiLine *meta = new MultiLine; 2397 2398 Var *fogColor = new Var; 2399 fogColor->setType( "float4" ); 2400 fogColor->setName( "fogColor" ); 2401 fogColor->uniform = true; 2402 fogColor->constSortPos = cspPass; 2403 2404 // Get the out color. 2405 Var *color = (Var*) LangElement::find( "col" ); 2406 if ( !color ) 2407 { 2408 color = new Var; 2409 color->setType( "fragout" ); 2410 color->setName( "col" ); 2411 color->setStructName( "OUT" ); 2412 } 2413 2414 Var *fogAmount; 2415 2416 const bool vertexFog = Con::getBoolVariable( "$useVertexFog", false ); 2417 if ( vertexFog || GFX->getPixelShaderVersion() < 3.0 ) 2418 { 2419 // Per-vertex.... just get the fog amount. 2420 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2421 fogAmount = connectComp->getElement( RT_TEXCOORD ); 2422 fogAmount->setName( "fogAmount" ); 2423 fogAmount->setStructName( "IN" ); 2424 fogAmount->setType( "float" ); 2425 } 2426 else 2427 { 2428 Var *wsPosition = getInWsPosition( componentList ); 2429 2430 // grab the eye position 2431 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 2432 if ( !eyePos ) 2433 { 2434 eyePos = new Var( "eyePosWorld", "float3" ); 2435 eyePos->uniform = true; 2436 eyePos->constSortPos = cspPass; 2437 } 2438 2439 Var *fogData = new Var( "fogData", "float3" ); 2440 fogData->uniform = true; 2441 fogData->constSortPos = cspPass; 2442 2443 /// Get the fog amount. 2444 fogAmount = new Var( "fogAmount", "float" ); 2445 meta->addStatement( new GenOp( " @ = saturate( computeSceneFog( @, @, @.r, @.g, @.b ) );\r\n", 2446 new DecOp( fogAmount ), eyePos, wsPosition, fogData, fogData, fogData ) ); 2447 } 2448 2449 // Lerp between the fog color and diffuse color. 2450 LangElement *fogLerp = new GenOp( "lerp( @.rgb, @.rgb, @ )", fogColor, color, fogAmount ); 2451 meta->addStatement( new GenOp( " @.rgb = @;\r\n", color, fogLerp ) ); 2452 2453 output = meta; 2454} 2455 2456ShaderFeature::Resources FogFeatHLSL::getResources( const MaterialFeatureData &fd ) 2457{ 2458 Resources res; 2459 res.numTexReg = 1; 2460 return res; 2461} 2462 2463 2464//**************************************************************************** 2465// Visibility 2466//**************************************************************************** 2467 2468VisibilityFeatHLSL::VisibilityFeatHLSL() 2469 : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" )) 2470{ 2471 addDependency( &mTorqueDep ); 2472} 2473 2474void VisibilityFeatHLSL::processVert( Vector<ShaderComponent*> &componentList, 2475 const MaterialFeatureData &fd ) 2476{ 2477 MultiLine *meta = new MultiLine; 2478 output = meta; 2479 2480 if ( fd.features[ MFT_UseInstancing ] ) 2481 { 2482 // We pass the visibility to the pixel shader via 2483 // another output register. 2484 // 2485 // TODO: We should see if we can share this register 2486 // with some other common instanced data. 2487 // 2488 ShaderConnector *conn = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2489 Var *outVisibility = conn->getElement( RT_TEXCOORD ); 2490 outVisibility->setStructName( "OUT" ); 2491 outVisibility->setName( "visibility" ); 2492 outVisibility->setType( "float" ); 2493 2494 ShaderConnector *vertStruct = dynamic_cast<ShaderConnector *>( componentList[C_VERT_STRUCT] ); 2495 Var *instVisibility = vertStruct->getElement( RT_TEXCOORD, 1 ); 2496 instVisibility->setStructName( "IN" ); 2497 instVisibility->setName( "inst_visibility" ); 2498 instVisibility->setType( "float" ); 2499 mInstancingFormat->addElement( "visibility", GFXDeclType_Float, instVisibility->constNum ); 2500 2501 meta->addStatement( new GenOp( " @ = @; // Instancing!\r\n", outVisibility, instVisibility ) ); 2502 } 2503 2504 if ( fd.features[ MFT_IsTranslucent ] ) 2505 return; 2506 2507 addOutVpos( meta, componentList ); 2508} 2509 2510void VisibilityFeatHLSL::processPix( Vector<ShaderComponent*> &componentList, 2511 const MaterialFeatureData &fd ) 2512{ 2513 // Get the visibility constant. 2514 Var *visibility = NULL; 2515 if ( fd.features[ MFT_UseInstancing ] ) 2516 visibility = getInTexCoord( "visibility", "float", componentList ); 2517 else 2518 { 2519 visibility = (Var*)LangElement::find( "visibility" ); 2520 2521 if ( !visibility ) 2522 { 2523 visibility = new Var(); 2524 visibility->setType( "float" ); 2525 visibility->setName( "visibility" ); 2526 visibility->uniform = true; 2527 visibility->constSortPos = cspPotentialPrimitive; 2528 } 2529 } 2530 2531 MultiLine *meta = new MultiLine; 2532 output = meta; 2533 2534 // Translucent objects do a simple alpha fade. 2535 if ( fd.features[ MFT_IsTranslucent ] ) 2536 { 2537 Var *color = (Var*)LangElement::find( "col" ); 2538 meta->addStatement( new GenOp( " @.a *= @;\r\n", color, visibility ) ); 2539 return; 2540 } 2541 2542 // Everything else does a fizzle. 2543 Var *vPos = getInVpos( meta, componentList ); 2544 // vpos is a float4 in d3d11 2545 meta->addStatement( new GenOp( " fizzle( @.xy, @ );\r\n", vPos, visibility ) ); 2546} 2547 2548ShaderFeature::Resources VisibilityFeatHLSL::getResources( const MaterialFeatureData &fd ) 2549{ 2550 Resources res; 2551 2552 // TODO: Fix for instancing. 2553 2554 if ( !fd.features[ MFT_IsTranslucent ] ) 2555 res.numTexReg = 1; 2556 2557 return res; 2558} 2559 2560//**************************************************************************** 2561// AlphaTest 2562//**************************************************************************** 2563 2564void AlphaTestHLSL::processPix( Vector<ShaderComponent*> &componentList, 2565 const MaterialFeatureData &fd ) 2566{ 2567 // If we're below SM3 and don't have a depth output 2568 // feature then don't waste an instruction here. 2569 if (( GFX->getPixelShaderVersion() < 3.0 && 2570 !fd.features[ MFT_EyeSpaceDepthOut ] && 2571 !fd.features[ MFT_DepthOut ] ) || 2572 fd.features[MFT_IsTranslucent]) 2573 { 2574 output = NULL; 2575 return; 2576 } 2577 2578 // If we don't have a color var then we cannot do an alpha test. 2579 Var *color = (Var*)LangElement::find( "col1" ); 2580 if (!color) 2581 color = (Var*)LangElement::find("col"); 2582 if ( !color ) 2583 { 2584 output = NULL; 2585 return; 2586 } 2587 2588 // Now grab the alpha test value. 2589 Var *alphaTestVal = new Var; 2590 alphaTestVal->setType( "float" ); 2591 alphaTestVal->setName( "alphaTestValue" ); 2592 alphaTestVal->uniform = true; 2593 alphaTestVal->constSortPos = cspPotentialPrimitive; 2594 2595 // Do the clip. 2596 output = new GenOp( " clip( @.a - @ );\r\n", color, alphaTestVal ); 2597} 2598 2599 2600//**************************************************************************** 2601// GlowMask 2602//**************************************************************************** 2603 2604void GlowMaskHLSL::processPix( Vector<ShaderComponent*> &componentList, 2605 const MaterialFeatureData &fd ) 2606{ 2607 output = NULL; 2608 2609 // Get the output color... and make it black to mask out 2610 // glow passes rendered before us. 2611 // 2612 // The shader compiler will optimize out all the other 2613 // code above that doesn't contribute to the alpha mask. 2614 Var *color = (Var*)LangElement::find( "col" ); 2615 if ( color ) 2616 output = new GenOp( " @.rgb = 0;\r\n", color ); 2617} 2618 2619 2620//**************************************************************************** 2621// RenderTargetZero 2622//**************************************************************************** 2623 2624void RenderTargetZeroHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd ) 2625{ 2626 // Do not actually assign zero, but instead a number so close to zero it may as well be zero. 2627 // This will prevent a divide by zero causing an FP special on float render targets 2628 output = new GenOp( " @;\r\n", assignColor( new GenOp( "0.00001" ), Material::None, NULL, mOutputTargetMask ) ); 2629} 2630 2631 2632//**************************************************************************** 2633// HDR Output 2634//**************************************************************************** 2635 2636HDROutHLSL::HDROutHLSL() 2637 : mTorqueDep(ShaderGen::smCommonShaderPath + String("/torque.hlsl" )) 2638{ 2639 addDependency( &mTorqueDep ); 2640} 2641 2642void HDROutHLSL::processPix( Vector<ShaderComponent*> &componentList, 2643 const MaterialFeatureData &fd ) 2644{ 2645 // Let the helper function do the work. 2646 Var *color = (Var*)LangElement::find( "col" ); 2647 if ( color ) 2648 output = new GenOp( " @ = hdrEncode( @ );\r\n", color, color ); 2649} 2650 2651//**************************************************************************** 2652// FoliageFeatureHLSL 2653//**************************************************************************** 2654 2655#include "T3D/fx/groundCover.h" 2656 2657FoliageFeatureHLSL::FoliageFeatureHLSL() 2658: mDep(ShaderGen::smCommonShaderPath + String("/foliage.hlsl" )) 2659{ 2660 addDependency( &mDep ); 2661} 2662 2663void FoliageFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList, 2664 const MaterialFeatureData &fd ) 2665{ 2666 // Get the input variables we need. 2667 2668 Var *inPosition = (Var*)LangElement::find( "inPosition" ); 2669 if ( !inPosition ) 2670 inPosition = (Var*)LangElement::find( "position" ); 2671 2672 Var *inColor = (Var*)LangElement::find( "diffuse" ); 2673 2674 Var *inParams = (Var*)LangElement::find( "texCoord" ); 2675 2676 MultiLine *meta = new MultiLine; 2677 2678 // Declare the normal and tangent variables since they do not exist 2679 // in this vert type, but we do need to set them up for others. 2680 2681 Var *normal = (Var*)LangElement::find( "normal" ); 2682 AssertFatal( normal, "FoliageFeatureHLSL requires vert normal!" ); 2683 2684 Var *tangent = new Var; 2685 tangent->setType( "float3" ); 2686 tangent->setName( "T" ); 2687 LangElement *tangentDec = new DecOp( tangent ); 2688 meta->addStatement( new GenOp( " @;\n", tangentDec ) ); 2689 2690 // We add a float foliageFade to the OUT structure. 2691 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2692 Var *fade = connectComp->getElement( RT_TEXCOORD ); 2693 fade->setName( "foliageFade" ); 2694 fade->setStructName( "OUT" ); 2695 fade->setType( "float" ); 2696 2697 // grab the eye position 2698 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 2699 if ( !eyePos ) 2700 { 2701 eyePos = new Var( "eyePosWorld", "float3" ); 2702 eyePos->uniform = true; 2703 eyePos->constSortPos = cspPass; 2704 } 2705 2706 // All actual work is offloaded to this method. 2707 meta->addStatement( new GenOp( " foliageProcessVert( @, @, @, @, @, @ );\r\n", inPosition, inColor, inParams, normal, tangent, eyePos ) ); 2708 2709 // Assign to foliageFade. InColor.a was set to the correct value inside foliageProcessVert. 2710 meta->addStatement( new GenOp( " @ = @.a;\r\n", fade, inColor ) ); 2711 2712 output = meta; 2713} 2714 2715void FoliageFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList, 2716 const MaterialFeatureData &fd ) 2717{ 2718 // Find / create IN.foliageFade 2719 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2720 Var *fade = connectComp->getElement( RT_TEXCOORD ); 2721 fade->setName( "foliageFade" ); 2722 fade->setStructName( "IN" ); 2723 fade->setType( "float" ); 2724 2725 // Find / create visibility 2726 Var *visibility = (Var*) LangElement::find( "visibility" ); 2727 if ( !visibility ) 2728 { 2729 visibility = new Var(); 2730 visibility->setType( "float" ); 2731 visibility->setName( "visibility" ); 2732 visibility->uniform = true; 2733 visibility->constSortPos = cspPotentialPrimitive; 2734 } 2735 2736 MultiLine *meta = new MultiLine; 2737 2738 // Multiply foliageFade into visibility. 2739 meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); 2740 2741 output = meta; 2742} 2743 2744void FoliageFeatureHLSL::determineFeature( Material *material, const GFXVertexFormat *vertexFormat, U32 stageNum, const FeatureType &type, const FeatureSet &features, MaterialFeatureData *outFeatureData ) 2745{ 2746 // This isn't really necessary since the outFeatureData will be filtered after 2747 // this call. 2748 if ( features.hasFeature( MFT_Foliage ) ) 2749 outFeatureData->features.addFeature( type ); 2750} 2751 2752 2753ShaderFeatureConstHandles* FoliageFeatureHLSL::createConstHandles( GFXShader *shader, SimObject *userObject ) 2754{ 2755 GroundCover *gcover = dynamic_cast< GroundCover* >( userObject ); 2756 AssertFatal( gcover != NULL, "FoliageFeatureHLSL::createConstHandles - userObject was not valid!" ); 2757 2758 GroundCoverShaderConstHandles *handles = new GroundCoverShaderConstHandles(); 2759 handles->mGroundCover = gcover; 2760 2761 handles->init( shader ); 2762 2763 return handles; 2764} 2765 2766 2767void ParticleNormalFeatureHLSL::processVert(Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd) 2768{ 2769 MultiLine *meta = new MultiLine; 2770 output = meta; 2771 2772 // Calculate normal and tangent values since we want to keep particle verts 2773 // as light-weight as possible 2774 2775 Var *normal = (Var*) LangElement::find("normal"); 2776 if(normal == NULL) 2777 { 2778 normal = new Var; 2779 normal->setType( "float3" ); 2780 normal->setName( "normal" ); 2781 2782 // These values are not accidental. It is slightly adjusted from facing straight into the 2783 // screen because there is a discontinuity at (0, 1, 0) for gbuffer encoding. Do not 2784 // cause this value to be (0, -1, 0) or interlaced normals will be discontinuous. 2785 // [11/23/2009 Pat] 2786 meta->addStatement(new GenOp(" @ = float3(0.0, -0.97, 0.14);\r\n", new DecOp(normal))); 2787 } 2788 2789 Var *T = (Var*) LangElement::find( "T" ); 2790 if(T == NULL) 2791 { 2792 T = new Var; 2793 T->setType( "float3" ); 2794 T->setName( "T" ); 2795 meta->addStatement(new GenOp(" @ = float3(0.0, 0.0, -1.0);\r\n", new DecOp(T))); 2796 } 2797} 2798 2799//**************************************************************************** 2800// ImposterVertFeatureHLSL 2801//**************************************************************************** 2802 2803ImposterVertFeatureHLSL::ImposterVertFeatureHLSL() 2804 : mDep(ShaderGen::smCommonShaderPath + String("/imposter.hlsl" )) 2805{ 2806 addDependency( &mDep ); 2807} 2808 2809void ImposterVertFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList, 2810 const MaterialFeatureData &fd ) 2811{ 2812 MultiLine *meta = new MultiLine; 2813 output = meta; 2814 2815 // Get the input vertex variables. 2816 Var *inPosition = (Var*)LangElement::find( "position" ); 2817 Var *inMiscParams = (Var*)LangElement::find( "tcImposterParams" ); 2818 Var *inUpVec = (Var*)LangElement::find( "tcImposterUpVec" ); 2819 Var *inRightVec = (Var*)LangElement::find( "tcImposterRightVec" ); 2820 2821 // Get the input shader constants. 2822 Var *imposterLimits = new Var; 2823 imposterLimits->setType( "float4" ); 2824 imposterLimits->setName( "imposterLimits" ); 2825 imposterLimits->uniform = true; 2826 imposterLimits->constSortPos = cspPotentialPrimitive; 2827 2828 Var *imposterUVs = new Var; 2829 imposterUVs->setType( "float4" ); 2830 imposterUVs->setName( "imposterUVs" ); 2831 imposterUVs->arraySize = 64; // See imposter.hlsl 2832 imposterUVs->uniform = true; 2833 imposterUVs->constSortPos = cspPotentialPrimitive; 2834 2835 Var *eyePos = (Var*)LangElement::find( "eyePosWorld" ); 2836 if ( !eyePos ) 2837 { 2838 eyePos = new Var( "eyePosWorld", "float3" ); 2839 eyePos->uniform = true; 2840 eyePos->constSortPos = cspPass; 2841 } 2842 2843 // Declare the outputs from this feature. 2844 Var *outInPosition = new Var; 2845 outInPosition->setType( "float3" ); 2846 outInPosition->setName( "inPosition" ); 2847 meta->addStatement( new GenOp( " @;\r\n", new DecOp( outInPosition ) ) ); 2848 2849 Var *outTexCoord = new Var; 2850 outTexCoord->setType( "float2" ); 2851 outTexCoord->setName( "texCoord" ); 2852 meta->addStatement( new GenOp( " @;\r\n", new DecOp( outTexCoord ) ) ); 2853 2854 Var *outWorldToTangent = new Var; 2855 outWorldToTangent->setType( "float3x3" ); 2856 outWorldToTangent->setName( "worldToTangent" ); 2857 meta->addStatement( new GenOp( " @;\r\n", new DecOp( outWorldToTangent ) ) ); 2858 2859 // Add imposterFade to the OUT structure. 2860 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2861 Var *outFade = connectComp->getElement( RT_TEXCOORD ); 2862 outFade->setName( "imposterFade" ); 2863 outFade->setStructName( "OUT" ); 2864 outFade->setType( "float" ); 2865 2866 // Assign OUT.imposterFade 2867 meta->addStatement( new GenOp( " @ = @.y;\r\n", outFade, inMiscParams ) ); 2868 2869 // All actual work is done in this method. 2870 meta->addStatement( new GenOp( " imposter_v( @.xyz, @.w, @.x * length(@), normalize(@), normalize(@), @.y, @.x, @.z, @.w, @, @, @, @, @ );\r\n", 2871 2872 inPosition, 2873 inPosition, 2874 2875 inMiscParams, 2876 inRightVec, 2877 2878 inUpVec, 2879 inRightVec, 2880 2881 imposterLimits, 2882 imposterLimits, 2883 imposterLimits, 2884 imposterLimits, 2885 2886 eyePos, 2887 imposterUVs, 2888 2889 outInPosition, 2890 outTexCoord, 2891 outWorldToTangent ) ); 2892 2893 // Copy the position to wsPosition for use in shaders 2894 // down stream instead of looking for objTrans. 2895 Var *wsPosition = new Var; 2896 wsPosition->setType( "float3" ); 2897 wsPosition->setName( "wsPosition" ); 2898 meta->addStatement( new GenOp( " @ = @.xyz;\r\n", new DecOp( wsPosition ), outInPosition ) ); 2899 2900 // If we new viewToTangent... its the same as the 2901 // world to tangent for an imposter. 2902 Var *viewToTangent = new Var; 2903 viewToTangent->setType( "float3x3" ); 2904 viewToTangent->setName( "viewToTangent" ); 2905 meta->addStatement( new GenOp( " @ = @;\r\n", new DecOp( viewToTangent ), outWorldToTangent ) ); 2906} 2907 2908void ImposterVertFeatureHLSL::processPix( Vector<ShaderComponent*> &componentList, 2909 const MaterialFeatureData &fd ) 2910{ 2911 // Find / create IN.imposterFade 2912 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 2913 Var *fade = connectComp->getElement( RT_TEXCOORD ); 2914 fade->setName( "imposterFade" ); 2915 fade->setStructName( "IN" ); 2916 fade->setType( "float" ); 2917 2918 // Find / create visibility 2919 Var *visibility = (Var*) LangElement::find( "visibility" ); 2920 if ( !visibility ) 2921 { 2922 visibility = new Var(); 2923 visibility->setType( "float" ); 2924 visibility->setName( "visibility" ); 2925 visibility->uniform = true; 2926 visibility->constSortPos = cspPotentialPrimitive; 2927 } 2928 2929 MultiLine *meta = new MultiLine; 2930 2931 // Multiply foliageFade into visibility. 2932 meta->addStatement( new GenOp( " @ *= @;\r\n", visibility, fade ) ); 2933 2934 output = meta; 2935} 2936 2937void ImposterVertFeatureHLSL::determineFeature( Material *material, 2938 const GFXVertexFormat *vertexFormat, 2939 U32 stageNum, 2940 const FeatureType &type, 2941 const FeatureSet &features, 2942 MaterialFeatureData *outFeatureData ) 2943{ 2944 if ( features.hasFeature( MFT_ImposterVert ) ) 2945 outFeatureData->features.addFeature( MFT_ImposterVert ); 2946} 2947 2948//**************************************************************************** 2949// HardwareSkinningFeatureHLSL 2950//**************************************************************************** 2951 2952void HardwareSkinningFeatureHLSL::processVert( Vector<ShaderComponent*> &componentList, 2953 const MaterialFeatureData &fd ) 2954{ 2955 MultiLine *meta = new MultiLine; 2956 2957 Var *inPosition = (Var*)LangElement::find( "inPosition" ); 2958 Var *inNormal = (Var*)LangElement::find( "inNormal" ); 2959 2960 if ( !inPosition ) 2961 inPosition = (Var*)LangElement::find( "position" ); 2962 2963 if ( !inNormal ) 2964 inNormal = (Var*)LangElement::find( "normal" ); 2965 2966 Var* posePos = new Var("posePos", "float3"); 2967 Var* poseNormal = new Var("poseNormal", "float3"); 2968 Var* poseMat = new Var("poseMat", "float4x3"); 2969 Var* poseRotMat = new Var("poseRotMat", "float3x3"); 2970 Var* nodeTransforms = (Var*)LangElement::find("nodeTransforms"); 2971 2972 if (!nodeTransforms) 2973 { 2974 nodeTransforms = new Var("nodeTransforms", "float4x3"); 2975 nodeTransforms->uniform = true; 2976 nodeTransforms->arraySize = TSShape::smMaxSkinBones; 2977 nodeTransforms->constSortPos = cspPotentialPrimitive; 2978 } 2979 2980 U32 numIndices = mVertexFormat->getNumBlendIndices(); 2981 meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( posePos ) ) ); 2982 meta->addStatement( new GenOp( " @ = 0.0;\r\n", new DecOp( poseNormal ) ) ); 2983 meta->addStatement( new GenOp( " @;\r\n", new DecOp( poseMat ) ) ); 2984 meta->addStatement(new GenOp(" @;\r\n int i;\r\n", new DecOp(poseRotMat))); 2985 2986 for (U32 i=0; i<numIndices; i++) 2987 { 2988 // NOTE: To keep things simple, we assume all 4 bone indices are used in each element chunk. 2989 LangElement* inIndices = (Var*)LangElement::find(String::ToString( "blendIndices%d", i )); 2990 LangElement* inWeights = (Var*)LangElement::find(String::ToString( "blendWeight%d", i )); 2991 2992 AssertFatal(inIndices && inWeights, "Something went wrong here"); 2993 AssertFatal(poseMat && nodeTransforms && posePos && inPosition && inWeights && poseNormal && inNormal && poseRotMat, "Something went REALLY wrong here"); 2994 2995 meta->addStatement( new GenOp( " for (i=0; i<4; i++) {\r\n" ) ); 2996 meta->addStatement( new GenOp( " int poseIdx = int(@[i]);\r\n", inIndices ) ); 2997 meta->addStatement( new GenOp( " float poseWeight = @[i];\r\n", inWeights) ); 2998 meta->addStatement( new GenOp( " @ = @[poseIdx];\r\n", poseMat, nodeTransforms) ); 2999 meta->addStatement( new GenOp( " @ = (float3x3)@;\r\n", poseRotMat, poseMat) ); 3000 meta->addStatement( new GenOp( " @ += (mul(float4(@, 1), @)).xyz * poseWeight;\r\n", posePos, inPosition, poseMat) ); 3001 meta->addStatement( new GenOp( " @ += (mul(@,@) * poseWeight);\r\n", poseNormal, inNormal, poseRotMat) ); 3002 meta->addStatement( new GenOp( " }\r\n" ) ); 3003 } 3004 3005 // Assign new position and normal 3006 meta->addStatement( new GenOp( " @ = @;\r\n", inPosition, posePos ) ); 3007 meta->addStatement( new GenOp( " @ = normalize(@);\r\n", inNormal, poseNormal ) ); 3008 3009 output = meta; 3010} 3011 3012//**************************************************************************** 3013// ReflectionProbeFeatHLSL 3014//**************************************************************************** 3015 3016ReflectionProbeFeatHLSL::ReflectionProbeFeatHLSL() 3017 : mDep(ShaderGen::smCommonShaderPath + String("/lighting.hlsl")) 3018{ 3019 addDependency(&mDep); 3020} 3021 3022void ReflectionProbeFeatHLSL::processVert(Vector<ShaderComponent*>& componentList, 3023 const MaterialFeatureData& fd) 3024{ 3025 MultiLine* meta = new MultiLine; 3026 output = meta; 3027 // Also output the worldToTanget transform which 3028 // we use to create the world space normal. 3029 getOutWorldToTangent(componentList, meta, fd); 3030} 3031 3032void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList, 3033 const MaterialFeatureData &fd) 3034{ 3035 // Skip out on realtime lighting if we don't have a normal 3036 // or we're doing some sort of baked lighting. 3037 // 3038 // TODO: We can totally detect for this in the material 3039 // feature setup... we should move it out of here! 3040 // 3041 if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit]) 3042 return; 3043 3044 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]); 3045 3046 MultiLine *meta = new MultiLine; 3047 3048 // Now the wsPosition and wsView. 3049 Var* worldToTangent = getInWorldToTangent(componentList); 3050 Var *wsNormal = getInWorldNormal(componentList); 3051 Var* wsPosition = getInWsPosition(componentList); 3052 Var *wsView = getWsView(wsPosition, meta); 3053 3054 //Reflection Probe WIP 3055 U32 MAX_FORWARD_PROBES = 4; 3056 3057 Var *numProbes = new Var("numProbes", "int"); 3058 numProbes->uniform = true; 3059 numProbes->constSortPos = cspPotentialPrimitive; 3060 3061 Var *cubeMips = new Var("cubeMips", "float"); 3062 cubeMips->uniform = true; 3063 cubeMips->constSortPos = cspPotentialPrimitive; 3064 3065 Var * skylightCubemapIdx = new Var("skylightCubemapIdx", "float"); 3066 skylightCubemapIdx->uniform = true; 3067 skylightCubemapIdx->constSortPos = cspPotentialPrimitive; 3068 3069 Var *inProbePosArray = new Var("inProbePosArray", "float4"); 3070 inProbePosArray->arraySize = MAX_FORWARD_PROBES; 3071 inProbePosArray->uniform = true; 3072 inProbePosArray->constSortPos = cspPotentialPrimitive; 3073 3074 Var *inRefPosArray = new Var("inRefPosArray", "float4"); 3075 inRefPosArray->arraySize = MAX_FORWARD_PROBES; 3076 inRefPosArray->uniform = true; 3077 inRefPosArray->constSortPos = cspPotentialPrimitive; 3078 3079 Var * refScaleArray = new Var("inRefScale", "float4"); 3080 refScaleArray->arraySize = MAX_FORWARD_PROBES; 3081 refScaleArray->uniform = true; 3082 refScaleArray->constSortPos = cspPotentialPrimitive; 3083 3084 Var *probeConfigData = new Var("probeConfigData", "float4"); 3085 probeConfigData->arraySize = MAX_FORWARD_PROBES; 3086 probeConfigData->uniform = true; 3087 probeConfigData->constSortPos = cspPotentialPrimitive; 3088 3089 Var *worldToObjArray = new Var("worldToObjArray", "float4x4"); 3090 worldToObjArray->arraySize = MAX_FORWARD_PROBES; 3091 worldToObjArray->uniform = true; 3092 worldToObjArray->constSortPos = cspPotentialPrimitive; 3093 3094 Var *BRDFTexture = new Var("BRDFTexture", "SamplerState"); 3095 BRDFTexture->uniform = true; 3096 BRDFTexture->sampler = true; 3097 BRDFTexture->constNum = Var::getTexUnitNum(); // used as texture unit num here 3098 3099 Var *BRDFTextureTex = new Var("texture_BRDFTexture", "Texture2D"); 3100 BRDFTextureTex->uniform = true; 3101 BRDFTextureTex->texture = true; 3102 BRDFTextureTex->constNum = BRDFTexture->constNum; 3103 3104 Var *specularCubemapAR = new Var("specularCubemapAR", "SamplerState"); 3105 specularCubemapAR->uniform = true; 3106 specularCubemapAR->sampler = true; 3107 specularCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here 3108 3109 Var *specularCubemapARTex = new Var("texture_specularCubemapAR", "TextureCubeArray"); 3110 specularCubemapARTex->uniform = true; 3111 specularCubemapARTex->texture = true; 3112 specularCubemapARTex->constNum = specularCubemapAR->constNum; 3113 3114 Var *irradianceCubemapAR = new Var("irradianceCubemapAR", "SamplerState"); 3115 irradianceCubemapAR->uniform = true; 3116 irradianceCubemapAR->sampler = true; 3117 irradianceCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here 3118 3119 Var *irradianceCubemapARTex = new Var("texture_irradianceCubemapAR", "TextureCubeArray"); 3120 irradianceCubemapARTex->uniform = true; 3121 irradianceCubemapARTex->texture = true; 3122 irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum; 3123 3124 Var* surface = getSurface(componentList, meta, fd); 3125 3126 if (!surface) 3127 { 3128 Con::errorf("ShaderGen::ReflectionProbeFeatHLSL() - failed to generate surface!"); 3129 return; 3130 } 3131 3132 Var *curColor = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); 3133 3134 //Reflection vec 3135 Var* ibl = (Var*)LangElement::find("ibl"); 3136 if (!ibl) 3137 { 3138 ibl = new Var("ibl", "float3"); 3139 } 3140 3141 String computeForwardProbes = String::String(" @ = computeForwardProbes(@,@,@,@,@,@,@,@,\r\n\t\t"); 3142 computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t"); 3143 computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n"); 3144 3145 meta->addStatement(new GenOp(computeForwardProbes.c_str(), new DecOp(ibl), surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, refScaleArray, inRefPosArray, 3146 skylightCubemapIdx, BRDFTexture, 3147 irradianceCubemapAR, specularCubemapAR)); 3148 3149 meta->addStatement(new GenOp(" @.rgb = @.rgb;\r\n", curColor, ibl)); 3150 3151 output = meta; 3152} 3153 3154ShaderFeature::Resources ReflectionProbeFeatHLSL::getResources(const MaterialFeatureData &fd) 3155{ 3156 Resources res; 3157 3158 res.numTex = 3; 3159 res.numTexReg = 3; 3160 3161 return res; 3162} 3163 3164void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat, 3165 const MaterialFeatureData &stageFeatures, 3166 RenderPassData &passData, 3167 U32 &texIndex) 3168{ 3169 if (stageFeatures.features[MFT_ReflectionProbes]) 3170 { 3171 passData.mSamplerNames[texIndex] = "BRDFTexture"; 3172 passData.mTexType[texIndex++] = Material::Standard; 3173 // assuming here that it is a scenegraph cubemap 3174 passData.mSamplerNames[texIndex] = "specularCubemapAR"; 3175 passData.mTexType[texIndex++] = Material::SGCube; 3176 passData.mSamplerNames[texIndex] = "irradianceCubemapAR"; 3177 passData.mTexType[texIndex++] = Material::SGCube; 3178 } 3179} 3180