advancedLightingFeaturesGLSL.cpp
Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.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 "lighting/advanced/glsl/advancedLightingFeaturesGLSL.h" 26 27#include "lighting/advanced/advancedLightBinManager.h" 28#include "shaderGen/langElement.h" 29#include "shaderGen/shaderOp.h" 30#include "shaderGen/conditionerFeature.h" 31#include "renderInstance/renderDeferredMgr.h" 32#include "materials/processedMaterial.h" 33#include "materials/materialFeatureTypes.h" 34 35 36void DeferredRTLightingFeatGLSL::processPixMacros( Vector<GFXShaderMacro> ¯os, 37 const MaterialFeatureData &fd ) 38{ 39 // Skip deferred features, and use forward shading instead 40 if ( !fd.features[MFT_isDeferred] ) 41 { 42 Parent::processPixMacros( macros, fd ); 43 return; 44 } 45 46 // Pull in the uncondition method for the light info buffer 47 NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName ); 48 if ( texTarget && texTarget->getConditioner() ) 49 { 50 ConditionerMethodDependency *unconditionMethod = texTarget->getConditioner()->getConditionerMethodDependency(ConditionerFeature::UnconditionMethod); 51 unconditionMethod->createMethodMacro( String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition", macros ); 52 addDependency(unconditionMethod); 53 } 54} 55 56void DeferredRTLightingFeatGLSL::processVert( Vector<ShaderComponent*> &componentList, 57 const MaterialFeatureData &fd ) 58{ 59 // Skip deferred features, and use forward shading instead 60 if ( !fd.features[MFT_isDeferred] ) 61 { 62 Parent::processVert( componentList, fd ); 63 return; 64 } 65 66 // Pass screen space position to pixel shader to compute a full screen buffer uv 67 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 68 Var *ssPos = connectComp->getElement( RT_TEXCOORD ); 69 ssPos->setName( "screenspacePos" ); 70 ssPos->setStructName( "OUT" ); 71 ssPos->setType( "vec4" ); 72 73 Var *outPosition = (Var*) LangElement::find( "gl_Position" ); 74 AssertFatal( outPosition, "No gl_Position, ohnoes." ); 75 76 output = new GenOp( " @ = @;\r\n", ssPos, outPosition ); 77} 78 79void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &componentList, 80 const MaterialFeatureData &fd ) 81{ 82 // Skip deferred features, and use forward shading instead 83 if ( !fd.features[MFT_isDeferred] ) 84 { 85 Parent::processPix( componentList, fd ); 86 return; 87 } 88 89 MultiLine *meta = new MultiLine; 90 91 ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] ); 92 Var *ssPos = connectComp->getElement( RT_TEXCOORD ); 93 ssPos->setName( "screenspacePos" ); 94 ssPos->setStructName( "IN" ); 95 ssPos->setType( "vec4" ); 96 97 Var *uvScene = new Var; 98 uvScene->setType( "vec2" ); 99 uvScene->setName( "uvScene" ); 100 LangElement *uvSceneDecl = new DecOp( uvScene ); 101 102 String rtParamName = String::ToString( "rtParams%s", "diffuseLightingBuffer" ); 103 Var *rtParams = (Var*) LangElement::find( rtParamName ); 104 if( !rtParams ) 105 { 106 rtParams = new Var; 107 rtParams->setType( "vec4" ); 108 rtParams->setName( rtParamName ); 109 rtParams->uniform = true; 110 rtParams->constSortPos = cspPass; 111 } 112 113 meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", uvSceneDecl, ssPos, ssPos ) ); // get the screen coord... its -1 to +1 114 meta->addStatement( new GenOp( " @ = ( @ + 1.0 ) / 2.0;\r\n", uvScene, uvScene ) ); // get the screen coord to 0 to 1 115 meta->addStatement( new GenOp( " @.y = 1.0 - @.y;\r\n", uvScene, uvScene ) ); // flip the y axis 116 meta->addStatement( new GenOp( " @ = ( @ * @.zw ) + @.xy;\r\n", uvScene, uvScene, rtParams, rtParams) ); // scale it down and offset it to the rt size 117 118 // create texture var 119 Var *lightInfoBuffer = new Var; 120 lightInfoBuffer->setType( "sampler2D" ); 121 lightInfoBuffer->setName( "diffuseLightingBuffer" ); 122 lightInfoBuffer->uniform = true; 123 lightInfoBuffer->sampler = true; 124 lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here 125 126 // Declare the RTLighting variables in this feature, they will either be assigned 127 // in this feature, or in the tonemap/lightmap feature 128 Var *d_lightcolor = new Var( "d_lightcolor", "vec3" ); 129 meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_lightcolor ) ) ); 130 131 Var *d_NL_Att = new Var( "d_NL_Att", "float" ); 132 meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_NL_Att ) ) ); 133 134 Var *d_specular = new Var( "d_specular", "float" ); 135 meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_specular ) ) ); 136 137 138 // Perform the uncondition here. 139 String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition"; 140 meta->addStatement( new GenOp( avar( " %s(tex2D(@, @), @, @, @);\r\n", 141 unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, d_lightcolor, d_NL_Att, d_specular ) ); 142 143 // This is kind of weak sauce 144 if( !fd.features[MFT_VertLit] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] && !fd.features[MFT_SubSurface] ) 145 meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@, 1.0)", d_lightcolor ), Material::Mul ) ) ); 146 147 output = meta; 148} 149 150ShaderFeature::Resources DeferredRTLightingFeatGLSL::getResources( const MaterialFeatureData &fd ) 151{ 152 // Skip deferred features, and use forward shading instead 153 if ( !fd.features[MFT_isDeferred] ) 154 return Parent::getResources( fd ); 155 156 // HACK: See DeferredRTLightingFeatGLSL::setTexData. 157 mLastTexIndex = 0; 158 159 Resources res; 160 res.numTex = 1; 161 res.numTexReg = 1; 162 return res; 163} 164 165void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat, 166 const MaterialFeatureData &fd, 167 RenderPassData &passData, 168 U32 &texIndex ) 169{ 170 // Skip deferred features, and use forward shading instead 171 if ( !fd.features[MFT_isDeferred] ) 172 { 173 Parent::setTexData( stageDat, fd, passData, texIndex ); 174 return; 175 } 176 177 NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName ); 178 if( texTarget ) 179 { 180 // HACK: We store this for use in DeferredRTLightingFeatGLSL::processPix() 181 // which cannot deduce the texture unit itself. 182 mLastTexIndex = texIndex; 183 184 passData.mTexType[ texIndex ] = Material::TexTarget; 185 passData.mSamplerNames[ texIndex ]= "diffuseLightingBuffer"; 186 passData.mTexSlot[ texIndex++ ].texTarget = texTarget; 187 } 188} 189 190 191void DeferredBumpFeatGLSL::processVert( Vector<ShaderComponent*> &componentList, 192 const MaterialFeatureData &fd ) 193{ 194 if( fd.features[MFT_DeferredConditioner] ) 195 { 196 // There is an output conditioner active, so we need to supply a transform 197 // to the pixel shader. 198 MultiLine *meta = new MultiLine; 199 200 // We need the view to tangent space transform in the pixel shader. 201 getOutViewToTangent( componentList, meta, fd ); 202 203 const bool useTexAnim = fd.features[MFT_TexAnim]; 204 // Make sure there are texcoords 205 if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap]) 206 { 207 208 getOutTexCoord( "texCoord", 209 "vec2", 210 useTexAnim, 211 meta, 212 componentList ); 213 } 214 215 const bool useFoliageTexCoord = fd.features[MFT_Foliage]; 216 217 if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) 218 addOutDetailTexCoord( componentList, 219 meta, 220 useTexAnim, useFoliageTexCoord); 221 222 output = meta; 223 } 224 else if ( fd.materialFeatures[MFT_NormalsOut] || 225 !fd.features[MFT_isDeferred] || 226 !fd.features[MFT_RTLighting] ) 227 { 228 Parent::processVert( componentList, fd ); 229 return; 230 } 231 else 232 { 233 output = NULL; 234 } 235} 236 237void DeferredBumpFeatGLSL::processPix( Vector<ShaderComponent*> &componentList, 238 const MaterialFeatureData &fd ) 239{ 240 // NULL output in case nothing gets handled 241 output = NULL; 242 243 if( fd.features[MFT_DeferredConditioner] ) 244 { 245 MultiLine *meta = new MultiLine; 246 247 Var *viewToTangent = getInViewToTangent( componentList ); 248 249 // create texture var 250 Var *bumpMap = getNormalMapTex(); 251 Var *texCoord = getInTexCoord( "texCoord", "vec2", componentList ); 252 LangElement *texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); 253 254 // create bump normal 255 Var *bumpNorm = new Var; 256 bumpNorm->setName( "bumpNormal" ); 257 bumpNorm->setType( "vec4" ); 258 259 LangElement *bumpNormDecl = new DecOp( bumpNorm ); 260 meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) ); 261 262 // If we have a detail normal map we add the xy coords of 263 // it to the base normal map. This gives us the effect we 264 // want with few instructions and minial artifacts. 265 if ( fd.features.hasFeature( MFT_DetailNormalMap ) ) 266 { 267 bumpMap = new Var; 268 bumpMap->setType( "sampler2D" ); 269 bumpMap->setName( "detailBumpMap" ); 270 bumpMap->uniform = true; 271 bumpMap->sampler = true; 272 bumpMap->constNum = Var::getTexUnitNum(); 273 274 texCoord = getInTexCoord( "detCoord", "vec2", componentList ); 275 texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord ); 276 277 Var *detailBump = new Var; 278 detailBump->setName( "detailBump" ); 279 detailBump->setType( "vec4" ); 280 meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) ); 281 282 Var *detailBumpScale = new Var; 283 detailBumpScale->setType( "float" ); 284 detailBumpScale->setName( "detailBumpStrength" ); 285 detailBumpScale->uniform = true; 286 detailBumpScale->constSortPos = cspPass; 287 meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) ); 288 } 289 290 // This var is read from GBufferConditionerGLSL and 291 // used in the deferred output. 292 // 293 // By using the 'half' type here we get a bunch of partial 294 // precision optimized code on further operations on the normal 295 // which helps alot on older Geforce cards. 296 // 297 Var *gbNormal = new Var; 298 gbNormal->setName( "gbNormal" ); 299 gbNormal->setType( "half3" ); 300 LangElement *gbNormalDecl = new DecOp( gbNormal ); 301 302 // Normalize is done later... 303 // Note: The reverse mul order is intentional. Affine matrix. 304 meta->addStatement( new GenOp( " @ = half3(tMul( @.xyz, @ ));\r\n", gbNormalDecl, bumpNorm, viewToTangent ) ); 305 306 output = meta; 307 return; 308 } 309 310 else if (fd.features[MFT_AccuMap]) 311 { 312 Var *bumpSample = (Var *)LangElement::find("bumpSample"); 313 if (bumpSample == NULL) 314 { 315 MultiLine *meta = new MultiLine; 316 317 Var *texCoord = getInTexCoord("texCoord", "vec2", componentList); 318 319 Var *bumpMap = getNormalMapTex(); 320 321 bumpSample = new Var; 322 bumpSample->setType("vec4"); 323 bumpSample->setName("bumpSample"); 324 LangElement *bumpSampleDecl = new DecOp(bumpSample); 325 326 meta->addStatement(new GenOp(" @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord)); 327 328 if (fd.features.hasFeature(MFT_DetailNormalMap)) 329 { 330 bumpMap = (Var*)LangElement::find("detailBumpMap"); 331 if (!bumpMap) { 332 bumpMap = new Var; 333 bumpMap->setType("sampler2D"); 334 bumpMap->setName("detailBumpMap"); 335 bumpMap->uniform = true; 336 bumpMap->sampler = true; 337 bumpMap->constNum = Var::getTexUnitNum(); 338 } 339 340 texCoord = getInTexCoord("detCoord", "vec2", componentList); 341 LangElement *texOp = new GenOp("tex2D(@, @)", bumpMap, texCoord); 342 343 Var *detailBump = new Var; 344 detailBump->setName("detailBump"); 345 detailBump->setType("vec4"); 346 meta->addStatement(expandNormalMap(texOp, new DecOp(detailBump), detailBump, fd)); 347 348 Var *detailBumpScale = new Var; 349 detailBumpScale->setType("float"); 350 detailBumpScale->setName("detailBumpStrength"); 351 detailBumpScale->uniform = true; 352 detailBumpScale->constSortPos = cspPass; 353 meta->addStatement(new GenOp(" @.xy += @.xy * @;\r\n", bumpSample, detailBump, detailBumpScale)); 354 } 355 356 output = meta; 357 358 return; 359 } 360 } 361 else if ( fd.materialFeatures[MFT_NormalsOut] || 362 !fd.features[MFT_isDeferred] || 363 !fd.features[MFT_RTLighting] ) 364 { 365 Parent::processPix( componentList, fd ); 366 return; 367 } 368 else if (!fd.features[MFT_OrmMap] ) 369 { 370 Var *bumpSample = (Var *)LangElement::find( "bumpSample" ); 371 if( bumpSample == NULL ) 372 { 373 Var *texCoord = getInTexCoord( "texCoord", "vec2", componentList ); 374 375 Var *bumpMap = getNormalMapTex(); 376 377 bumpSample = new Var; 378 bumpSample->setType( "vec4" ); 379 bumpSample->setName( "bumpSample" ); 380 LangElement *bumpSampleDecl = new DecOp( bumpSample ); 381 382 output = new GenOp( " @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord ); 383 return; 384 } 385 } 386 387 output = NULL; 388} 389 390ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatureData &fd ) 391{ 392 if ( fd.materialFeatures[MFT_NormalsOut] || 393 !fd.features[MFT_isDeferred] || 394 fd.features[MFT_Parallax] || 395 !fd.features[MFT_RTLighting] ) 396 return Parent::getResources( fd ); 397 398 Resources res; 399 if(!fd.features[MFT_OrmMap]) 400 { 401 res.numTex = 1; 402 res.numTexReg = 1; 403 404 if ( fd.features[MFT_DeferredConditioner] && 405 fd.features.hasFeature( MFT_DetailNormalMap ) ) 406 { 407 res.numTex += 1; 408 if ( !fd.features.hasFeature( MFT_DetailMap ) ) 409 res.numTexReg += 1; 410 } 411 } 412 413 return res; 414} 415 416void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat, 417 const MaterialFeatureData &fd, 418 RenderPassData &passData, 419 U32 &texIndex ) 420{ 421 if ( fd.materialFeatures[MFT_NormalsOut] || 422 !fd.features[MFT_isDeferred] || 423 !fd.features[MFT_RTLighting] ) 424 { 425 Parent::setTexData( stageDat, fd, passData, texIndex ); 426 return; 427 } 428 429 if (!fd.features[MFT_DeferredConditioner] && fd.features[MFT_AccuMap]) 430 { 431 passData.mTexType[texIndex] = Material::Bump; 432 passData.mSamplerNames[texIndex] = "bumpMap"; 433 passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_NormalMap); 434 435 if (fd.features.hasFeature(MFT_DetailNormalMap)) 436 { 437 passData.mTexType[texIndex] = Material::DetailBump; 438 passData.mSamplerNames[texIndex] = "detailBumpMap"; 439 passData.mTexSlot[texIndex++].texObject = stageDat.getTex(MFT_DetailNormalMap); 440 } 441 } 442 else if (!fd.features[MFT_Parallax] && !fd.features[MFT_OrmMap] && 443 ( fd.features[MFT_DeferredConditioner]) ) 444 { 445 passData.mTexType[ texIndex ] = Material::Bump; 446 passData.mSamplerNames[ texIndex ] = "bumpMap"; 447 passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); 448 449 if ( fd.features[MFT_DeferredConditioner] && 450 fd.features.hasFeature( MFT_DetailNormalMap ) ) 451 { 452 passData.mTexType[ texIndex ] = Material::DetailBump; 453 passData.mSamplerNames[ texIndex ] = "detailBumpMap"; 454 passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); 455 } 456 } 457} 458 459 460ShaderFeature::Resources DeferredMinnaertGLSL::getResources( const MaterialFeatureData &fd ) 461{ 462 Resources res; 463 if( fd.features[MFT_isDeferred] && fd.features[MFT_RTLighting] ) 464 { 465 res.numTex = 1; 466 res.numTexReg = 1; 467 } 468 return res; 469} 470 471void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat, 472 const MaterialFeatureData &fd, 473 RenderPassData &passData, 474 U32 &texIndex ) 475{ 476 if( fd.features[MFT_isDeferred] && fd.features[MFT_RTLighting] ) 477 { 478 NamedTexTarget *texTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName); 479 if ( texTarget ) 480 { 481 passData.mTexType[texIndex] = Material::TexTarget; 482 passData.mSamplerNames[texIndex] = "deferredBuffer"; 483 passData.mTexSlot[ texIndex++ ].texTarget = texTarget; 484 } 485 } 486} 487 488void DeferredMinnaertGLSL::processPixMacros( Vector<GFXShaderMacro> ¯os, 489 const MaterialFeatureData &fd ) 490{ 491 if( fd.features[MFT_isDeferred] && fd.features[MFT_RTLighting] ) 492 { 493 // Pull in the uncondition method for the g buffer 494 NamedTexTarget *texTarget = NamedTexTarget::find( RenderDeferredMgr::BufferName ); 495 if ( texTarget && texTarget->getConditioner() ) 496 { 497 ConditionerMethodDependency *unconditionMethod = texTarget->getConditioner()->getConditionerMethodDependency(ConditionerFeature::UnconditionMethod); 498 unconditionMethod->createMethodMacro( String::ToLower(RenderDeferredMgr::BufferName) + "Uncondition", macros ); 499 addDependency(unconditionMethod); 500 } 501 } 502} 503 504void DeferredMinnaertGLSL::processVert( Vector<ShaderComponent*> &componentList, 505 const MaterialFeatureData &fd ) 506{ 507 // If there is no deferred information, bail on this feature 508 if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] ) 509 { 510 output = NULL; 511 return; 512 } 513 514 // Make sure we pass the world space position to the 515 // pixel shader so we can calculate a view vector. 516 MultiLine *meta = new MultiLine; 517 addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta ); 518 output = meta; 519} 520 521void DeferredMinnaertGLSL::processPix( Vector<ShaderComponent*> &componentList, 522 const MaterialFeatureData &fd ) 523{ 524 // If there is no deferred information, bail on this feature 525 if( !fd.features[MFT_isDeferred] || !fd.features[MFT_RTLighting] ) 526 { 527 output = NULL; 528 return; 529 } 530 531 Var *minnaertConstant = new Var; 532 minnaertConstant->setType( "float" ); 533 minnaertConstant->setName( "minnaertConstant" ); 534 minnaertConstant->uniform = true; 535 minnaertConstant->constSortPos = cspPotentialPrimitive; 536 537 // create texture var 538 Var *deferredBuffer = new Var; 539 deferredBuffer->setType( "sampler2D" ); 540 deferredBuffer->setName( "deferredBuffer" ); 541 deferredBuffer->uniform = true; 542 deferredBuffer->sampler = true; 543 deferredBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here 544 545 // Texture coord 546 Var *uvScene = (Var*) LangElement::find( "uvScene" ); 547 AssertFatal(uvScene != NULL, "Unable to find UVScene, no RTLighting feature?"); 548 549 MultiLine *meta = new MultiLine; 550 551 // Get the world space view vector. 552 Var *wsViewVec = getWsView( getInWsPosition( componentList ), meta ); 553 554 String unconditionDeferredMethod = String::ToLower(RenderDeferredMgr::BufferName) + "Uncondition"; 555 556 Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); 557 558 meta->addStatement( new GenOp( avar( " vec4 normalDepth = %s(@, @);\r\n", unconditionDeferredMethod.c_str() ), deferredBuffer, uvScene ) ); 559 meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, @);\r\n", wsViewVec ) ); 560 meta->addStatement( new GenOp( " float Minnaert = pow( @, @) * pow(vDotN, 1.0 - @);\r\n", d_NL_Att, minnaertConstant, minnaertConstant ) ); 561 meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) ); 562 563 output = meta; 564} 565 566 567void DeferredSubSurfaceGLSL::processPix( Vector<ShaderComponent*> &componentList, 568 const MaterialFeatureData &fd ) 569{ 570 571 Var *subSurfaceParams = new Var; 572 subSurfaceParams->setType( "vec4" ); 573 subSurfaceParams->setName( "subSurfaceParams" ); 574 subSurfaceParams->uniform = true; 575 subSurfaceParams->constSortPos = cspPotentialPrimitive; 576 577 Var *d_lightcolor = (Var*)LangElement::find( "d_lightcolor" ); 578 Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" ); 579 580 MultiLine *meta = new MultiLine; 581 Var* targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); 582 if (fd.features[MFT_isDeferred]) 583 { 584 targ = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget3)); 585 meta->addStatement(new GenOp(" @.rgb += @.rgb*@.a;\r\n", targ, subSurfaceParams, subSurfaceParams)); 586 output = meta; 587 return; 588 } 589 590 output = meta; 591} 592