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