1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreTerrainMaterialGeneratorA.h" 29 #include "OgreTerrain.h" 30 #include "OgreMaterialManager.h" 31 #include "OgreTechnique.h" 32 #include "OgrePass.h" 33 #include "OgreTextureUnitState.h" 34 #include "OgreGpuProgramManager.h" 35 #include "OgreHighLevelGpuProgramManager.h" 36 #include "OgreHardwarePixelBuffer.h" 37 #include "OgreShadowCameraSetupPSSM.h" 38 39 namespace Ogre 40 { 41 //--------------------------------------------------------------------- TerrainMaterialGeneratorA()42 TerrainMaterialGeneratorA::TerrainMaterialGeneratorA() 43 { 44 // define the layers 45 // We expect terrain textures to have no alpha, so we use the alpha channel 46 // in the albedo texture to store specular reflection 47 // similarly we double-up the normal and height (for parallax) 48 mLayerDecl.samplers.push_back(TerrainLayerSampler("albedo_specular", PF_BYTE_RGBA)); 49 mLayerDecl.samplers.push_back(TerrainLayerSampler("normal_height", PF_BYTE_RGBA)); 50 51 mLayerDecl.elements.push_back( 52 TerrainLayerSamplerElement(0, TLSS_ALBEDO, 0, 3)); 53 mLayerDecl.elements.push_back( 54 TerrainLayerSamplerElement(0, TLSS_SPECULAR, 3, 1)); 55 mLayerDecl.elements.push_back( 56 TerrainLayerSamplerElement(1, TLSS_NORMAL, 0, 3)); 57 mLayerDecl.elements.push_back( 58 TerrainLayerSamplerElement(1, TLSS_HEIGHT, 3, 1)); 59 60 61 mProfiles.push_back(OGRE_NEW SM2Profile(this, "SM2", "Profile for rendering on Shader Model 2 capable cards")); 62 // TODO - check hardware capabilities & use fallbacks if required (more profiles needed) 63 setActiveProfile("SM2"); 64 65 } 66 //--------------------------------------------------------------------- ~TerrainMaterialGeneratorA()67 TerrainMaterialGeneratorA::~TerrainMaterialGeneratorA() 68 { 69 70 } 71 //--------------------------------------------------------------------- 72 //--------------------------------------------------------------------- SM2Profile(TerrainMaterialGenerator * parent,const String & name,const String & desc)73 TerrainMaterialGeneratorA::SM2Profile::SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc) 74 : Profile(parent, name, desc) 75 , mShaderGen(0) 76 , mLayerNormalMappingEnabled(true) 77 , mLayerParallaxMappingEnabled(true) 78 , mLayerSpecularMappingEnabled(true) 79 , mGlobalColourMapEnabled(true) 80 , mLightmapEnabled(true) 81 , mCompositeMapEnabled(true) 82 , mReceiveDynamicShadows(true) 83 , mPSSM(0) 84 , mDepthShadows(false) 85 , mLowLodShadows(false) 86 , mSM3Available(false) 87 , mSM4Available(false) 88 { 89 HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton(); 90 if (hmgr.isLanguageSupported("cg")) 91 { 92 mShaderLanguage = "cg"; 93 } 94 else if (hmgr.isLanguageSupported("hlsl")) 95 { 96 mShaderLanguage = "hlsl"; 97 } 98 else if (hmgr.isLanguageSupported("glsl")) 99 { 100 mShaderLanguage = "glsl"; 101 } 102 else if (hmgr.isLanguageSupported("glsles")) 103 { 104 mShaderLanguage = "glsles"; 105 } 106 else 107 { 108 // todo 109 } 110 } 111 //--------------------------------------------------------------------- ~SM2Profile()112 TerrainMaterialGeneratorA::SM2Profile::~SM2Profile() 113 { 114 OGRE_DELETE mShaderGen; 115 } 116 //--------------------------------------------------------------------- requestOptions(Terrain * terrain)117 void TerrainMaterialGeneratorA::SM2Profile::requestOptions(Terrain* terrain) 118 { 119 terrain->_setMorphRequired(true); 120 terrain->_setNormalMapRequired(true); 121 terrain->_setLightMapRequired(mLightmapEnabled, true); 122 terrain->_setCompositeMapRequired(mCompositeMapEnabled); 123 } 124 //--------------------------------------------------------------------- isVertexCompressionSupported() const125 bool TerrainMaterialGeneratorA::SM2Profile::isVertexCompressionSupported() const 126 { 127 // FIXME: Not supporting compression on GLSL at the moment 128 if ((mShaderLanguage == "glsl") || (mShaderLanguage == "glsles")) 129 return false; 130 else 131 return true; 132 } 133 //--------------------------------------------------------------------- setLayerNormalMappingEnabled(bool enabled)134 void TerrainMaterialGeneratorA::SM2Profile::setLayerNormalMappingEnabled(bool enabled) 135 { 136 if (enabled != mLayerNormalMappingEnabled) 137 { 138 mLayerNormalMappingEnabled = enabled; 139 mParent->_markChanged(); 140 } 141 } 142 //--------------------------------------------------------------------- setLayerParallaxMappingEnabled(bool enabled)143 void TerrainMaterialGeneratorA::SM2Profile::setLayerParallaxMappingEnabled(bool enabled) 144 { 145 if (enabled != mLayerParallaxMappingEnabled) 146 { 147 mLayerParallaxMappingEnabled = enabled; 148 mParent->_markChanged(); 149 } 150 } 151 //--------------------------------------------------------------------- setLayerSpecularMappingEnabled(bool enabled)152 void TerrainMaterialGeneratorA::SM2Profile::setLayerSpecularMappingEnabled(bool enabled) 153 { 154 if (enabled != mLayerSpecularMappingEnabled) 155 { 156 mLayerSpecularMappingEnabled = enabled; 157 mParent->_markChanged(); 158 } 159 } 160 //--------------------------------------------------------------------- setGlobalColourMapEnabled(bool enabled)161 void TerrainMaterialGeneratorA::SM2Profile::setGlobalColourMapEnabled(bool enabled) 162 { 163 if (enabled != mGlobalColourMapEnabled) 164 { 165 mGlobalColourMapEnabled = enabled; 166 mParent->_markChanged(); 167 } 168 } 169 //--------------------------------------------------------------------- setLightmapEnabled(bool enabled)170 void TerrainMaterialGeneratorA::SM2Profile::setLightmapEnabled(bool enabled) 171 { 172 if (enabled != mLightmapEnabled) 173 { 174 mLightmapEnabled = enabled; 175 mParent->_markChanged(); 176 } 177 } 178 //--------------------------------------------------------------------- setCompositeMapEnabled(bool enabled)179 void TerrainMaterialGeneratorA::SM2Profile::setCompositeMapEnabled(bool enabled) 180 { 181 if (enabled != mCompositeMapEnabled) 182 { 183 mCompositeMapEnabled = enabled; 184 mParent->_markChanged(); 185 } 186 } 187 //--------------------------------------------------------------------- setReceiveDynamicShadowsEnabled(bool enabled)188 void TerrainMaterialGeneratorA::SM2Profile::setReceiveDynamicShadowsEnabled(bool enabled) 189 { 190 if (enabled != mReceiveDynamicShadows) 191 { 192 mReceiveDynamicShadows = enabled; 193 mParent->_markChanged(); 194 } 195 } 196 //--------------------------------------------------------------------- setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup * pssmSettings)197 void TerrainMaterialGeneratorA::SM2Profile::setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings) 198 { 199 if (pssmSettings != mPSSM) 200 { 201 mPSSM = pssmSettings; 202 mParent->_markChanged(); 203 } 204 } 205 //--------------------------------------------------------------------- setReceiveDynamicShadowsDepth(bool enabled)206 void TerrainMaterialGeneratorA::SM2Profile::setReceiveDynamicShadowsDepth(bool enabled) 207 { 208 if (enabled != mDepthShadows) 209 { 210 mDepthShadows = enabled; 211 mParent->_markChanged(); 212 } 213 214 } 215 //--------------------------------------------------------------------- setReceiveDynamicShadowsLowLod(bool enabled)216 void TerrainMaterialGeneratorA::SM2Profile::setReceiveDynamicShadowsLowLod(bool enabled) 217 { 218 if (enabled != mLowLodShadows) 219 { 220 mLowLodShadows = enabled; 221 mParent->_markChanged(); 222 } 223 } 224 //--------------------------------------------------------------------- getMaxLayers(const Terrain * terrain) const225 uint8 TerrainMaterialGeneratorA::SM2Profile::getMaxLayers(const Terrain* terrain) const 226 { 227 // count the texture units free 228 uint8 freeTextureUnits = 16; 229 // lightmap 230 --freeTextureUnits; 231 // normalmap 232 --freeTextureUnits; 233 // colourmap 234 if (terrain->getGlobalColourMapEnabled()) 235 --freeTextureUnits; 236 if (isShadowingEnabled(HIGH_LOD, terrain)) 237 { 238 uint8 numShadowTextures = 1; 239 if (getReceiveDynamicShadowsPSSM()) 240 { 241 numShadowTextures = (uint8)getReceiveDynamicShadowsPSSM()->getSplitCount(); 242 } 243 freeTextureUnits -= numShadowTextures; 244 } 245 246 // each layer needs 2.25 units (1xdiffusespec, 1xnormalheight, 0.25xblend) 247 return static_cast<uint8>(freeTextureUnits / 2.25f); 248 249 250 } 251 //--------------------------------------------------------------------- generate(const Terrain * terrain)252 MaterialPtr TerrainMaterialGeneratorA::SM2Profile::generate(const Terrain* terrain) 253 { 254 // re-use old material if exists 255 MaterialPtr mat = terrain->_getMaterial(); 256 if (mat.isNull()) 257 { 258 MaterialManager& matMgr = MaterialManager::getSingleton(); 259 260 // it's important that the names are deterministic for a given terrain, so 261 // use the terrain pointer as an ID 262 const String& matName = terrain->getMaterialName(); 263 mat = matMgr.getByName(matName); 264 if (mat.isNull()) 265 { 266 mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); 267 } 268 } 269 // clear everything 270 mat->removeAllTechniques(); 271 272 // Automatically disable normal & parallax mapping if card cannot handle it 273 // We do this rather than having a specific technique for it since it's simpler 274 GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); 275 if (!gmgr.isSyntaxSupported("ps_4_0") && !gmgr.isSyntaxSupported("ps_3_0") && !gmgr.isSyntaxSupported("ps_2_x") 276 && !gmgr.isSyntaxSupported("fp40") && !gmgr.isSyntaxSupported("arbfp1") && !gmgr.isSyntaxSupported("glsl") 277 && !gmgr.isSyntaxSupported("glsles")) 278 { 279 setLayerNormalMappingEnabled(false); 280 setLayerParallaxMappingEnabled(false); 281 } 282 283 addTechnique(mat, terrain, HIGH_LOD); 284 285 // LOD 286 if(mCompositeMapEnabled) 287 { 288 addTechnique(mat, terrain, LOW_LOD); 289 Material::LodValueList lodValues; 290 lodValues.push_back(TerrainGlobalOptions::getSingleton().getCompositeMapDistance()); 291 mat->setLodLevels(lodValues); 292 Technique* lowLodTechnique = mat->getTechnique(1); 293 lowLodTechnique->setLodIndex(1); 294 } 295 296 updateParams(mat, terrain); 297 298 return mat; 299 300 } 301 //--------------------------------------------------------------------- generateForCompositeMap(const Terrain * terrain)302 MaterialPtr TerrainMaterialGeneratorA::SM2Profile::generateForCompositeMap(const Terrain* terrain) 303 { 304 // re-use old material if exists 305 MaterialPtr mat = terrain->_getCompositeMapMaterial(); 306 if (mat.isNull()) 307 { 308 MaterialManager& matMgr = MaterialManager::getSingleton(); 309 310 // it's important that the names are deterministic for a given terrain, so 311 // use the terrain pointer as an ID 312 const String& matName = terrain->getMaterialName() + "/comp"; 313 mat = matMgr.getByName(matName); 314 if (mat.isNull()) 315 { 316 mat = matMgr.create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); 317 } 318 } 319 // clear everything 320 mat->removeAllTechniques(); 321 322 addTechnique(mat, terrain, RENDER_COMPOSITE_MAP); 323 324 updateParamsForCompositeMap(mat, terrain); 325 326 return mat; 327 328 } 329 //--------------------------------------------------------------------- addTechnique(const MaterialPtr & mat,const Terrain * terrain,TechniqueType tt)330 void TerrainMaterialGeneratorA::SM2Profile::addTechnique( 331 const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt) 332 { 333 Technique* tech = mat->createTechnique(); 334 335 // Only supporting one pass 336 Pass* pass = tech->createPass(); 337 338 GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); 339 HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton(); 340 if (!mShaderGen) 341 { 342 bool check2x = mLayerNormalMappingEnabled || mLayerParallaxMappingEnabled; 343 if (hmgr.isLanguageSupported("cg")) 344 { 345 mShaderGen = OGRE_NEW ShaderHelperCg(); 346 } 347 else if (hmgr.isLanguageSupported("hlsl") && 348 ((check2x && gmgr.isSyntaxSupported("ps_4_0")) || 349 (check2x && gmgr.isSyntaxSupported("ps_2_x")) || 350 (!check2x && gmgr.isSyntaxSupported("ps_2_0")))) 351 { 352 mShaderGen = OGRE_NEW ShaderHelperHLSL(); 353 } 354 else if (hmgr.isLanguageSupported("glsl")) 355 { 356 mShaderGen = OGRE_NEW ShaderHelperGLSL(); 357 } 358 else if (hmgr.isLanguageSupported("glsles")) 359 { 360 mShaderGen = OGRE_NEW ShaderHelperGLSLES(); 361 } 362 363 // check SM3 features 364 mSM3Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0"); 365 mSM4Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"); 366 } 367 368 HighLevelGpuProgramPtr vprog = mShaderGen->generateVertexProgram(this, terrain, tt); 369 HighLevelGpuProgramPtr fprog = mShaderGen->generateFragmentProgram(this, terrain, tt); 370 371 pass->setVertexProgram(vprog->getName()); 372 pass->setFragmentProgram(fprog->getName()); 373 374 if (tt == HIGH_LOD || tt == RENDER_COMPOSITE_MAP) 375 { 376 // global normal map 377 TextureUnitState* tu = pass->createTextureUnitState(); 378 tu->setTextureName(terrain->getTerrainNormalMap()->getName()); 379 tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); 380 381 // global colour map 382 if (terrain->getGlobalColourMapEnabled() && isGlobalColourMapEnabled()) 383 { 384 tu = pass->createTextureUnitState(terrain->getGlobalColourMap()->getName()); 385 tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); 386 } 387 388 // light map 389 if (isLightmapEnabled()) 390 { 391 tu = pass->createTextureUnitState(terrain->getLightmap()->getName()); 392 tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); 393 } 394 395 // blend maps 396 uint maxLayers = getMaxLayers(terrain); 397 uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); 398 uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); 399 for (uint i = 0; i < numBlendTextures; ++i) 400 { 401 tu = pass->createTextureUnitState(terrain->getBlendTextureName(i)); 402 tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); 403 } 404 405 // layer textures 406 for (uint i = 0; i < numLayers; ++i) 407 { 408 // diffuse / specular 409 pass->createTextureUnitState(terrain->getLayerTextureName(i, 0)); 410 // normal / height 411 pass->createTextureUnitState(terrain->getLayerTextureName(i, 1)); 412 } 413 414 } 415 else 416 { 417 // LOW_LOD textures 418 // composite map 419 TextureUnitState* tu = pass->createTextureUnitState(); 420 tu->setTextureName(terrain->getCompositeMap()->getName()); 421 tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); 422 423 // That's it! 424 425 } 426 427 // Add shadow textures (always at the end) 428 if (isShadowingEnabled(tt, terrain)) 429 { 430 uint numTextures = 1; 431 if (getReceiveDynamicShadowsPSSM()) 432 { 433 numTextures = (uint)getReceiveDynamicShadowsPSSM()->getSplitCount(); 434 } 435 for (uint i = 0; i < numTextures; ++i) 436 { 437 TextureUnitState* tu = pass->createTextureUnitState(); 438 tu->setContentType(TextureUnitState::CONTENT_SHADOW); 439 tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER); 440 tu->setTextureBorderColour(ColourValue::White); 441 } 442 } 443 444 } 445 //--------------------------------------------------------------------- isShadowingEnabled(TechniqueType tt,const Terrain * terrain) const446 bool TerrainMaterialGeneratorA::SM2Profile::isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const 447 { 448 return getReceiveDynamicShadowsEnabled() && tt != RENDER_COMPOSITE_MAP && 449 (tt != LOW_LOD || mLowLodShadows) && 450 terrain->getSceneManager()->isShadowTechniqueTextureBased(); 451 452 } 453 //--------------------------------------------------------------------- updateParams(const MaterialPtr & mat,const Terrain * terrain)454 void TerrainMaterialGeneratorA::SM2Profile::updateParams(const MaterialPtr& mat, const Terrain* terrain) 455 { 456 mShaderGen->updateParams(this, mat, terrain, false); 457 458 } 459 //--------------------------------------------------------------------- updateParamsForCompositeMap(const MaterialPtr & mat,const Terrain * terrain)460 void TerrainMaterialGeneratorA::SM2Profile::updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain) 461 { 462 mShaderGen->updateParams(this, mat, terrain, true); 463 } 464 //--------------------------------------------------------------------- 465 //--------------------------------------------------------------------- 466 HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt)467 TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::generateVertexProgram( 468 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) 469 { 470 HighLevelGpuProgramPtr ret = createVertexProgram(prof, terrain, tt); 471 472 StringUtil::StrStreamType sourceStr; 473 generateVertexProgramSource(prof, terrain, tt, sourceStr); 474 ret->setSource(sourceStr.str()); 475 ret->load(); 476 defaultVpParams(prof, terrain, tt, ret); 477 #if OGRE_DEBUG_MODE 478 LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Vertex Program: " 479 << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; 480 #endif 481 482 return ret; 483 484 } 485 //--------------------------------------------------------------------- 486 HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt)487 TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::generateFragmentProgram( 488 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) 489 { 490 HighLevelGpuProgramPtr ret = createFragmentProgram(prof, terrain, tt); 491 492 StringUtil::StrStreamType sourceStr; 493 generateFragmentProgramSource(prof, terrain, tt, sourceStr); 494 ret->setSource(sourceStr.str()); 495 ret->load(); 496 defaultFpParams(prof, terrain, tt, ret); 497 498 #if OGRE_DEBUG_MODE 499 LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Fragment Program: " 500 << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; 501 #endif 502 503 return ret; 504 } 505 //--------------------------------------------------------------------- generateVertexProgramSource(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt,StringUtil::StrStreamType & outStream)506 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::generateVertexProgramSource( 507 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) 508 { 509 generateVpHeader(prof, terrain, tt, outStream); 510 511 if (tt != LOW_LOD) 512 { 513 uint maxLayers = prof->getMaxLayers(terrain); 514 uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); 515 516 for (uint i = 0; i < numLayers; ++i) 517 generateVpLayer(prof, terrain, tt, i, outStream); 518 } 519 520 generateVpFooter(prof, terrain, tt, outStream); 521 522 } 523 //--------------------------------------------------------------------- generateFragmentProgramSource(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt,StringUtil::StrStreamType & outStream)524 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::generateFragmentProgramSource( 525 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) 526 { 527 generateFpHeader(prof, terrain, tt, outStream); 528 529 if (tt != LOW_LOD) 530 { 531 uint maxLayers = prof->getMaxLayers(terrain); 532 uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); 533 534 for (uint i = 0; i < numLayers; ++i) 535 generateFpLayer(prof, terrain, tt, i, outStream); 536 } 537 538 generateFpFooter(prof, terrain, tt, outStream); 539 } 540 //--------------------------------------------------------------------- defaultVpParams(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt,const HighLevelGpuProgramPtr & prog)541 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::defaultVpParams( 542 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog) 543 { 544 GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); 545 params->setIgnoreMissingParams(true); 546 params->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX); 547 params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX); 548 params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM, 549 Terrain::LOD_MORPH_CUSTOM_PARAM); 550 params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); 551 552 if (prof->isShadowingEnabled(tt, terrain)) 553 { 554 uint numTextures = 1; 555 if (prof->getReceiveDynamicShadowsPSSM()) 556 { 557 numTextures = (uint)prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); 558 } 559 for (uint i = 0; i < numTextures; ++i) 560 { 561 params->setNamedAutoConstant("texViewProjMatrix" + StringConverter::toString(i), 562 GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i); 563 if (prof->getReceiveDynamicShadowsDepth()) 564 { 565 params->setNamedAutoConstant("depthRange" + StringConverter::toString(i), 566 GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i); 567 } 568 } 569 } 570 571 if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP) 572 { 573 Matrix4 posIndexToObjectSpace; 574 terrain->getPointTransform(&posIndexToObjectSpace); 575 params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace); 576 } 577 578 579 580 } 581 //--------------------------------------------------------------------- defaultFpParams(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt,const HighLevelGpuProgramPtr & prog)582 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::defaultFpParams( 583 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog) 584 { 585 GpuProgramParametersSharedPtr params = prog->getDefaultParameters(); 586 params->setIgnoreMissingParams(true); 587 588 params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); 589 params->setNamedAutoConstant("lightPosObjSpace", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, 0); 590 params->setNamedAutoConstant("lightDiffuseColour", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0); 591 params->setNamedAutoConstant("lightSpecularColour", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0); 592 params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); 593 params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR); 594 595 if (prof->isShadowingEnabled(tt, terrain)) 596 { 597 uint numTextures = 1; 598 if (prof->getReceiveDynamicShadowsPSSM()) 599 { 600 PSSMShadowCameraSetup* pssm = prof->getReceiveDynamicShadowsPSSM(); 601 numTextures = (uint)pssm->getSplitCount(); 602 Vector4 splitPoints; 603 const PSSMShadowCameraSetup::SplitPointList& splitPointList = pssm->getSplitPoints(); 604 // Populate from split point 1, not 0, since split 0 isn't useful (usually 0) 605 for (uint i = 1; i < numTextures; ++i) 606 { 607 splitPoints[i-1] = splitPointList[i]; 608 } 609 params->setNamedConstant("pssmSplitPoints", splitPoints); 610 } 611 612 if (prof->getReceiveDynamicShadowsDepth()) 613 { 614 size_t samplerOffset = (tt == HIGH_LOD) ? mShadowSamplerStartHi : mShadowSamplerStartLo; 615 for (uint i = 0; i < numTextures; ++i) 616 { 617 params->setNamedAutoConstant("inverseShadowmapSize" + StringConverter::toString(i), 618 GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i + samplerOffset); 619 } 620 } 621 } 622 623 // Explicitly bind samplers for GLSL 624 if ((prof->_getShaderLanguage() == "glsl") || (prof->_getShaderLanguage() == "glsles")) 625 { 626 int numSamplers = 0; 627 if (tt == LOW_LOD) 628 { 629 params->setNamedConstant("compositeMap", (int)numSamplers++); 630 } 631 else 632 { 633 params->setNamedConstant("globalNormal", (int)numSamplers++); 634 635 if (terrain->getGlobalColourMapEnabled() && prof->isGlobalColourMapEnabled()) 636 { 637 params->setNamedConstant("globalColourMap", (int)numSamplers++); 638 } 639 if (prof->isLightmapEnabled()) 640 { 641 params->setNamedConstant("lightMap", (int)numSamplers++); 642 } 643 644 uint maxLayers = prof->getMaxLayers(terrain); 645 uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); 646 uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); 647 // Blend textures - sampler definitions 648 for (uint i = 0; i < numBlendTextures; ++i) 649 { 650 params->setNamedConstant("blendTex" + StringConverter::toString(i), (int)numSamplers++); 651 } 652 653 // Layer textures - sampler definitions & UV multipliers 654 for (uint i = 0; i < numLayers; ++i) 655 { 656 params->setNamedConstant("difftex" + StringConverter::toString(i), (int)numSamplers++); 657 params->setNamedConstant("normtex" + StringConverter::toString(i), (int)numSamplers++); 658 } 659 660 uint numShadowTextures = 1; 661 if (prof->getReceiveDynamicShadowsPSSM()) 662 numShadowTextures = (uint)prof->getReceiveDynamicShadowsPSSM()->getSplitCount(); 663 664 for (uint i = 0; i < numShadowTextures; ++i) 665 { 666 if (prof->isShadowingEnabled(tt, terrain)) 667 params->setNamedConstant("shadowMap" + StringConverter::toString(i), (int)numSamplers++); 668 } 669 } 670 } 671 } 672 //--------------------------------------------------------------------- updateParams(const SM2Profile * prof,const MaterialPtr & mat,const Terrain * terrain,bool compositeMap)673 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::updateParams( 674 const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap) 675 { 676 Pass* p = mat->getTechnique(0)->getPass(0); 677 if (compositeMap) 678 { 679 updateVpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getVertexProgramParameters()); 680 updateFpParams(prof, terrain, RENDER_COMPOSITE_MAP, p->getFragmentProgramParameters()); 681 } 682 else 683 { 684 // high lod 685 updateVpParams(prof, terrain, HIGH_LOD, p->getVertexProgramParameters()); 686 updateFpParams(prof, terrain, HIGH_LOD, p->getFragmentProgramParameters()); 687 688 if(prof->isCompositeMapEnabled()) 689 { 690 // low lod 691 p = mat->getTechnique(1)->getPass(0); 692 updateVpParams(prof, terrain, LOW_LOD, p->getVertexProgramParameters()); 693 updateFpParams(prof, terrain, LOW_LOD, p->getFragmentProgramParameters()); 694 } 695 } 696 } 697 //--------------------------------------------------------------------- updateVpParams(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt,const GpuProgramParametersSharedPtr & params)698 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::updateVpParams( 699 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params) 700 { 701 params->setIgnoreMissingParams(true); 702 uint maxLayers = prof->getMaxLayers(terrain); 703 uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); 704 uint numUVMul = numLayers / 4; 705 if (numLayers % 4) 706 ++numUVMul; 707 for (uint i = 0; i < numUVMul; ++i) 708 { 709 Vector4 uvMul( 710 terrain->getLayerUVMultiplier(i * 4), 711 terrain->getLayerUVMultiplier(i * 4 + 1), 712 terrain->getLayerUVMultiplier(i * 4 + 2), 713 terrain->getLayerUVMultiplier(i * 4 + 3) 714 ); 715 params->setNamedConstant("uvMul_" + StringConverter::toString(i), uvMul); 716 } 717 718 if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP) 719 { 720 Real baseUVScale = 1.0f / (terrain->getSize() - 1); 721 params->setNamedConstant("baseUVScale", baseUVScale); 722 } 723 724 } 725 //--------------------------------------------------------------------- updateFpParams(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt,const GpuProgramParametersSharedPtr & params)726 void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::updateFpParams( 727 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params) 728 { 729 params->setIgnoreMissingParams(true); 730 // TODO - parameterise this? 731 Vector4 scaleBiasSpecular(0.03, -0.04, 32, 1); 732 params->setNamedConstant("scaleBiasSpecular", scaleBiasSpecular); 733 734 } 735 //--------------------------------------------------------------------- getChannel(uint idx)736 String TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::getChannel(uint idx) 737 { 738 uint rem = idx % 4; 739 switch(rem) 740 { 741 case 0: 742 default: 743 return "r"; 744 case 1: 745 return "g"; 746 case 2: 747 return "b"; 748 case 3: 749 return "a"; 750 }; 751 } 752 //--------------------------------------------------------------------- getVertexProgramName(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt)753 String TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::getVertexProgramName( 754 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) 755 { 756 String progName = terrain->getMaterialName() + "/sm2/vp"; 757 758 switch(tt) 759 { 760 case HIGH_LOD: 761 progName += "/hlod"; 762 break; 763 case LOW_LOD: 764 progName += "/llod"; 765 break; 766 case RENDER_COMPOSITE_MAP: 767 progName += "/comp"; 768 break; 769 } 770 771 return progName; 772 773 } 774 //--------------------------------------------------------------------- getFragmentProgramName(const SM2Profile * prof,const Terrain * terrain,TechniqueType tt)775 String TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::getFragmentProgramName( 776 const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) 777 { 778 779 String progName = terrain->getMaterialName() + "/sm2/fp"; 780 781 switch(tt) 782 { 783 case HIGH_LOD: 784 progName += "/hlod"; 785 break; 786 case LOW_LOD: 787 progName += "/llod"; 788 break; 789 case RENDER_COMPOSITE_MAP: 790 progName += "/comp"; 791 break; 792 } 793 794 return progName; 795 } 796 } 797