1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 //-----------------------------------------------------------------------------
23 #include "platform/platform.h"
24 #include "terrain/glsl/terrFeatureGLSL.h"
26 #include "terrain/terrFeatureTypes.h"
27 #include "materials/materialFeatureTypes.h"
28 #include "materials/materialFeatureData.h"
29 #include "materials/processedMaterial.h"
30 #include "gfx/gfxDevice.h"
31 #include "shaderGen/langElement.h"
32 #include "shaderGen/shaderOp.h"
33 #include "shaderGen/featureMgr.h"
34 #include "shaderGen/shaderGen.h"
35 #include "core/module.h"
39 void register_glsl_shader_features_for_terrain(GFXAdapterType type
)
44 FEATUREMGR
->registerFeature( MFT_TerrainBaseMap
, new TerrainBaseMapFeatGLSL
);
45 FEATUREMGR
->registerFeature( MFT_TerrainParallaxMap
, new NamedFeatureGLSL( "Terrain Parallax Texture" ) );
46 FEATUREMGR
->registerFeature( MFT_TerrainDetailMap
, new TerrainDetailMapFeatGLSL
);
47 FEATUREMGR
->registerFeature( MFT_TerrainNormalMap
, new TerrainNormalMapFeatGLSL
);
48 FEATUREMGR
->registerFeature( MFT_TerrainMacroMap
, new TerrainMacroMapFeatGLSL
);
49 FEATUREMGR
->registerFeature( MFT_TerrainLightMap
, new TerrainLightMapFeatGLSL
);
50 FEATUREMGR
->registerFeature( MFT_TerrainSideProject
, new NamedFeatureGLSL( "Terrain Side Projection" ) );
51 FEATUREMGR
->registerFeature( MFT_TerrainAdditive
, new TerrainAdditiveFeatGLSL
);
52 FEATUREMGR
->registerFeature( MFT_DeferredTerrainBaseMap
, new TerrainBaseMapFeatGLSL
);
53 FEATUREMGR
->registerFeature( MFT_DeferredTerrainMacroMap
, new TerrainMacroMapFeatGLSL
);
54 FEATUREMGR
->registerFeature( MFT_DeferredTerrainDetailMap
, new TerrainDetailMapFeatGLSL
);
55 FEATUREMGR
->registerFeature( MFT_DeferredTerrainBlankInfoMap
, new TerrainBlankInfoMapFeatGLSL
);
60 MODULE_BEGIN( TerrainFeatGLSL
)
62 MODULE_INIT_AFTER( ShaderGen
)
66 SHADERGEN
->getFeatureInitSignal().notify(®ister_glsl_shader_features_for_terrain
);
72 TerrainFeatGLSL::TerrainFeatGLSL()
73 : mTorqueDep( "shaders/common/gl/torque.glsl" )
75 addDependency( &mTorqueDep
);
78 Var
* TerrainFeatGLSL::_getUniformVar( const char *name
, const char *type
, ConstantSortPosition csp
)
80 Var
*theVar
= (Var
*)LangElement::find( name
);
84 theVar
->setType( type
);
85 theVar
->setName( name
);
86 theVar
->uniform
= true;
87 theVar
->constSortPos
= csp
;
93 Var
* TerrainFeatGLSL::_getInDetailCoord( Vector
<ShaderComponent
*> &componentList
)
95 String
name( String::ToString( "detCoord%d", getProcessIndex() ) );
96 Var
*inDet
= (Var
*)LangElement::find( name
);
100 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
102 inDet
= connectComp
->getElement( RT_TEXCOORD
);
103 inDet
->setName( name
);
104 inDet
->setStructName( "IN" );
105 inDet
->setType( "vec4" );
106 inDet
->mapsToSampler
= true;
112 Var
* TerrainFeatGLSL::_getInMacroCoord( Vector
<ShaderComponent
*> &componentList
)
114 String
name( String::ToString( "macroCoord%d", getProcessIndex() ) );
115 Var
*inDet
= (Var
*)LangElement::find( name
);
119 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
121 inDet
= connectComp
->getElement( RT_TEXCOORD
);
122 inDet
->setName( name
);
123 inDet
->setStructName( "IN" );
124 inDet
->setType( "vec4" );
125 inDet
->mapsToSampler
= true;
131 Var
* TerrainFeatGLSL::_getNormalMapTex()
133 String
name( String::ToString( "normalMap%d", getProcessIndex() ) );
134 Var
*normalMap
= (Var
*)LangElement::find( name
);
139 normalMap
->setType( "sampler2D" );
140 normalMap
->setName( name
);
141 normalMap
->uniform
= true;
142 normalMap
->sampler
= true;
143 normalMap
->constNum
= Var::getTexUnitNum();
149 Var
* TerrainFeatGLSL::_getDetailIdStrengthParallax()
151 String
name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
153 Var
*detailInfo
= (Var
*)LangElement::find( name
);
156 detailInfo
= new Var
;
157 detailInfo
->setType( "vec3" );
158 detailInfo
->setName( name
);
159 detailInfo
->uniform
= true;
160 detailInfo
->constSortPos
= cspPotentialPrimitive
;
166 Var
* TerrainFeatGLSL::_getMacroIdStrengthParallax()
168 String
name( String::ToString( "macroIdStrengthParallax%d", getProcessIndex() ) );
170 Var
*detailInfo
= (Var
*)LangElement::find( name
);
173 detailInfo
= new Var
;
174 detailInfo
->setType( "vec3" );
175 detailInfo
->setName( name
);
176 detailInfo
->uniform
= true;
177 detailInfo
->constSortPos
= cspPotentialPrimitive
;
184 void TerrainBaseMapFeatGLSL::processVert( Vector
<ShaderComponent
*> &componentList
,
185 const MaterialFeatureData
&fd
)
187 MultiLine
*meta
= new MultiLine
;
190 // Generate the incoming texture var.
193 Var
*inPos
= (Var
*)LangElement::find( "inPosition" );
195 inPos
= (Var
*)LangElement::find( "position" );
197 inTex
= new Var( "texCoord", "vec3" );
199 Var
*oneOverTerrainSize
= _getUniformVar( "oneOverTerrainSize", "float", cspPass
);
201 // NOTE: The y coord here should be negative to have
202 // the texture maps not end up flipped which also caused
203 // normal and parallax mapping to be incorrect.
205 // This mistake early in development means that the layer
206 // id bilinear blend depends on it being that way.
208 // So instead i fixed this by flipping the base and detail
209 // coord y scale to compensate when rendering.
211 meta
->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n",
212 new DecOp( inTex
), inPos
, oneOverTerrainSize
, oneOverTerrainSize
, oneOverTerrainSize
) );
215 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
217 // Pass the texture coord to the pixel shader.
218 Var
*outTex
= connectComp
->getElement( RT_TEXCOORD
);
219 outTex
->setName( "outTexCoord" );
220 outTex
->setStructName( "OUT" );
221 outTex
->setType( "vec3" );
222 outTex
->mapsToSampler
= true;
223 meta
->addStatement( new GenOp( " @.xy = @.xy;\r\n", outTex
, inTex
) );
225 // If this shader has a side projected layer then we
226 // pass the dot product between the +Y and the normal
227 // thru outTexCoord.z for use in blending the textures.
228 if ( fd
.features
.hasFeature( MFT_TerrainSideProject
) )
230 Var
*inNormal
= (Var
*)LangElement::find( "normal" );
232 new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n",
233 outTex
, inNormal
, inNormal
) );
236 meta
->addStatement( new GenOp( " @.z = 0;\r\n", outTex
) );
238 // HACK: This is sort of lazy... we generate the tanget
239 // vector here so that we're sure it exists in the parallax
240 // and normal features which will expect "T" to exist.
242 // If this shader doesn't use it the shader compiler will
243 // optimize away this code.
245 Var
*inTangentZ
= getVertTexCoord( "tcTangentZ" );
246 Var
*inTanget
= new Var( "T", "vec3" );
247 Var
*squareSize
= _getUniformVar( "squareSize", "float", cspPass
);
248 meta
->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n",
249 new DecOp( inTanget
), squareSize
, inTangentZ
) );
252 void TerrainBaseMapFeatGLSL::processPix( Vector
<ShaderComponent
*> &componentList
,
253 const MaterialFeatureData
&fd
)
255 // grab connector texcoord register
256 Var
*texCoord
= getInTexCoord( "texCoord", "vec3", true, componentList
);
258 // create texture var
259 Var
*diffuseMap
= new Var
;
260 diffuseMap
->setType( "sampler2D" );
261 diffuseMap
->setName( "baseTexMap" );
262 diffuseMap
->uniform
= true;
263 diffuseMap
->sampler
= true;
264 diffuseMap
->constNum
= Var::getTexUnitNum(); // used as texture unit num here
266 MultiLine
*meta
= new MultiLine
;
268 Var
*baseColor
= new Var
;
269 baseColor
->setType( "vec4" );
270 baseColor
->setName( "baseColor" );
271 meta
->addStatement( new GenOp( " @ = tex2D( @, @.xy );\r\n", new DecOp( baseColor
), diffuseMap
, texCoord
) );
272 meta
->addStatement(new GenOp(" @ = toLinear(@);\r\n", baseColor
, baseColor
));
274 ShaderFeature::OutputTarget target
= ShaderFeature::DefaultTarget
;
276 if(fd
.features
.hasFeature(MFT_isDeferred
))
278 target
= ShaderFeature::RenderTarget1
;
280 meta
->addStatement( new GenOp( " @;\r\n", assignColor( baseColor
, Material::Mul
,NULL
,target
) ) );
285 ShaderFeature::Resources
TerrainBaseMapFeatGLSL::getResources( const MaterialFeatureData
&fd
)
294 U32
TerrainBaseMapFeatGLSL::getOutputTargets( const MaterialFeatureData
&fd
) const
296 return fd
.features
[MFT_isDeferred
] ? ShaderFeature::RenderTarget1
: ShaderFeature::DefaultTarget
;
299 TerrainDetailMapFeatGLSL::TerrainDetailMapFeatGLSL()
300 : mTorqueDep( "shaders/common/gl/torque.glsl" ),
301 mTerrainDep( "shaders/common/terrain/terrain.glsl" )
304 addDependency( &mTorqueDep
);
305 addDependency( &mTerrainDep
);
308 void TerrainDetailMapFeatGLSL::processVert( Vector
<ShaderComponent
*> &componentList
,
309 const MaterialFeatureData
&fd
)
311 const S32 detailIndex
= getProcessIndex();
313 // Grab incoming texture coords... the base map feature
314 // made sure this was created.
315 Var
*inTex
= (Var
*)LangElement::find( "texCoord" );
316 AssertFatal( inTex
, "The texture coord is missing!" );
318 // Grab the input position.
319 Var
*inPos
= (Var
*)LangElement::find( "inPosition" );
321 inPos
= (Var
*)LangElement::find( "position" );
323 // Get the object space eye position.
324 Var
*eyePos
= _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive
);
326 MultiLine
*meta
= new MultiLine
;
328 // If we have parallax mapping then make sure we've sent
329 // the negative view vector to the pixel shader.
330 if ( fd
.features
.hasFeature( MFT_TerrainParallaxMap
) &&
331 !LangElement::find( "outNegViewTS" ) )
333 // Get the object to tangent transform which
334 // will consume 3 output registers.
335 Var
*objToTangentSpace
= getOutObjToTangentSpace( componentList
, meta
, fd
);
337 // Now use a single output register to send the negative
338 // view vector in tangent space to the pixel shader.
339 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
340 Var
*outNegViewTS
= connectComp
->getElement( RT_TEXCOORD
);
341 outNegViewTS
->setName( "outNegViewTS" );
342 outNegViewTS
->setStructName( "OUT" );
343 outNegViewTS
->setType( "vec3" );
344 meta
->addStatement( new GenOp( " @ = tMul( @, float3( @ - @.xyz ) );\r\n",
345 outNegViewTS
, objToTangentSpace
, eyePos
, inPos
) );
348 // Get the distance from the eye to this vertex.
349 Var
*dist
= (Var
*)LangElement::find( "dist" );
353 dist
->setType( "float" );
354 dist
->setName( "dist" );
356 meta
->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
357 new DecOp( dist
), inPos
, eyePos
) );
360 // grab connector texcoord register
361 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
362 Var
*outTex
= connectComp
->getElement( RT_TEXCOORD
);
363 outTex
->setName( String::ToString( "detCoord%d", detailIndex
) );
364 outTex
->setStructName( "OUT" );
365 outTex
->setType( "vec4" );
366 outTex
->mapsToSampler
= true;
368 // Get the detail scale and fade info.
369 Var
*detScaleAndFade
= new Var
;
370 detScaleAndFade
->setType( "vec4" );
371 detScaleAndFade
->setName( String::ToString( "detailScaleAndFade%d", detailIndex
) );
372 detScaleAndFade
->uniform
= true;
373 detScaleAndFade
->constSortPos
= cspPotentialPrimitive
;
375 // Setup the detail coord.
377 // NOTE: You see here we scale the texture coord by 'xyx'
378 // to generate the detail coord. This y is here because
379 // its scale is flipped to correct for the non negative y
382 // See TerrainBaseMapFeatGLSL::processVert().
384 meta
->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex
, inTex
, detScaleAndFade
) );
386 // And sneak the detail fade thru the w detailCoord.
387 meta
->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
388 outTex
, detScaleAndFade
, dist
, detScaleAndFade
) );
393 void TerrainDetailMapFeatGLSL::processPix( Vector
<ShaderComponent
*> &componentList
,
394 const MaterialFeatureData
&fd
)
396 const S32 detailIndex
= getProcessIndex();
397 Var
*inTex
= getVertTexCoord( "texCoord" );
400 bool hasNormal
= fd
.features
.hasFeature(MFT_TerrainNormalMap
, detailIndex
);
402 MultiLine
*meta
= new MultiLine
;
404 // We need the negative tangent space view vector
405 // as in parallax mapping we step towards the camera.
406 Var
*negViewTS
= (Var
*)LangElement::find( "negViewTS" );
408 fd
.features
.hasFeature( MFT_TerrainParallaxMap
) )
410 Var
*inNegViewTS
= (Var
*)LangElement::find( "outNegViewTS" );
413 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
414 inNegViewTS
= connectComp
->getElement( RT_TEXCOORD
);
415 inNegViewTS
->setName( "outNegViewTS" );
416 inNegViewTS
->setStructName( "IN" );
417 inNegViewTS
->setType( "vec3" );
420 negViewTS
= new Var( "negViewTS", "vec3" );
421 meta
->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS
), inNegViewTS
) );
424 // Get the layer samples.
425 Var
*layerSample
= (Var
*)LangElement::find( "layerSample" );
428 layerSample
= new Var
;
429 layerSample
->setType( "vec4" );
430 layerSample
->setName( "layerSample" );
432 // Get the layer texture var
433 Var
*layerTex
= new Var
;
434 layerTex
->setType( "sampler2D" );
435 layerTex
->setName( "layerTex" );
436 layerTex
->uniform
= true;
437 layerTex
->sampler
= true;
438 layerTex
->constNum
= Var::getTexUnitNum();
440 // Read the layer texture to get the samples.
441 meta
->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
442 new DecOp( layerSample
), layerTex
, inTex
) );
445 Var
*layerSize
= (Var
*)LangElement::find( "layerSize" );
449 layerSize
->setType( "float" );
450 layerSize
->setName( "layerSize" );
451 layerSize
->uniform
= true;
452 layerSize
->constSortPos
= cspPass
;
455 // Grab the incoming detail coord.
456 Var
*inDet
= _getInDetailCoord( componentList
);
458 // Get the detail id.
459 Var
*detailInfo
= _getDetailIdStrengthParallax();
461 // Create the detail blend var.
462 Var
*detailBlend
= new Var
;
463 detailBlend
->setType( "float" );
464 detailBlend
->setName( String::ToString( "detailBlend%d", detailIndex
) );
466 // Calculate the blend for this detail texture.
467 meta
->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
468 new DecOp( detailBlend
), detailInfo
, inTex
, layerSize
, layerSample
) );
472 Var
*lerpBlend
= (Var
*)LangElement::find("lerpBlend");
476 lerpBlend
->setType("float");
477 lerpBlend
->setName("lerpBlend");
478 lerpBlend
->uniform
= true;
479 lerpBlend
->constSortPos
= cspPrimitive
;
483 Var
*blendDepth
= (Var
*)LangElement::find(String::ToString("blendDepth%d", detailIndex
));
486 blendDepth
= new Var
;
487 blendDepth
->setType("float");
488 blendDepth
->setName(String::ToString("blendDepth%d", detailIndex
));
489 blendDepth
->uniform
= true;
490 blendDepth
->constSortPos
= cspPrimitive
;
493 Var
*baseColor
= (Var
*)LangElement::find("baseColor");
494 ShaderFeature::OutputTarget target
= ShaderFeature::DefaultTarget
;
496 if(fd
.features
.hasFeature( MFT_DeferredTerrainDetailMap
))
497 target
= ShaderFeature::RenderTarget1
;
499 Var
*outColor
= (Var
*)LangElement::find( getOutputTargetVarName(target
) );
505 outColor
->setType("float4");
506 outColor
->setName("col");
507 outColor
->setStructName("OUT");
508 meta
->addStatement(new GenOp(" @;\r\n", outColor
));
511 Var
*detailColor
= (Var
*)LangElement::find("detailColor");
514 detailColor
= new Var
;
515 detailColor
->setType("float4");
516 detailColor
->setName("detailColor");
517 meta
->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor
)));
520 // Get the detail texture.
521 Var
*detailMap
= new Var
;
522 detailMap
->setType("sampler2D");
523 detailMap
->setName(String::ToString("detailMap%d", detailIndex
));
524 detailMap
->uniform
= true;
525 detailMap
->sampler
= true;
526 detailMap
->constNum
= Var::getTexUnitNum(); // used as texture unit num here
528 // Get the normal map texture.
529 Var
*normalMap
= _getNormalMapTex();
531 // Issue happens somewhere here -----
533 // Sample the normal map.
535 // We take two normal samples and lerp between them for
536 // side projection layers... else a single sample.
539 // Note that we're doing the standard greyscale detail
540 // map technique here which can darken and lighten the
543 // We take two color samples and lerp between them for
544 // side projection layers... else a single sample.
546 if (fd
.features
.hasFeature(MFT_TerrainSideProject
, detailIndex
))
548 meta
->addStatement(new GenOp(" @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
549 detailColor
, detailMap
, inDet
, detailMap
, inDet
, inTex
));
551 texOp
= new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
552 normalMap
, inDet
, normalMap
, inDet
, inTex
);
556 meta
->addStatement(new GenOp(" @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
557 detailColor
, detailMap
, inDet
));
559 texOp
= new GenOp("tex2D(@, @.xy)", normalMap
, inDet
);
564 // Get a var and accumulate the blend amount.
565 Var
*blendTotal
= (Var
*)LangElement::find( "blendTotal" );
568 blendTotal
= new Var
;
569 blendTotal
->setName( "blendTotal" );
570 blendTotal
->setType( "float" );
571 meta
->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal
) ) );
574 // Add to the blend total.
575 meta
->addStatement( new GenOp( " @ += @;\r\n", blendTotal
, detailBlend
) );
577 // If we had a parallax feature... then factor in the parallax
578 // amount so that it fades out with the layer blending.
579 if ( fd
.features
.hasFeature( MFT_TerrainParallaxMap
, detailIndex
) )
581 // Get the rest of our inputs.
582 Var
*normalMap
= _getNormalMapTex();
584 // Call the library function to do the rest.
585 if (fd
.features
.hasFeature(MFT_IsDXTnm
, detailIndex
))
587 meta
->addStatement(new GenOp(" @.xy += parallaxOffsetDxtnm( @, @.xy, @, @.z * @ );\r\n",
588 inDet
, normalMap
, inDet
, negViewTS
, detailInfo
, detailBlend
));
592 meta
->addStatement(new GenOp(" @.xy += parallaxOffset( @, @.xy, @, @.z * @ );\r\n",
593 inDet
, normalMap
, inDet
, negViewTS
, detailInfo
, detailBlend
));
597 // If we're using SM 3.0 then take advantage of
598 // dynamic branching to skip layers per-pixel.
601 if ( GFX
->getPixelShaderVersion() >= 3.0f
)
602 meta
->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend
) );
604 meta
->addStatement( new GenOp( " {\r\n" ) );
606 // Note that we're doing the standard greyscale detail
607 // map technique here which can darken and lighten the
610 // We take two color samples and lerp between them for
611 // side projection layers... else a single sample.
613 if ( fd
.features
.hasFeature( MFT_TerrainSideProject
, detailIndex
) )
615 meta
->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
616 detailColor
, detailMap
, inDet
, detailMap
, inDet
, inTex
) );
620 meta
->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
621 detailColor
, detailMap
, inDet
) );
624 meta
->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
625 detailColor
, detailInfo
, inDet
) );
627 meta
->addStatement( new GenOp( " @ += @ * @;\r\n",
628 outColor
, detailColor
, detailBlend
));
630 meta
->addStatement( new GenOp( " }\r\n" ) );
635 ShaderFeature::Resources
TerrainDetailMapFeatGLSL::getResources( const MaterialFeatureData
&fd
)
639 if ( getProcessIndex() == 0 )
641 // If this is the first detail pass then we
642 // samples from the layer tex.
645 // If this material also does parallax then it
646 // will generate the negative view vector and the
647 // worldToTanget transform.
648 if ( fd
.features
.hasFeature( MFT_TerrainParallaxMap
) )
652 // sample from the detail texture for diffuse coloring.
655 // If we have parallax for this layer then we'll also
656 // be sampling the normal map for the parallax heightmap.
657 if ( fd
.features
.hasFeature( MFT_TerrainParallaxMap
, getProcessIndex() ) )
660 // Finally we always send the detail texture
661 // coord to the pixel shader.
667 U32
TerrainDetailMapFeatGLSL::getOutputTargets( const MaterialFeatureData
&fd
) const
669 return fd
.features
[MFT_DeferredTerrainDetailMap
] ? ShaderFeature::RenderTarget1
: ShaderFeature::DefaultTarget
;
673 TerrainMacroMapFeatGLSL::TerrainMacroMapFeatGLSL()
674 : mTorqueDep( "shaders/common/gl/torque.glsl" ),
675 mTerrainDep( "shaders/common/terrain/terrain.glsl" )
678 addDependency( &mTorqueDep
);
679 addDependency( &mTerrainDep
);
683 void TerrainMacroMapFeatGLSL::processVert( Vector
<ShaderComponent
*> &componentList
,
684 const MaterialFeatureData
&fd
)
686 const S32 detailIndex
= getProcessIndex();
688 // Grab incoming texture coords... the base map feature
689 // made sure this was created.
690 Var
*inTex
= (Var
*)LangElement::find( "texCoord" );
691 AssertFatal( inTex
, "The texture coord is missing!" );
693 // Grab the input position.
694 Var
*inPos
= (Var
*)LangElement::find( "inPosition" );
696 inPos
= (Var
*)LangElement::find( "position" );
698 // Get the object space eye position.
699 Var
*eyePos
= _getUniformVar( "eyePos", "vec3", cspPotentialPrimitive
);
701 MultiLine
*meta
= new MultiLine
;
703 // Get the distance from the eye to this vertex.
704 Var
*dist
= (Var
*)LangElement::find( "macroDist" );
708 dist
->setType( "float" );
709 dist
->setName( "macroDist" );
711 meta
->addStatement( new GenOp( " @ = distance( @.xyz, @ );\r\n",
712 new DecOp( dist
), inPos
, eyePos
) );
715 // grab connector texcoord register
716 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
717 Var
*outTex
= connectComp
->getElement( RT_TEXCOORD
);
718 outTex
->setName( String::ToString( "macroCoord%d", detailIndex
) );
719 outTex
->setStructName( "OUT" );
720 outTex
->setType( "vec4" );
721 outTex
->mapsToSampler
= true;
723 // Get the detail scale and fade info.
724 Var
*detScaleAndFade
= new Var
;
725 detScaleAndFade
->setType( "vec4" );
726 detScaleAndFade
->setName( String::ToString( "macroScaleAndFade%d", detailIndex
) );
727 detScaleAndFade
->uniform
= true;
728 detScaleAndFade
->constSortPos
= cspPotentialPrimitive
;
730 // Setup the detail coord.
731 meta
->addStatement( new GenOp( " @.xyz = @ * @.xyx;\r\n", outTex
, inTex
, detScaleAndFade
) );
733 // And sneak the detail fade thru the w detailCoord.
734 meta
->addStatement( new GenOp( " @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
735 outTex
, detScaleAndFade
, dist
, detScaleAndFade
) );
741 void TerrainMacroMapFeatGLSL::processPix( Vector
<ShaderComponent
*> &componentList
,
742 const MaterialFeatureData
&fd
)
744 const S32 detailIndex
= getProcessIndex();
745 Var
*inTex
= getVertTexCoord( "texCoord" );
747 MultiLine
*meta
= new MultiLine
;
749 // We need the negative tangent space view vector
750 // as in parallax mapping we step towards the camera.
751 Var
*negViewTS
= (Var
*)LangElement::find( "negViewTS" );
753 fd
.features
.hasFeature( MFT_TerrainParallaxMap
) )
755 Var
*inNegViewTS
= (Var
*)LangElement::find( "outNegViewTS" );
758 ShaderConnector
*connectComp
= dynamic_cast<ShaderConnector
*>( componentList
[C_CONNECTOR
] );
759 inNegViewTS
= connectComp
->getElement( RT_TEXCOORD
);
760 inNegViewTS
->setName( "outNegViewTS" );
761 inNegViewTS
->setStructName( "IN" );
762 inNegViewTS
->setType( "vec3" );
765 negViewTS
= new Var( "negViewTS", "vec3" );
766 meta
->addStatement( new GenOp( " @ = normalize( @ );\r\n", new DecOp( negViewTS
), inNegViewTS
) );
769 // Get the layer samples.
770 Var
*layerSample
= (Var
*)LangElement::find( "layerSample" );
773 layerSample
= new Var
;
774 layerSample
->setType( "vec4" );
775 layerSample
->setName( "layerSample" );
777 // Get the layer texture var
778 Var
*layerTex
= new Var
;
779 layerTex
->setType( "sampler2D" );
780 layerTex
->setName( "macrolayerTex" );
781 layerTex
->uniform
= true;
782 layerTex
->sampler
= true;
783 layerTex
->constNum
= Var::getTexUnitNum();
785 // Read the layer texture to get the samples.
786 meta
->addStatement( new GenOp( " @ = round( tex2D( @, @.xy ) * 255.0f );\r\n",
787 new DecOp( layerSample
), layerTex
, inTex
) );
790 Var
*layerSize
= (Var
*)LangElement::find( "layerSize" );
794 layerSize
->setType( "float" );
795 layerSize
->setName( "layerSize" );
796 layerSize
->uniform
= true;
797 layerSize
->constSortPos
= cspPass
;
800 // Grab the incoming detail coord.
801 Var
*inDet
= _getInMacroCoord( componentList
);
803 // Get the detail id.
804 Var
*detailInfo
= _getMacroIdStrengthParallax();
806 // Create the detail blend var.
807 Var
*detailBlend
= new Var
;
808 detailBlend
->setType( "float" );
809 detailBlend
->setName( String::ToString( "macroBlend%d", detailIndex
) );
811 // Calculate the blend for this detail texture.
812 meta
->addStatement( new GenOp( " @ = calcBlend( @.x, @.xy, @, @ );\r\n",
813 new DecOp( detailBlend
), detailInfo
, inTex
, layerSize
, layerSample
) );
815 // Get a var and accumulate the blend amount.
816 Var
*blendTotal
= (Var
*)LangElement::find( "blendTotal" );
819 blendTotal
= new Var
;
820 //blendTotal->setName( "blendTotal" );
821 blendTotal
->setName( "blendTotal" );
822 blendTotal
->setType( "float" );
823 meta
->addStatement( new GenOp( " @ = 0;\r\n", new DecOp( blendTotal
) ) );
826 // Add to the blend total.
827 meta
->addStatement( new GenOp( " @ += @;\r\n", blendTotal
, detailBlend
) );
829 Var
*detailColor
= (Var
*)LangElement::find( "macroColor" );
832 detailColor
= new Var
;
833 detailColor
->setType( "vec4" );
834 detailColor
->setName( "macroColor" );
835 meta
->addStatement( new GenOp( " @;\r\n", new DecOp( detailColor
) ) );
838 // Get the detail texture.
839 Var
*detailMap
= new Var
;
840 detailMap
->setType( "sampler2D" );
841 detailMap
->setName( String::ToString( "macroMap%d", detailIndex
) );
842 detailMap
->uniform
= true;
843 detailMap
->sampler
= true;
844 detailMap
->constNum
= Var::getTexUnitNum(); // used as texture unit num here
846 // If we're using SM 3.0 then take advantage of
847 // dynamic branching to skip layers per-pixel.
848 if ( GFX
->getPixelShaderVersion() >= 3.0f
)
849 meta
->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend
) );
851 meta
->addStatement( new GenOp( " {\r\n" ) );
853 // Note that we're doing the standard greyscale detail
854 // map technique here which can darken and lighten the
857 // We take two color samples and lerp between them for
858 // side projection layers... else a single sample.
860 if ( fd
.features
.hasFeature( MFT_TerrainSideProject
, detailIndex
) )
862 meta
->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;\r\n",
863 detailColor
, detailMap
, inDet
, detailMap
, inDet
, inTex
) );
867 meta
->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;\r\n",
868 detailColor
, detailMap
, inDet
) );
871 meta
->addStatement( new GenOp( " @ *= @.y * @.w;\r\n",
872 detailColor
, detailInfo
, inDet
) );
873 ShaderFeature::OutputTarget target
= ShaderFeature::DefaultTarget
;
875 if(fd
.features
.hasFeature(MFT_DeferredTerrainMacroMap
))
876 target
= ShaderFeature::RenderTarget1
;
878 Var
*outColor
= (Var
*)LangElement::find( getOutputTargetVarName(target
) );
880 meta
->addStatement(new GenOp(" @ += @ * @;\r\n",
881 outColor
, detailColor
, detailBlend
));
883 meta
->addStatement( new GenOp( " }\r\n" ) );
890 ShaderFeature::Resources
TerrainMacroMapFeatGLSL::getResources( const MaterialFeatureData
&fd
)
894 if ( getProcessIndex() == 0 )
896 // If this is the first detail pass then we
897 // samples from the layer tex.
903 // Finally we always send the detail texture
904 // coord to the pixel shader.
910 U32
TerrainMacroMapFeatGLSL::getOutputTargets( const MaterialFeatureData
&fd
) const
912 return fd
.features
[MFT_DeferredTerrainMacroMap
] ? ShaderFeature::RenderTarget1
: ShaderFeature::DefaultTarget
;
915 void TerrainNormalMapFeatGLSL::processVert( Vector
<ShaderComponent
*> &componentList
,
916 const MaterialFeatureData
&fd
)
918 // We only need to process normals during the prepass.
919 if ( !fd
.features
.hasFeature( MFT_PrePassConditioner
) )
922 MultiLine
*meta
= new MultiLine
;
924 // Make sure the world to tangent transform
925 // is created and available for the pixel shader.
926 getOutViewToTangent( componentList
, meta
, fd
);
931 void TerrainNormalMapFeatGLSL::processPix( Vector
<ShaderComponent
*> &componentList
,
932 const MaterialFeatureData
&fd
)
935 MultiLine
*meta
= new MultiLine
;
937 Var
*viewToTangent
= getInViewToTangent( componentList
);
939 // This var is read from GBufferConditionerGLSL and
940 // used in the prepass output.
941 Var
*gbNormal
= (Var
*)LangElement::find( "gbNormal" );
945 gbNormal
->setName( "gbNormal" );
946 gbNormal
->setType( "vec3" );
947 meta
->addStatement( new GenOp( " @ = tGetMatrix3Row(@, 2);\r\n", new DecOp( gbNormal
), viewToTangent
) );
950 const S32 normalIndex
= getProcessIndex();
952 Var
*detailBlend
= (Var
*)LangElement::find( String::ToString( "detailBlend%d", normalIndex
) );
953 AssertFatal( detailBlend
, "The detail blend is missing!" );
955 // If we're using SM 3.0 then take advantage of
956 // dynamic branching to skip layers per-pixel.
957 if ( GFX
->getPixelShaderVersion() >= 3.0f
)
958 meta
->addStatement( new GenOp( " if ( @ > 0.0f )\r\n", detailBlend
) );
960 meta
->addStatement( new GenOp( " {\r\n" ) );
962 // Get the normal map texture.
963 Var
*normalMap
= _getNormalMapTex();
965 /// Get the texture coord.
966 Var
*inDet
= _getInDetailCoord( componentList
);
967 Var
*inTex
= getVertTexCoord( "texCoord" );
969 // Sample the normal map.
971 // We take two normal samples and lerp between them for
972 // side projection layers... else a single sample.
974 if ( fd
.features
.hasFeature( MFT_TerrainSideProject
, normalIndex
) )
976 texOp
= new GenOp( "lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
977 normalMap
, inDet
, normalMap
, inDet
, inTex
);
980 texOp
= new GenOp( "tex2D(@, @.xy)", normalMap
, inDet
);
982 // create bump normal
983 Var
*bumpNorm
= new Var
;
984 bumpNorm
->setName( "bumpNormal" );
985 bumpNorm
->setType( "vec4" );
987 LangElement
*bumpNormDecl
= new DecOp( bumpNorm
);
988 meta
->addStatement( expandNormalMap( texOp
, bumpNormDecl
, bumpNorm
, fd
) );
990 // Normalize is done later...
991 // Note: The reverse mul order is intentional. Affine matrix.
992 meta
->addStatement( new GenOp( " @ = lerp( @, tMul( @.xyz, @ ), min( @, @.w ) );\r\n",
993 gbNormal
, gbNormal
, bumpNorm
, viewToTangent
, detailBlend
, inDet
) );
995 // End the conditional block.
996 meta
->addStatement( new GenOp( " }\r\n" ) );
998 // If this is the last normal map then we
999 // can test to see the total blend value
1000 // to see if we should clip the result.
1001 //if ( fd.features.getNextFeatureIndex( MFT_TerrainNormalMap, normalIndex ) == -1 )
1002 //meta->addStatement( new GenOp( " clip( @ - 0.0001f );\r\n", blendTotal ) );
1007 ShaderFeature::Resources
TerrainNormalMapFeatGLSL::getResources( const MaterialFeatureData
&fd
)
1011 // We only need to process normals during the prepass.
1012 if ( fd
.features
.hasFeature( MFT_PrePassConditioner
) )
1014 // If this is the first normal map and there
1015 // are no parallax features then we will
1016 // generate the worldToTanget transform.
1017 if ( !fd
.features
.hasFeature( MFT_TerrainParallaxMap
) &&
1018 ( getProcessIndex() == 0 || !fd
.features
.hasFeature( MFT_TerrainNormalMap
, getProcessIndex() - 1 ) ) )
1027 void TerrainLightMapFeatGLSL::processPix( Vector
<ShaderComponent
*> &componentList
,
1028 const MaterialFeatureData
&fd
)
1030 // grab connector texcoord register
1031 Var
*inTex
= (Var
*)LangElement::find( "texCoord" );
1035 // Get the lightmap texture.
1036 Var
*lightMap
= new Var
;
1037 lightMap
->setType( "sampler2D" );
1038 lightMap
->setName( "lightMapTex" );
1039 lightMap
->uniform
= true;
1040 lightMap
->sampler
= true;
1041 lightMap
->constNum
= Var::getTexUnitNum();
1043 MultiLine
*meta
= new MultiLine
;
1045 // Find or create the lightMask value which is read by
1046 // RTLighting to mask out the lights.
1048 // The first light is always the sunlight so we apply
1049 // the shadow mask to only the first channel.
1051 Var
*lightMask
= (Var
*)LangElement::find( "lightMask" );
1054 lightMask
= new Var( "lightMask", "vec4" );
1055 meta
->addStatement( new GenOp( " @ = vec4(1);\r\n", new DecOp( lightMask
) ) );
1058 meta
->addStatement( new GenOp( " @[0] = tex2D( @, @.xy ).r;\r\n", lightMask
, lightMap
, inTex
) );
1062 ShaderFeature::Resources
TerrainLightMapFeatGLSL::getResources( const MaterialFeatureData
&fd
)
1070 void TerrainAdditiveFeatGLSL::processPix( Vector
<ShaderComponent
*> &componentList
,
1071 const MaterialFeatureData
&fd
)
1074 if (fd
.features
[MFT_DeferredTerrainDetailMap
])
1075 color
= (Var
*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget1
) );
1077 color
= (Var
*) LangElement::find( getOutputTargetVarName(ShaderFeature::DefaultTarget
) );
1079 Var
*blendTotal
= (Var
*)LangElement::find( "blendTotal" );
1080 if ( !color
|| !blendTotal
)
1083 MultiLine
*meta
= new MultiLine
;
1085 meta
->addStatement( new GenOp( " clip( @ - 0.0001 );\r\n", blendTotal
) );
1086 meta
->addStatement( new GenOp( " @.a = @;\r\n", color
, blendTotal
) );
1091 //standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
1092 //.b = specular strength, a= spec power.
1093 //here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
1094 //we'll most likely revisit that later. possibly several ways...
1096 U32
TerrainBlankInfoMapFeatGLSL::getOutputTargets(const MaterialFeatureData
&fd
) const
1098 return fd
.features
[MFT_isDeferred
] ? ShaderFeature::RenderTarget2
: ShaderFeature::RenderTarget1
;
1101 void TerrainBlankInfoMapFeatGLSL::processPix(Vector
<ShaderComponent
*> &componentList
,
1102 const MaterialFeatureData
&fd
)
1104 // search for material var
1106 OutputTarget targ
= RenderTarget1
;
1107 if (fd
.features
[MFT_isDeferred
])
1109 targ
= RenderTarget2
;
1111 material
= (Var
*)LangElement::find(getOutputTargetVarName(targ
));
1113 MultiLine
* meta
= new MultiLine
;
1118 material
->setType("vec4");
1119 material
->setName(getOutputTargetVarName(targ
));
1120 material
->setStructName("OUT");
1123 meta
->addStatement(new GenOp(" @ = float4(0.0,0.0,0.0,0.0001);\r\n", material
));