summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonçalo Camelo Neves Pereira2018-08-06 21:19:04 +0100
committerGonçalo Camelo Neves Pereira2018-08-06 21:19:04 +0100
commit9071033e65f8723bf5a3b3e82601672c0541f750 (patch)
treeacdbc63395e4eb70d3810a81eaf0927e2389efbd
parentdaae4f81eec1bd040e31ce675a17816ec0cce482 (diff)
downloadaur-9071033e65f8723bf5a3b3e82601672c0541f750.tar.gz
Update to 9.3.0 and Fixed Issues
-rw-r--r--.SRCINFO13
-rw-r--r--PKGBUILD32
-rw-r--r--ogre-1.10.patch13
-rw-r--r--ogre-1.11.patch4725
4 files changed, 4747 insertions, 36 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 431e2496e2b..7e1c1f75c48 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,7 +1,7 @@
pkgbase = gazebo
pkgdesc = A multi-robot simulator for outdoor environments
- pkgver = 9.0.0
- pkgrel = 2
+ pkgver = 9.3.0
+ pkgrel = 1
url = http://gazebosim.org/
install = gazebo.install
arch = i686
@@ -9,7 +9,6 @@ pkgbase = gazebo
license = Apache
makedepends = cmake
makedepends = doxygen
- makedepends = pkgconf>=0.26
depends = boost>=1.40.0
depends = curl>=4.0
depends = freeglut
@@ -39,10 +38,10 @@ pkgbase = gazebo
optdepends = ruby-ronn: Generate manpages
optdepends = simbody: Simbody support
optdepends = urdfdom: Load URDF files
- source = http://osrf-distributions.s3.amazonaws.com/gazebo/releases/gazebo-9.0.0.tar.bz2
- source = ogre-1.10.patch
- sha256sums = 2c29955d476c97dc0ccbb1c8295ec6e8ffe203d7bc6047c1f34433a82ab9215e
- sha256sums = a1c8a9d181f3de6007361f571a40fd04e780081cd9a9a281d64d316e8cc89892
+ source = https://bitbucket.org/osrf/gazebo/get/gazebo9_9.3.0.tar.bz2
+ source = ogre-1.11.patch
+ sha256sums = ba1acb778b3360af883b5331ab639ebfea395ebceb9d1cd0aaed2bced041a0a5
+ sha256sums = 0544018a614fe6a4caf7554cb6c751fc1e1c82e8035a0c3ddb0178786955ce9a
pkgname = gazebo
diff --git a/PKGBUILD b/PKGBUILD
index 809d9e0bdb3..e654ec563b2 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -5,8 +5,8 @@
# Contributor: Vladimir Ermakov <vooon341@gmail.com>
pkgname=gazebo
-pkgver=9.0.0
-pkgrel=2
+pkgver=9.3.0
+pkgrel=1
pkgdesc="A multi-robot simulator for outdoor environments"
arch=('i686' 'x86_64')
url="http://gazebosim.org/"
@@ -26,25 +26,25 @@ optdepends=('bullet: Bullet support'
'ruby-ronn: Generate manpages'
'simbody: Simbody support'
'urdfdom: Load URDF files')
-makedepends=('cmake' 'doxygen' 'pkgconf>=0.26')
+makedepends=('cmake' 'doxygen')
install="${pkgname}.install"
-source=("http://osrf-distributions.s3.amazonaws.com/gazebo/releases/${pkgname}-${pkgver}.tar.bz2" "ogre-1.10.patch")
-sha256sums=('2c29955d476c97dc0ccbb1c8295ec6e8ffe203d7bc6047c1f34433a82ab9215e'
- 'a1c8a9d181f3de6007361f571a40fd04e780081cd9a9a281d64d316e8cc89892')
+source=("https://bitbucket.org/osrf/gazebo/get/gazebo9_9.3.0.tar.bz2" "ogre-1.11.patch")
+sha256sums=('ba1acb778b3360af883b5331ab639ebfea395ebceb9d1cd0aaed2bced041a0a5'
+ '0544018a614fe6a4caf7554cb6c751fc1e1c82e8035a0c3ddb0178786955ce9a')
-prepare() {
- cd "${srcdir}/${pkgname}-${pkgver}"
- patch -Np2 -i "${srcdir}/ogre-1.10.patch"
-}
+ prepare() {
+ cd "${srcdir}/osrf-${pkgname}-33c8adccf084"
+ patch -Np2 -i "${srcdir}/ogre-1.11.patch"
+ }
build() {
- cd "${srcdir}/${pkgname}-${pkgver}"
+ cd "${srcdir}/osrf-${pkgname}-33c8adccf084"
- sed -i -e 's/CODEC_CAP_TRUNCATED/AV_CODEC_CAP_TRUNCATED/g' gazebo/common/AudioDecoder.cc
- sed -i -e 's/CODEC_FLAG_TRUNCATED/AV_CODEC_FLAG_TRUNCATED/g' gazebo/common/AudioDecoder.cc
+ # sed -i -e 's/CODEC_CAP_TRUNCATED/AV_CODEC_CAP_TRUNCATED/g' gazebo/common/AudioDecoder.cc
+ # sed -i -e 's/CODEC_FLAG_TRUNCATED/AV_CODEC_FLAG_TRUNCATED/g' gazebo/common/AudioDecoder.cc
- sed -i -e 's/CODEC_CAP_TRUNCATED/AV_CODEC_CAP_TRUNCATED/g' gazebo/common/Video.cc
- sed -i -e 's/CODEC_FLAG_TRUNCATED/AV_CODEC_FLAG_TRUNCATED/g' gazebo/common/Video.cc
+ # sed -i -e 's/CODEC_CAP_TRUNCATED/AV_CODEC_CAP_TRUNCATED/g' gazebo/common/Video.cc
+ # sed -i -e 's/CODEC_FLAG_TRUNCATED/AV_CODEC_FLAG_TRUNCATED/g' gazebo/common/Video.cc
mkdir -p build && cd build
# Note: we skip unit tests (else set to TRUE)
@@ -55,7 +55,7 @@ build() {
}
package() {
- cd "${srcdir}/${pkgname}-${pkgver}/build"
+ cd "${srcdir}/osrf-${pkgname}-33c8adccf084/build"
make DESTDIR="${pkgdir}" install
}
diff --git a/ogre-1.10.patch b/ogre-1.10.patch
deleted file mode 100644
index b92a09e6a9b..00000000000
--- a/ogre-1.10.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-Only in patched/gazebo-9.0.0: build
-diff -ura original/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc patched/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc
---- original/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc 2018-01-25 23:25:48.000000000 +0100
-+++ patched/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc 2018-02-24 12:29:12.219115580 +0100
-@@ -49,6 +49,8 @@
-
- #include "gazebo/rendering/CustomPSSMShadowCameraSetup.hh"
- #include "gazebo/rendering/ogre_gazebo.h"
-+#include <OGRE/RTShaderSystem/OgreShaderFunction.h>
-+#include <OGRE/RTShaderSystem/OgreShaderProgram.h>
-
- using namespace gazebo;
- using namespace rendering;
diff --git a/ogre-1.11.patch b/ogre-1.11.patch
new file mode 100644
index 00000000000..3224138aabd
--- /dev/null
+++ b/ogre-1.11.patch
@@ -0,0 +1,4725 @@
+diff -ruN original/gazebo-9.0.0/gazebo/gui/model/JointMaker.cc patched/gazebo-9.0.0/gazebo/gui/model/JointMaker.cc
+--- original/gazebo-9.0.0/gazebo/gui/model/JointMaker.cc 2018-01-25 23:25:47.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/gui/model/JointMaker.cc 2018-06-02 21:55:56.462116279 +0200
+@@ -506,7 +506,7 @@
+ jointData->parent = _parent;
+ jointData->line = jointLine;
+ jointData->type = this->dataPtr->jointType;
+- jointData->line->setMaterial(this->jointMaterials[jointData->type]);
++ jointData->line->setMaterial(Ogre::MaterialManager::getSingleton().getByName(this->jointMaterials[jointData->type]));
+
+ return jointData;
+ }
+@@ -1221,7 +1221,7 @@
+ // Line
+ if (this->line)
+ {
+- this->line->setMaterial(material);
++ this->line->setMaterial(Ogre::MaterialManager::getSingleton().getByName(material));
+
+ // Parent - child
+ if (this->child && this->jointVisual)
+diff -ruN original/gazebo-9.0.0/gazebo/gui/ModelSnap.cc patched/gazebo-9.0.0/gazebo/gui/ModelSnap.cc
+--- original/gazebo-9.0.0/gazebo/gui/ModelSnap.cc 2018-01-25 23:25:47.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/gui/ModelSnap.cc 2018-06-02 21:52:42.833149545 +0200
+@@ -416,7 +416,7 @@
+ this->dataPtr->snapHighlight =
+ this->dataPtr->highlightVisual->CreateDynamicLine(
+ rendering::RENDERING_TRIANGLE_FAN);
+- this->dataPtr->snapHighlight->setMaterial("Gazebo/RedTransparent");
++ this->dataPtr->snapHighlight->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/RedTransparent"));
+ this->dataPtr->snapHighlight->AddPoint(hoverTriangle[0]);
+ this->dataPtr->snapHighlight->AddPoint(hoverTriangle[1]);
+ this->dataPtr->snapHighlight->AddPoint(hoverTriangle[2]);
+@@ -480,7 +480,7 @@
+ this->dataPtr->snapLines =
+ this->dataPtr->snapVisual->CreateDynamicLine(
+ rendering::RENDERING_LINE_STRIP);
+- this->dataPtr->snapLines->setMaterial("Gazebo/RedGlow");
++ this->dataPtr->snapLines->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/RedGlow"));
+ this->dataPtr->snapLines->AddPoint(triangle[0]);
+ this->dataPtr->snapLines->AddPoint(triangle[1]);
+ this->dataPtr->snapLines->AddPoint(triangle[2]);
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/ApplyWrenchVisual.cc patched/gazebo-9.0.0/gazebo/rendering/ApplyWrenchVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/ApplyWrenchVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/ApplyWrenchVisual.cc 2018-05-31 11:01:14.012257184 +0200
+@@ -175,7 +175,7 @@
+ // Torque line
+ dPtr->torqueLine = dPtr->torqueVisual->
+ CreateDynamicLine(rendering::RENDERING_LINE_LIST);
+- dPtr->torqueLine->setMaterial(dPtr->unselectedMaterial);
++ dPtr->torqueLine->setMaterial(Ogre::MaterialManager::getSingleton().getByName(dPtr->unselectedMaterial));
+ dPtr->torqueLine->AddPoint(0, 0, 0);
+ dPtr->torqueLine->AddPoint(0, 0, 0.1);
+
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/Camera.cc patched/gazebo-9.0.0/gazebo/rendering/Camera.cc
+--- original/gazebo-9.0.0/gazebo/rendering/Camera.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/Camera.cc 2018-05-31 11:01:14.035590482 +0200
+@@ -1613,7 +1613,7 @@
+ box.setMinimum(bbox.Min().X(), bbox.Min().Y(), bbox.Min().Z());
+ box.setMaximum(bbox.Max().X(), bbox.Max().Y(), bbox.Max().Z());
+
+- box.transformAffine(_visual->GetSceneNode()->_getFullTransform());
++ box.transform(_visual->GetSceneNode()->_getFullTransform());
+ return this->camera->isVisible(box);
+ }
+
+@@ -1829,7 +1829,7 @@
+ float Camera::AvgFPS() const
+ {
+ if (this->renderTarget)
+- return this->renderTarget->getAverageFPS();
++ return this->renderTarget->getStatistics().avgFPS;
+ else
+ return 0.0f;
+ }
+@@ -1837,7 +1837,7 @@
+ //////////////////////////////////////////////////
+ unsigned int Camera::TriangleCount() const
+ {
+- return this->renderTarget->getTriangleCount();
++ return this->renderTarget->getStatistics().triangleCount;
+ }
+
+ //////////////////////////////////////////////////
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/CameraVisual.cc patched/gazebo-9.0.0/gazebo/rendering/CameraVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/CameraVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/CameraVisual.cc 2018-05-31 11:01:14.022257168 +0200
+@@ -114,7 +114,7 @@
+ line->AddPoint(ignition::math::Vector3d(0, 0, 0));
+ line->AddPoint(ignition::math::Vector3d(dist, width*0.5, -height*0.5));
+
+- line->setMaterial("Gazebo/WhiteGlow");
++ line->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/WhiteGlow"));
+ line->setVisibilityFlags(GZ_VISIBILITY_GUI);
+
+ this->AttachObject(planeEnt);
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/COMVisual.cc patched/gazebo-9.0.0/gazebo/rendering/COMVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/COMVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/COMVisual.cc 2018-05-31 11:01:14.015590512 +0200
+@@ -183,7 +183,7 @@
+ p6 += dPtr->inertiaPose.Pos();
+
+ dPtr->crossLines = this->CreateDynamicLine(rendering::RENDERING_LINE_LIST);
+- dPtr->crossLines->setMaterial("Gazebo/Green");
++ dPtr->crossLines->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/Green"));
+ dPtr->crossLines->AddPoint(p1);
+ dPtr->crossLines->AddPoint(p2);
+ dPtr->crossLines->AddPoint(p3);
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/ContactVisual.cc patched/gazebo-9.0.0/gazebo/rendering/ContactVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/ContactVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/ContactVisual.cc 2018-05-31 11:01:14.018923841 +0200
+@@ -120,8 +120,8 @@
+ dPtr->points[c]->normal->SetPoint(1, (normal*normalScale));
+ dPtr->points[c]->depth->SetPoint(1, (normal*-depth*10));
+
+- dPtr->points[c]->normal->setMaterial("Gazebo/LightOn");
+- dPtr->points[c]->depth->setMaterial("Gazebo/LightOff");
++ dPtr->points[c]->normal->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/LightOn"));
++ dPtr->points[c]->depth->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/LightOff"));
+ dPtr->points[c]->depth->Update();
+ dPtr->points[c]->normal->Update();
+ c++;
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc patched/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc
+--- original/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc 2018-06-03 09:02:54.541619560 +0200
++++ patched/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.cc 2018-06-02 18:33:14.441141020 +0200
+@@ -276,7 +276,7 @@
+ //////////////////////////////////////////////////
+ void CustomPSSMShadowCameraSetup::calculateShadowMappingMatrix(
+ const Ogre::SceneManager &_sm, const Ogre::Camera &_cam,
+- const Ogre::Light &_light, Ogre::Matrix4 *_outView,
++ const Ogre::Light &_light, Ogre::Affine3 *_outView,
+ Ogre::Matrix4 *_outProj, Ogre::Camera *outCam) const
+ {
+ // get the shadow frustum's far distance
+@@ -312,7 +312,7 @@
+ // generate projection matrix if requested
+ if (_outProj != nullptr)
+ {
+- *_outProj = Ogre::Matrix4::getScale(1, 1, -1);
++ *_outProj = Ogre::Affine3::getScale(1, 1, -1);
+ }
+
+ // set up camera if requested
+@@ -411,7 +411,7 @@
+ }
+
+ //////////////////////////////////////////////////
+-Ogre::Matrix4 CustomPSSMShadowCameraSetup::buildViewMatrix(
++Ogre::Affine3 CustomPSSMShadowCameraSetup::buildViewMatrix(
+ const Ogre::Vector3 &_pos, const Ogre::Vector3 &_dir,
+ const Ogre::Vector3 &_up) const
+ {
+@@ -421,10 +421,9 @@
+ upN.normalise();
+
+ // Modified for z-up light frusta
+- Ogre::Matrix4 m(xN.x, xN.y, xN.z, -xN.dotProduct(_pos),
++ Ogre::Affine3 m(xN.x, xN.y, xN.z, -xN.dotProduct(_pos),
+ _dir.x, _dir.y, _dir.z, -_dir.dotProduct(_pos),
+- upN.x, upN.y, upN.z, -upN.dotProduct(_pos),
+- 0.0, 0.0, 0.0, 1.0);
++ upN.x, upN.y, upN.z, -upN.dotProduct(_pos));
+
+ return m;
+ }
+@@ -446,7 +445,8 @@
+ _texCam->setFarClipDistance(_light->_deriveShadowFarClipDistance(_cam));
+
+ // calculate standard shadow mapping matrix
+- Ogre::Matrix4 LView, LProj;
++ Ogre::Affine3 LView;
++ Ogre::Matrix4 LProj;
+ this->calculateShadowMappingMatrix(*_sm, *_cam, *_light, &LView, &LProj,
+ nullptr);
+
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.hh patched/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.hh
+--- original/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.hh 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/CustomPSSMShadowCameraSetup.hh 2018-06-02 18:33:34.537793729 +0200
+@@ -99,13 +99,13 @@
+ /// FocusedShadowCameraSetup::calculateShadowMappingMatrix().
+ void calculateShadowMappingMatrix(const Ogre::SceneManager &_sm,
+ const Ogre::Camera &_cam, const Ogre::Light &_light,
+- Ogre::Matrix4 *_out_view, Ogre::Matrix4 *_outProj,
++ Ogre::Affine3 *_outView, Ogre::Matrix4 *_outProj,
+ Ogre::Camera *_outCam) const;
+
+ /// \brief The same as FocusedShadowCameraSetup::buildViewMatrix() except
+ /// resulting matrices are z-up instead of y-up.
+ /// \sa FocusedShadowCameraSetup::buildViewMatrix()
+- public: Ogre::Matrix4 buildViewMatrix(const Ogre::Vector3 &_pos,
++ public: Ogre::Affine3 buildViewMatrix(const Ogre::Vector3 &_pos,
+ const Ogre::Vector3 &_dir, const Ogre::Vector3 & _up) const;
+
+ /// \brief The same as FocusedShadowCameraSetup::ShadowCameraSetup()
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/Distortion.cc patched/gazebo-9.0.0/gazebo/rendering/Distortion.cc
+--- original/gazebo-9.0.0/gazebo/rendering/Distortion.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/Distortion.cc 2018-06-02 18:57:02.741420137 +0200
+@@ -204,7 +204,11 @@
+ // fill the distortion map, while interpolating to fill dead pixels
+ pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
+ const Ogre::PixelBox &pixelBox = pixelBuffer->getCurrentLock();
+- float *pDest = static_cast<float *>(pixelBox.data);
++ // Ogre 1.11 changed Ogre::PixelBox::data from void* to uchar*, hence
++ // reinterpret_cast is required here. static_cast is not allowed between
++ // pointers of unrelated types (see, for instance, Standard § 3.9.1
++ // Fundamental types).
++ float *pDest = reinterpret_cast<float *>(pixelBox.data);
+ for (unsigned int i = 0; i < this->dataPtr->distortionTexHeight; ++i)
+ {
+ for (unsigned int j = 0; j < this->dataPtr->distortionTexWidth; ++j)
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/Heightmap.cc patched/gazebo-9.0.0/gazebo/rendering/Heightmap.cc
+--- original/gazebo-9.0.0/gazebo/rendering/Heightmap.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/Heightmap.cc 2018-06-02 22:56:27.057221623 +0200
+@@ -1138,8 +1138,9 @@
+ Ogre::TerrainMaterialGeneratorPtr matGen =
+ this->dataPtr->terrainGlobals->getDefaultMaterialGenerator();
+
+- matProfile = static_cast<GzTerrainMatGen::SM2Profile*>(
+- matGen->getActiveProfile());
++ // matProfile = static_cast<GzTerrainMatGen::SM2Profile*>(
++ // matGen->getActiveProfile());
++ matProfile = static_cast<Ogre::TerrainMaterialGeneratorA::SM2Profile*>(matGen->getActiveProfile());
+ if (!matProfile)
+ {
+ // using custom material script so ignore setting shadows
+@@ -1262,1905 +1263,1906 @@
+ {
+ }
+
+-/////////////////////////////////////////////////
+-GzTerrainMatGen::SM2Profile::SM2Profile(
+- Ogre::TerrainMaterialGenerator *_parent, const Ogre::String &_name,
+- const Ogre::String &_desc)
+-: TerrainMaterialGeneratorA::SM2Profile(_parent, _name, _desc)
+-{
+- this->mShaderGen = nullptr;
+-}
+-
+-/////////////////////////////////////////////////
+-GzTerrainMatGen::SM2Profile::~SM2Profile()
+-{
+- // Because the base SM2Profile has no virtual destructor:
+- delete this->mShaderGen;
+- this->mShaderGen = nullptr;
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::addTechnique(
+- const Ogre::MaterialPtr &_mat, const Ogre::Terrain *_terrain,
+- TechniqueType _tt)
+-{
+- // Initiate specialized mShaderGen
+- // Ogre::GpuProgramManager &gmgr = Ogre::GpuProgramManager::getSingleton();
+-
+- Ogre::HighLevelGpuProgramManager &hmgr =
+- Ogre::HighLevelGpuProgramManager::getSingleton();
+-
+- if (!this->mShaderGen)
+- {
+- // By default we use the GLSL shaders.
+- if (hmgr.isLanguageSupported("glsl"))
+- {
+- this->mShaderGen = OGRE_NEW
+- GzTerrainMatGen::SM2Profile::ShaderHelperGLSL();
+- }
+- else
+- {
+- gzthrow("No supported shader languages");
+- }
+-
+- // Uncomment this to use cg shaders. I'm keeping the CG
+- // shader for reference. There is some more code to switch, located
+- // below, to enable CG shaders.
+- // if (hmgr.isLanguageSupported("cg"))
+- // {
+- // this->mShaderGen = OGRE_NEW
+- // // This will use Ogre's CG shader
+- // // Ogre::TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg();
+- // //
+- // // This will use our CG shader, which has terrain shadows
+- // GzTerrainMatGen::SM2Profile::ShaderHelperCg();
+- // }
+-
+- // check SM3 features
+- this->mSM3Available =
+- Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0");
+-
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- this->mSM4Available =
+- Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0");
+-#endif
+- }
+-
+- // Unfortunately this doesn't work
+- // Default implementation
+- // TerrainMaterialGeneratorA::SM2Profile::addTechnique(mat, terrain, tt);
+-
+- // So we have to replicate the entire method:
+- Ogre::Technique *tech = _mat->createTechnique();
+-
+- // Only supporting one pass
+- Ogre::Pass *pass = tech->createPass();
+-
+- // Doesn't delegate to the proper method otherwise
+- Ogre::HighLevelGpuProgramPtr vprog =
+- ((GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*)this->mShaderGen)
+- // Use this line if running Ogre's CG shaders
+- // ((TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg*)this->mShaderGen)
+- // Use this line if running our CG shaders
+- // ((GzTerrainMatGen::SM2Profile::ShaderHelperCg*)this->mShaderGen)
+- ->generateVertexProgram(this, _terrain, _tt);
+-
+- // DEBUG: std::cout << "VertShader[" << vprog->getName() << "]:\n"
+- // << vprog->getSource() << "\n\n";
+-
+- Ogre::HighLevelGpuProgramPtr fprog =
+- ((GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*)this->mShaderGen)
+- // Use this line if running Ogre's CG shaders
+- // ((TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg*)this->mShaderGen)
+- // Use this line if running our CG shaders
+- // ((GzTerrainMatGen::SM2Profile::ShaderHelperCg*)this->mShaderGen)
+- ->generateFragmentProgram(this, _terrain, _tt);
+-
+- // DEBUG: std::cout << "FragShader[" << fprog->getName() << "]:\n"
+- // << fprog->getSource() << "\n\n";
+-
+- pass->setVertexProgram(vprog->getName());
+- pass->setFragmentProgram(fprog->getName());
+-
+- if (_tt == HIGH_LOD || _tt == RENDER_COMPOSITE_MAP)
+- {
+- // global normal map
+- Ogre::TextureUnitState* tu = pass->createTextureUnitState();
+- tu->setTextureName(_terrain->getTerrainNormalMap()->getName());
+- tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
+-
+- // global colour map
+- if (_terrain->getGlobalColourMapEnabled() &&
+- this->isGlobalColourMapEnabled())
+- {
+- tu = pass->createTextureUnitState(
+- _terrain->getGlobalColourMap()->getName());
+- tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
+- }
+-
+- // light map
+- if (this->isLightmapEnabled())
+- {
+- tu = pass->createTextureUnitState(_terrain->getLightmap()->getName());
+- tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
+- }
+-
+- // blend maps
+- unsigned int maxLayers = this->getMaxLayers(_terrain);
+-
+- unsigned int numBlendTextures = std::min(
+- _terrain->getBlendTextureCount(maxLayers),
+- _terrain->getBlendTextureCount());
+-
+- unsigned int numLayers = std::min(
+- maxLayers, static_cast<unsigned int>(_terrain->getLayerCount()));
+-
+- for (unsigned int i = 0; i < numBlendTextures; ++i)
+- {
+- tu = pass->createTextureUnitState(_terrain->getBlendTextureName(i));
+- tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
+- }
+-
+- // layer textures
+- for (unsigned int i = 0; i < numLayers; ++i)
+- {
+- // diffuse / specular
+- pass->createTextureUnitState(_terrain->getLayerTextureName(i, 0));
+-
+- // normal / height
+- pass->createTextureUnitState(_terrain->getLayerTextureName(i, 1));
+- }
+- }
+- else
+- {
+- // LOW_LOD textures
+- // composite map
+- Ogre::TextureUnitState *tu = pass->createTextureUnitState();
+- tu->setTextureName(_terrain->getCompositeMap()->getName());
+- tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
+- }
+-
+- // Add shadow textures (always at the end)
+- if (this->isShadowingEnabled(_tt, _terrain))
+- {
+- unsigned int numTextures = 1;
+-
+- if (this->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = this->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- Ogre::TextureUnitState *tu = pass->createTextureUnitState();
+- tu->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW);
+- tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER);
+- tu->setTextureBorderColour(Ogre::ColourValue::White);
+- }
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-// generate() and generateForCompositeMap() are identical to
+-// TerrainMaterialGeneratorA implementation, the only reason for repeating
+-// them is that, unfortunately, addTechnique() is not declared virtual.
+-Ogre::MaterialPtr GzTerrainMatGen::SM2Profile::generate(
+- const Ogre::Terrain *_terrain)
+-{
+- // re-use old material if exists
+- Ogre::MaterialPtr mat = _terrain->_getMaterial();
+-
+- if (mat.isNull())
+- {
+- Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton();
+-
+- // it's important that the names are deterministic for a given terrain, so
+- // use the terrain pointer as an ID
+- const Ogre::String &matName = _terrain->getMaterialName();
+- mat = matMgr.getByName(matName);
+-
+- if (mat.isNull())
+- {
+- mat = matMgr.create(matName,
+- Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+- }
+- }
+-
+- // clear everything
+- mat->removeAllTechniques();
+-
+- // Automatically disable normal & parallax mapping if card cannot handle it
+- // We do this rather than having a specific technique for it since it's
+- // simpler.
+- Ogre::GpuProgramManager &gmgr = Ogre::GpuProgramManager::getSingleton();
+-
+- if (!gmgr.isSyntaxSupported("ps_4_0") &&
+- !gmgr.isSyntaxSupported("ps_3_0") &&
+- !gmgr.isSyntaxSupported("ps_2_x") &&
+- !gmgr.isSyntaxSupported("fp40") &&
+- !gmgr.isSyntaxSupported("arbfp1"))
+- {
+- this->setLayerNormalMappingEnabled(false);
+- this->setLayerParallaxMappingEnabled(false);
+- }
+-
+- this->addTechnique(mat, _terrain, HIGH_LOD);
+-
+- // LOD
+- if (this->mCompositeMapEnabled)
+- {
+- this->addTechnique(mat, _terrain, LOW_LOD);
+- Ogre::Material::LodValueList lodValues;
+- lodValues.push_back(
+- Ogre::TerrainGlobalOptions::getSingleton().getCompositeMapDistance());
+-
+- mat->setLodLevels(lodValues);
+- Ogre::Technique *lowLodTechnique = mat->getTechnique(1);
+- lowLodTechnique->setLodIndex(1);
+- }
+-
+- this->UpdateParams(mat, _terrain);
+-
+- return mat;
+-}
+-
+-/////////////////////////////////////////////////
+-Ogre::MaterialPtr GzTerrainMatGen::SM2Profile::generateForCompositeMap(
+- const Ogre::Terrain *_terrain)
+-{
+- // re-use old material if exists
+- Ogre::MaterialPtr mat = _terrain->_getCompositeMapMaterial();
+-
+- if (mat.isNull())
+- {
+- Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton();
+-
+- // it's important that the names are deterministic for a given terrain, so
+- // use the terrain pointer as an ID
+- const Ogre::String &matName = _terrain->getMaterialName() + "/comp";
+-
+- mat = matMgr.getByName(matName);
+-
+- if (mat.isNull())
+- {
+- mat = matMgr.create(matName,
+- Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+- }
+- }
+-
+- // clear everything
+- mat->removeAllTechniques();
+-
+- this->addTechnique(mat, _terrain, RENDER_COMPOSITE_MAP);
+-
+- this->UpdateParamsForCompositeMap(mat, _terrain);
+-
+- return mat;
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::UpdateParams(const Ogre::MaterialPtr &_mat,
+- const Ogre::Terrain *_terrain)
+-{
+- static_cast<GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*>(
+- this->mShaderGen)->updateParams(this, _mat, _terrain, false);
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::UpdateParamsForCompositeMap(
+- const Ogre::MaterialPtr &_mat, const Ogre::Terrain *_terrain)
+-{
+- static_cast<GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*>(
+- this->mShaderGen)->updateParams(this, _mat, _terrain, true);
+-}
+-
+-/////////////////////////////////////////////////
+-/////////////////////////////////////////////////
+-// GLSL Shader helper
+-/////////////////////////////////////////////////
+-/////////////////////////////////////////////////
+-
+-/////////////////////////////////////////////////
+-Ogre::HighLevelGpuProgramPtr
+-GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVertexProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt)
+-{
+- Ogre::HighLevelGpuProgramPtr ret =
+- this->createVertexProgram(_prof, _terrain, _tt);
+-
+- Ogre::StringStream sourceStr;
+- this->generateVertexProgramSource(_prof, _terrain, _tt, sourceStr);
+-
+- ret->setSource(sourceStr.str());
+- ret->load();
+- this->defaultVpParams(_prof, _terrain, _tt, ret);
+-
+- return ret;
+-}
+-
+-/////////////////////////////////////////////////
+-Ogre::HighLevelGpuProgramPtr
+-GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFragmentProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain, TechniqueType _tt)
+-{
+- Ogre::HighLevelGpuProgramPtr ret = this->createFragmentProgram(_prof,
+- _terrain, _tt);
+-
+- Ogre::StringStream sourceStr;
+-
+- this->generateFragmentProgramSource(_prof, _terrain, _tt, sourceStr);
+-
+- ret->setSource(sourceStr.str());
+-
+- ret->load();
+-
+- this->defaultFpParams(_prof, _terrain, _tt, ret);
+-
+- Ogre::GpuProgramParametersSharedPtr params = ret->getDefaultParameters();
+- params->setIgnoreMissingParams(false);
+-
+- Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
+- Ogre::uint numBlendTextures = std::min(
+- _terrain->getBlendTextureCount(maxLayers),
+- _terrain->getBlendTextureCount());
+-
+- Ogre::uint numLayers = std::min(maxLayers,
+- static_cast<Ogre::uint>(_terrain->getLayerCount()));
+-
+- int samplerCounter = 0;
+-
+- if (_tt == LOW_LOD)
+- params->setNamedConstant("compositeMap", samplerCounter++);
+- else
+- {
+- params->setNamedConstant("globalNormal", samplerCounter++);
+-
+- if (_terrain->getGlobalColourMapEnabled() &&
+- _prof->isGlobalColourMapEnabled())
+- {
+- params->setNamedConstant("globalColourMap", samplerCounter++);
+- }
+-
+- if (_prof->isLightmapEnabled())
+- params->setNamedConstant("lightMap", samplerCounter++);
+-
+- for (Ogre::uint i = 0; i < numBlendTextures; ++i)
+- {
+- params->setNamedConstant("blendTex" +
+- boost::lexical_cast<std::string>(i), samplerCounter++);
+- }
+-
+- for (Ogre::uint i = 0; i < numLayers; ++i)
+- {
+- params->setNamedConstant("difftex" +
+- boost::lexical_cast<std::string>(i), samplerCounter++);
+- params->setNamedConstant("normtex" +
+- boost::lexical_cast<std::string>(i), samplerCounter++);
+- }
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- Ogre::uint numTextures = 1;
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- {
+- params->setNamedConstant("shadowMap" +
+- boost::lexical_cast<std::string>(i), samplerCounter++);
+- }
+- }
+-
+- return ret;
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::updateParams(
+- const SM2Profile *_prof, const Ogre::MaterialPtr &_mat,
+- const Ogre::Terrain *_terrain, bool _compositeMap)
+-{
+- Ogre::Pass *p = _mat->getTechnique(0)->getPass(0);
+-
+- if (_compositeMap)
+- {
+- this->updateVpParams(_prof, _terrain, RENDER_COMPOSITE_MAP,
+- p->getVertexProgramParameters());
+- this->updateFpParams(_prof, _terrain, RENDER_COMPOSITE_MAP,
+- p->getFragmentProgramParameters());
+- }
+- else
+- {
+- // high lod
+- this->updateVpParams(_prof, _terrain, HIGH_LOD,
+- p->getVertexProgramParameters());
+- this->updateFpParams(_prof, _terrain, HIGH_LOD,
+- p->getFragmentProgramParameters());
+-
+- if (_prof->isCompositeMapEnabled())
+- {
+- // low lod
+- p = _mat->getTechnique(1)->getPass(0);
+- this->updateVpParams(_prof, _terrain, LOW_LOD,
+- p->getVertexProgramParameters());
+- this->updateFpParams(_prof, _terrain, LOW_LOD,
+- p->getFragmentProgramParameters());
+- }
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::
+-generateVertexProgramSource(const SM2Profile *_prof,
+- const Ogre::Terrain* _terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream)
+-{
+- this->generateVpHeader(_prof, _terrain, _tt, _outStream);
+-
+- if (_tt != LOW_LOD)
+- {
+- unsigned int maxLayers = _prof->getMaxLayers(_terrain);
+- unsigned int numLayers = std::min(maxLayers,
+- static_cast<unsigned int>(_terrain->getLayerCount()));
+-
+- for (unsigned int i = 0; i < numLayers; ++i)
+- this->generateVpLayer(_prof, _terrain, _tt, i, _outStream);
+- }
+-
+- this->generateVpFooter(_prof, _terrain, _tt, _outStream);
+-}
+-
+-/////////////////////////////////////////////////
+-// This method is identical to
+-// TerrainMaterialGeneratorA::SM2Profile::ShaderHelperGLSL::generateVpHeader()
+-// but is needed because generateVpDynamicShadowsParams() is not declared
+-// virtual.
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVpHeader(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- bool compression = false;
+-
+- _outStream << "#version " << glslVersion << "\n\n";
+-
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- compression = _terrain->_getUseVertexCompression() &&
+- _tt != RENDER_COMPOSITE_MAP;
+-
+- if (compression)
+- {
+- // The parameter "in vec4 vertex;" is automatically bound by OGRE.
+- // The parameter "in vec4 uv0'" is automatically bound by OGRE.
+- _outStream << vpInStr << " vec4 vertex;\n"
+- << vpInStr << " vec4 uv0;\n";
+- }
+- else
+-#endif
+- {
+- // The parameter "in vec4 vertex;" is automatically bound by OGRE.
+- // The parameter "in vec4 uv0'" is automatically bound by OGRE.
+- _outStream << vpInStr << " vec4 vertex;\n"
+- << vpInStr << " vec4 uv0;\n";
+- }
+-
+- if (_tt != RENDER_COMPOSITE_MAP)
+- // The parameter "in vec4 uv1'" is automatically bound by OGRE.
+- _outStream << vpInStr << " vec4 uv1;\n";
+-
+- _outStream <<
+- "uniform mat4 worldMatrix;\n"
+- "uniform mat4 viewProjMatrix;\n"
+- "uniform vec2 lodMorph;\n";
+-
+- if (compression)
+- {
+- _outStream <<
+- "uniform mat4 posIndexToObjectSpace;\n"
+- "uniform float baseUVScale;\n";
+- }
+-
+-
+- // uv multipliers
+- unsigned int maxLayers = _prof->getMaxLayers(_terrain);
+- unsigned int numLayers = std::min(maxLayers,
+- static_cast<unsigned int>(_terrain->getLayerCount()));
+-
+- unsigned int numUVMultipliers = (numLayers / 4);
+-
+- if (numLayers % 4)
+- ++numUVMultipliers;
+-
+- for (unsigned int i = 0; i < numUVMultipliers; ++i)
+- _outStream << "uniform vec4 uvMul" << i << ";\n";
+-
+- _outStream <<
+- vpOutStr << " vec4 position;\n";
+-
+- unsigned int texCoordSet = 1;
+- _outStream << vpOutStr << " vec4 uvMisc;\n";
+-
+- // layer UV's premultiplied, packed as xy/zw
+- unsigned int numUVSets = numLayers / 2;
+-
+- if (numLayers % 2)
+- ++numUVSets;
+-
+- if (_tt != LOW_LOD)
+- {
+- for (unsigned int i = 0; i < numUVSets; ++i)
+- {
+- _outStream << vpOutStr << " vec4 layerUV" << i << ";\n";
+- }
+- }
+-
+- if (_prof->getParent()->getDebugLevel() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- _outStream << vpOutStr << " vec2 lodInfo;\n";
+- }
+-
+- bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
+- _tt != RENDER_COMPOSITE_MAP;
+-
+- if (fog)
+- {
+- _outStream <<
+- "uniform vec4 fogParams;\n"
+- << vpOutStr << " float fogVal;\n";
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- texCoordSet = this->generateVpDynamicShadowsParams(texCoordSet, _prof,
+- _terrain, _tt, _outStream);
+- }
+-
+- // check we haven't exceeded texture coordinates
+- if (texCoordSet > 8)
+- {
+- OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
+- "Requested options require too many texture coordinate sets! "
+- "Try reducing the number of layers.",
+- __FUNCTION__);
+- }
+-
+- _outStream << "void main()\n"
+- << "{\n";
+-
+- if (compression)
+- {
+- _outStream
+- << " vec4 pos = posIndexToObjectSpace * "
+- << "vec4(vertex.x, vertex.y, uv0.x, 1.0);\n"
+-
+- << " vec2 uv = vec2(vertex.x * baseUVScale, 1.0 - "
+- << "(vertex.y * baseUVScale));\n";
+- }
+- else
+- {
+- _outStream
+- << " vec4 pos = vertex;\n"
+- << " vec2 uv = vec2(uv0.x, uv0.y);\n";
+- }
+-
+- _outStream << " vec4 worldPos = worldMatrix * pos;\n";
+- _outStream << " position = pos;\n";
+-
+- if (_tt != RENDER_COMPOSITE_MAP)
+- {
+- // determine whether to apply the LOD morph to this vertex
+- // we store the deltas against all vertices so we only want to apply
+- // the morph to the ones which would disappear. The target LOD which is
+- // being morphed to is stored in lodMorph.y, and the LOD at which
+- // the vertex should be morphed is stored in uv.w. If we subtract
+- // the former from the latter, and arrange to only morph if the
+- // result is negative (it will only be -1 in fact, since after that
+- // the vertex will never be indexed), we will achieve our aim.
+- // sign(vertexLOD - targetLOD) == -1 is to morph
+- _outStream <<
+- " float toMorph = -min(0.0, sign(uv1.y - lodMorph.y));\n";
+-
+- // this will either be 1 (morph) or 0 (don't morph)
+- if (_prof->getParent()->getDebugLevel())
+- {
+- // x == LOD level (-1 since value is target level, we want to
+- // display actual)
+- _outStream << "lodInfo.x = (lodMorph.y - 1.0) / "
+- << _terrain->getNumLodLevels() << ";\n";
+-
+- // y == LOD morph
+- _outStream << "lodInfo.y = toMorph * lodMorph.x;\n";
+- }
+-
+- // morph
+- switch (_terrain->getAlignment())
+- {
+- case Ogre::Terrain::ALIGN_X_Y:
+- _outStream << " worldPos.z += uv1.x * toMorph * lodMorph.x;\n";
+- break;
+- case Ogre::Terrain::ALIGN_X_Z:
+- _outStream << " worldPos.y += uv1.x * toMorph * lodMorph.x;\n";
+- break;
+- case Ogre::Terrain::ALIGN_Y_Z:
+- _outStream << " worldPos.x += uv1.x * toMorph * lodMorph.x;\n";
+- break;
+- default:
+- gzerr << "Invalid alignment\n";
+- };
+- }
+-
+- // generate UVs
+- if (_tt != LOW_LOD)
+- {
+- for (unsigned int i = 0; i < numUVSets; ++i)
+- {
+- unsigned int layer = i * 2;
+- unsigned int uvMulIdx = layer / 4;
+-
+- _outStream << " layerUV" << i << ".xy = " << " uv.xy * uvMul"
+- << uvMulIdx << "." << this->GetChannel(layer) << ";\n";
+- _outStream << " layerUV" << i << ".zw = " << " uv.xy * uvMul"
+- << uvMulIdx << "." << this->GetChannel(layer+1) << ";\n";
+- }
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-// This method is identical to
+-// TerrainMaterialGeneratorA::SM2Profile::ShaderHelperGLSL::generateVpFooter()
+-// but is needed because generateVpDynamicShadows() is not declared virtual.
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVpFooter(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- _outStream << " gl_Position = viewProjMatrix * worldPos;\n"
+- << " uvMisc.xy = uv.xy;\n";
+-
+- bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
+- _tt != RENDER_COMPOSITE_MAP;
+- if (fog)
+- {
+- if (_terrain->getSceneManager()->getFogMode() == Ogre::FOG_LINEAR)
+- {
+- _outStream <<
+- " fogVal = clamp((oPos.z - fogParams.y) * fogParams.w, 0.0, 1.0);\n";
+- }
+- else
+- {
+- _outStream <<
+- " fogVal = 1 - clamp(1 / (exp(oPos.z * fogParams.x)), 0.0, 1.0);\n";
+- }
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- this->generateVpDynamicShadows(_prof, _terrain, _tt, _outStream);
+-
+- _outStream << "}\n";
+-}
+-
+-/////////////////////////////////////////////////
+-void
+-GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVpDynamicShadows(
+- const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
+- TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
+-{
+- unsigned int numTextures = 1;
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+-
+- // Calculate the position of vertex in light space
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- _outStream << " lightSpacePos" << i << " = texViewProjMatrix"
+- << i << " * worldPos;\n";
+-
+- // Don't linearize depth range: RTSS PSSM implementation uses
+- // view-space depth
+- // if (prof->getReceiveDynamicShadowsDepth())
+- // {
+- // // make linear
+- // outStream << "lightSpacePos" << i << ".z = (lightSpacePos" << i
+- // << ".z - depthRange" << i << ".x) * depthRange" << i
+- // << ".w;\n";
+- // }
+- }
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- _outStream << " // pass cam depth\n uvMisc.z = gl_Position.z;\n";
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::defaultVpParams(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, const Ogre::HighLevelGpuProgramPtr &_prog)
+-{
+- Ogre::GpuProgramParametersSharedPtr params = _prog->getDefaultParameters();
+- params->setIgnoreMissingParams(true);
+-
+- params->setNamedAutoConstant("worldMatrix",
+- Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
+-
+- params->setNamedAutoConstant("viewProjMatrix",
+- Ogre::GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
+-
+- params->setNamedAutoConstant("lodMorph",
+- Ogre::GpuProgramParameters::ACT_CUSTOM,
+- Ogre::Terrain::LOD_MORPH_CUSTOM_PARAM);
+-
+- params->setNamedAutoConstant("fogParams",
+- Ogre::GpuProgramParameters::ACT_FOG_PARAMS);
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- unsigned int numTextures = 1;
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- params->setNamedAutoConstant("texViewProjMatrix" +
+- Ogre::StringConverter::toString(i),
+- Ogre::GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
+-
+- // Don't add depth range params
+- // if (prof->getReceiveDynamicShadowsDepth())
+- // {
+- // params->setNamedAutoConstant("depthRange" +
+- // Ogre::StringConverter::toString(i),
+- // Ogre::GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
+- // }
+- }
+- }
+-
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- if (_terrain->_getUseVertexCompression() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- Ogre::Matrix4 posIndexToObjectSpace;
+- _terrain->getPointTransform(&posIndexToObjectSpace);
+- params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace);
+- }
+-#endif
+-}
+-
+-/////////////////////////////////////////////////
+-unsigned int GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::
+-generateVpDynamicShadowsParams(unsigned int _texCoord, const SM2Profile *_prof,
+- const Ogre::Terrain * /*_terrain*/, TechniqueType /*_tt*/,
+- Ogre::StringStream &_outStream)
+-{
+- // out semantics & params
+- unsigned int numTextures = 1;
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+-
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- _outStream << vpOutStr << " vec4 lightSpacePos" << i << ";\n"
+- << "uniform mat4 texViewProjMatrix" << i << ";\n";
+-
+- // Don't add depth range params
+- // if (prof->getReceiveDynamicShadowsDepth())
+- // {
+- // _outStream << ", uniform float4 depthRange" << i
+- // << " // x = min, y = max, z = range, w = 1/range\n";
+- // }
+- }
+-
+- return _texCoord;
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpHeader(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- _outStream << "#version " << glslVersion << "\n\n";
+-
+- _outStream <<
+- "vec4 expand(vec4 v)\n"
+- "{\n"
+- " return v * 2 - 1;\n"
+- "}\n\n";
+-
+- _outStream <<
+- "vec4 lit(float NdotL, float NdotH, float m)\n"
+- "{\n"
+- " float specular = (NdotL > 0) ? pow(max(0.0, NdotH), m) : 0.0;\n"
+- " return vec4(1.0, max(0.0, NdotL), specular, 1.0);\n"
+- "}\n";
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- this->generateFpDynamicShadowsHelpers(_prof, _terrain, _tt, _outStream);
+-
+- _outStream <<
+- fpInStr << " vec4 position;\n";
+-
+- Ogre::uint texCoordSet = 1;
+- _outStream << fpInStr << " vec4 uvMisc;\n";
+-
+- // UV's premultiplied, packed as xy/zw
+- Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
+- Ogre::uint numBlendTextures = std::min(
+- _terrain->getBlendTextureCount(maxLayers),
+- _terrain->getBlendTextureCount());
+- Ogre::uint numLayers = std::min(maxLayers,
+- static_cast<Ogre::uint>(_terrain->getLayerCount()));
+-
+- Ogre::uint numUVSets = numLayers / 2;
+-
+- if (numLayers % 2)
+- ++numUVSets;
+-
+- if (_tt != LOW_LOD)
+- {
+- for (Ogre::uint i = 0; i < numUVSets; ++i)
+- {
+- _outStream <<
+- fpInStr << " vec4 layerUV" << i << ";\n";
+- }
+- }
+-
+- if (_prof->getParent()->getDebugLevel() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- _outStream << fpInStr << " vec2 lodInfo;\n";
+- }
+-
+- bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
+- _tt != RENDER_COMPOSITE_MAP;
+-
+- if (fog)
+- {
+- _outStream <<
+- "uniform vec3 fogColour;\n"
+- << fpInStr << " float fogVal;\n";
+- }
+-
+- Ogre::uint currentSamplerIdx = 0;
+-
+- _outStream <<
+- // Only 1 light supported in this version
+- // deferred shading profile / generator later, ok? :)
+- "uniform vec3 ambient;\n"
+- "uniform vec4 lightPosObjSpace;\n"
+- "uniform vec3 lightDiffuseColour;\n"
+- "uniform vec3 lightSpecularColour;\n"
+- "uniform vec3 eyePosObjSpace;\n"
+- // pack scale, bias and specular
+- "uniform vec4 scaleBiasSpecular;\n";
+-
+- if (_tt == LOW_LOD)
+- {
+- // single composite map covers all the others below
+- _outStream << "uniform sampler2D compositeMap;\n";
+- }
+- else
+- {
+- _outStream << "uniform sampler2D globalNormal;\n";
+-
+- if (_terrain->getGlobalColourMapEnabled() &&
+- _prof->isGlobalColourMapEnabled())
+- {
+- _outStream << "uniform sampler2D globalColourMap;\n";
+- }
+-
+- if (_prof->isLightmapEnabled())
+- {
+- _outStream << "uniform sampler2D lightMap;\n";
+- }
+-
+- // Blend textures - sampler definitions
+- for (Ogre::uint i = 0; i < numBlendTextures; ++i)
+- {
+- _outStream << "uniform sampler2D blendTex" << i << ";\n";
+- }
+-
+- // Layer textures - sampler definitions & UV multipliers
+- for (Ogre::uint i = 0; i < numLayers; ++i)
+- {
+- _outStream << "uniform sampler2D difftex" << i << ";\n";
+- _outStream << "uniform sampler2D normtex" << i << ";\n";
+- }
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- this->generateFpDynamicShadowsParams(&texCoordSet, &currentSamplerIdx,
+- _prof, _terrain, _tt, _outStream);
+- }
+-
+- // check we haven't exceeded samplers
+- if (currentSamplerIdx > 16)
+- {
+- OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
+- "Requested options require too many texture samplers! "
+- "Try reducing the number of layers.", __FUNCTION__);
+- }
+-
+- std::string outputColTypeStr = "vec4";
+- if (glslVersion != "120")
+- {
+- _outStream << "out vec4 outputCol;\n";
+- outputColTypeStr = "";
+- }
+-
+- _outStream <<
+- "void main()\n"
+- "{\n"
+- " float shadow = 1.0;\n"
+- " vec2 uv = uvMisc.xy;\n"
+- " " << outputColTypeStr << " outputCol = vec4(0.0, 0.0, 0.0, 1.0);\n";
+-
+- if (_tt != LOW_LOD)
+- {
+- // global normal
+- _outStream << " vec3 normal = expand("
+- << textureStr << "(globalNormal, uv)).xyz;\n";
+- }
+-
+- _outStream <<
+- " vec3 lightDir =\n"
+- " lightPosObjSpace.xyz - (position.xyz * lightPosObjSpace.w);\n"
+- " vec3 eyeDir = eyePosObjSpace - position.xyz;\n"
+-
+- // set up accumulation areas
+- " vec3 diffuse = vec3(0.0, 0.0, 0.0);\n"
+- " float specular = 0.0;\n";
+-
+- if (_tt == LOW_LOD)
+- {
+- // we just do a single calculation from composite map
+- _outStream <<
+- " vec4 composite = " << textureStr << "(compositeMap, uv);\n"
+- " diffuse = composite.xyz;\n";
+- // TODO - specular; we'll need normals for this!
+- }
+- else
+- {
+- // set up the blend values
+- for (Ogre::uint i = 0; i < numBlendTextures; ++i)
+- {
+- _outStream << " vec4 blendTexVal" << i
+- << " = " << textureStr << "(blendTex" << i << ", uv);\n";
+- }
+-
+- if (_prof->isLayerNormalMappingEnabled())
+- {
+- // derive the tangent space basis
+- // we do this in the pixel shader because we don't have per-vertex normals
+- // because of the LOD, we use a normal map
+- // tangent is always +x or -z in object space depending on alignment
+- switch (_terrain->getAlignment())
+- {
+- case Ogre::Terrain::ALIGN_X_Y:
+- case Ogre::Terrain::ALIGN_X_Z:
+- _outStream << " vec3 tangent = vec3(1.0, 0.0, 0.0);\n";
+- break;
+- case Ogre::Terrain::ALIGN_Y_Z:
+- _outStream << " vec3 tangent = vec3(0.0, 0.0, -1.0);\n";
+- break;
+- default:
+- gzerr << "Invalid terrain alignment\n";
+- break;
+- };
+-
+- _outStream << " vec3 binormal = normalize(cross(tangent, normal));\n";
+- // note, now we need to re-cross to derive tangent again because it
+- // wasn't orthonormal
+- _outStream << " tangent = normalize(cross(normal, binormal));\n";
+- // derive final matrix
+- /*_outStream << " mat3 TBN = mat3(tangent.x, tangent.y, tangent.z,"
+- "binormal.x, binormal.y, binormal.z,"
+- "normal.x, normal.y, normal.z);\n";
+- */
+-
+- // set up lighting result placeholders for interpolation
+- _outStream << " vec4 litRes, litResLayer;\n";
+- _outStream << " vec3 TSlightDir, TSeyeDir, TShalfAngle, TSnormal;\n";
+- if (_prof->isLayerParallaxMappingEnabled())
+- _outStream << " float displacement;\n";
+- // move
+- _outStream << " TSlightDir = normalize(vec3(dot(tangent, lightDir),"
+- "dot(binormal, lightDir),"
+- "dot(normal, lightDir)));\n";
+- _outStream << " TSeyeDir = normalize(vec3(dot(tangent, eyeDir),"
+- "dot(binormal, eyeDir),"
+- "dot(normal, eyeDir)));\n";
+- }
+- else
+- {
+- // simple per-pixel lighting with no normal mapping
+- _outStream << " lightDir = normalize(lightDir);\n";
+- _outStream << " eyeDir = normalize(eyeDir);\n";
+- _outStream << " vec3 halfAngle = normalize(lightDir + eyeDir);\n";
+-
+- _outStream << " vec4 litRes = lit(dot(lightDir, normal), "
+- "dot(halfAngle, normal), scaleBiasSpecular.z);\n";
+- }
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-void
+-GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpDynamicShadowsParams(
+- Ogre::uint *_texCoord, Ogre::uint *_sampler, const SM2Profile *_prof,
+- const Ogre::Terrain * /*_terrain*/, TechniqueType _tt,
+- Ogre::StringStream &_outStream)
+-{
+- if (_tt == HIGH_LOD)
+- this->mShadowSamplerStartHi = *_sampler;
+- else if (_tt == LOW_LOD)
+- this->mShadowSamplerStartLo = *_sampler;
+-
+- // in semantics & params
+- Ogre::uint numTextures = 1;
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- _outStream << "uniform vec4 pssmSplitPoints;\n";
+- }
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- {
+- _outStream << fpInStr <<
+- " vec4 lightSpacePos" << i << ";\n" <<
+- "uniform sampler2D shadowMap" << i << ";\n";
+-
+- *_sampler = *_sampler + 1;
+- *_texCoord = *_texCoord + 1;
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream <<
+- "uniform float inverseShadowmapSize" << i << ";\n";
+- }
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpLayer(
+- const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
+- TechniqueType _tt, Ogre::uint _layer,
+- Ogre::StringStream &_outStream)
+-{
+- Ogre::uint uvIdx = _layer / 2;
+- Ogre::String uvChannels = (_layer % 2) ? ".zw" : ".xy";
+- Ogre::uint blendIdx = (_layer-1) / 4;
+- Ogre::String blendChannel = this->GetChannel(_layer-1);
+- Ogre::String blendWeightStr = Ogre::String("blendTexVal") +
+- Ogre::StringConverter::toString(blendIdx) + "." + blendChannel;
+-
+- // generate early-out conditional
+- // Disable - causing some issues even when trying to force the use of texldd
+- // if (layer && prof->_isSM3Available())
+- // _outStream << " if (" << blendWeightStr << " > 0.0003)\n {\n";
+-
+- // generate UV
+- _outStream << " vec2 uv" << _layer << " = layerUV" << uvIdx
+- << uvChannels << ";\n";
+-
+- // calculate lighting here if normal mapping
+- if (_prof->isLayerNormalMappingEnabled())
+- {
+- if (_prof->isLayerParallaxMappingEnabled() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- // modify UV - note we have to sample an extra time
+- _outStream << " displacement = " << textureStr << "(normtex" << _layer
+- << ", uv" << _layer << ").w\n"
+- " * scaleBiasSpecular.x + scaleBiasSpecular.y;\n";
+- _outStream << " uv" << _layer << " += TSeyeDir.xy * displacement;\n";
+- }
+-
+- // access TS normal map
+- _outStream << " TSnormal = expand(" << textureStr << "(normtex"
+- << _layer << ", uv" << _layer << ")).xyz;\n";
+- _outStream << " TShalfAngle = normalize(TSlightDir + TSeyeDir);\n";
+-
+- _outStream << " litResLayer = lit(dot(TSlightDir, TSnormal), "
+- "dot(TShalfAngle, TSnormal), scaleBiasSpecular.z);\n";
+-
+- if (!_layer)
+- _outStream << " litRes = litResLayer;\n";
+- else
+- _outStream << " litRes = mix(litRes, litResLayer, "
+- << blendWeightStr << ");\n";
+- }
+-
+- // sample diffuse texture
+- _outStream << " vec4 diffuseSpecTex" << _layer
+- << " = " << textureStr << "(difftex" << _layer << ", uv" << _layer
+- << ");\n";
+-
+- // apply to common
+- if (!_layer)
+- {
+- _outStream << " diffuse = diffuseSpecTex0.xyz;\n";
+- if (_prof->isLayerSpecularMappingEnabled())
+- _outStream << " specular = diffuseSpecTex0.w;\n";
+- }
+- else
+- {
+- _outStream << " diffuse = mix(diffuse, diffuseSpecTex" << _layer
+- << ".xyz, " << blendWeightStr << ");\n";
+-
+- if (_prof->isLayerSpecularMappingEnabled())
+- {
+- _outStream << " specular = mix(specular, diffuseSpecTex" << _layer
+- << ".w, " << blendWeightStr << ");\n";
+- }
+- }
+-
+- // End early-out
+- // Disable - causing some issues even when trying to force the use of texldd
+- // if (layer && prof->_isSM3Available())
+- // _outStream << " } // early-out blend value\n";
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpFooter(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- if (_tt == LOW_LOD)
+- {
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- this->generateFpDynamicShadows(_prof, _terrain, _tt, _outStream);
+- _outStream << " outputCol.xyz = diffuse * rtshadow;\n";
+- }
+- else
+- {
+- _outStream << " outputCol.xyz = diffuse;\n";
+- }
+- }
+- else
+- {
+- if (_terrain->getGlobalColourMapEnabled() &&
+- _prof->isGlobalColourMapEnabled())
+- {
+- // sample colour map and apply to diffuse
+- _outStream << " diffuse *= " << textureStr
+- << "(globalColourMap, uv).xyz;\n";
+- }
+-
+- if (_prof->isLightmapEnabled())
+- {
+- // sample lightmap
+- _outStream << " shadow = " << textureStr << "(lightMap, uv).x;\n";
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- this->generateFpDynamicShadows(_prof, _terrain, _tt, _outStream);
+- }
+-
+- // diffuse lighting
+- _outStream << " outputCol.xyz += ambient * diffuse + litRes.y * "
+- "lightDiffuseColour * diffuse * shadow;\n";
+-
+- // specular default
+- if (!_prof->isLayerSpecularMappingEnabled())
+- _outStream << " specular = 1.0;\n";
+-
+- if (_tt == RENDER_COMPOSITE_MAP)
+- {
+- // Lighting embedded in alpha
+- _outStream << " outputCol.w = shadow;\n";
+- }
+- else
+- {
+- // Apply specular
+- _outStream << " outputCol.xyz += litRes.z * lightSpecularColour * "
+- "specular * shadow;\n";
+-
+- if (_prof->getParent()->getDebugLevel())
+- {
+- _outStream << " outputCol.xy += lodInfo.xy;\n";
+- }
+- }
+- }
+-
+- bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
+- _tt != RENDER_COMPOSITE_MAP;
+- if (fog)
+- {
+- _outStream << " outputCol.xyz = mix(outputCol.xyz, fogColour, fogVal);\n";
+- }
+-
+- if (glslVersion == "120")
+- _outStream << " gl_FragColor = outputCol;\n";
+-
+- // Final return
+- _outStream << "\n}\n";
+-}
+-
+-/////////////////////////////////////////////////
+-void
+-GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpDynamicShadowsHelpers(
+- const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
+- TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
+-{
+- // TODO make filtering configurable
+- _outStream <<
+- "// Simple PCF\n"
+- "// Number of samples in one dimension (square for total samples)\n"
+- "#define NUM_SHADOW_SAMPLES_1D 2.0\n"
+- "#define SHADOW_FILTER_SCALE 1.0\n"
+-
+- "#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D\n"
+-
+- "vec4 offsetSample(vec4 uv, vec2 offset, float invMapSize)\n"
+- "{\n"
+- " return vec4(uv.xy + offset * invMapSize * uv.w, uv.z, uv.w);\n"
+- "}\n";
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream <<
+- "float calcDepthShadow(sampler2D shadowMap, vec4 uv, "
+- "float invShadowMapSize)\n"
+- "{\n"
+- " // 4-sample PCF\n"
+- " float shadow = 0.0;\n"
+- " float offset = (NUM_SHADOW_SAMPLES_1D/2.0 - 0.5) *SHADOW_FILTER_SCALE;"
+- "\n"
+- " for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE)\n"
+- " for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE)\n"
+- " {\n"
+- " vec4 newUV = offsetSample(uv, vec2(x, y), invShadowMapSize);\n"
+- " // manually project and assign derivatives\n"
+- " // to avoid gradient issues inside loops\n"
+- " newUV = newUV / newUV.w;\n";
+- // The following line used to be:
+- // " float depth = tex2d(shadowMap, newUV.xy).x;\n"
+- if (glslVersion == "120")
+- _outStream <<
+- " float depth = texture2D(shadowMap, newUV.xy).x;\n";
+- else
+- {
+- _outStream <<
+- " float depth = textureGrad(shadowMap, newUV.xy, "
+- " vec2(1.0, 1.0), vec2(1.0, 1.0)).x;\n";
+- }
+- _outStream <<
+- // " if (depth >= 1.0 || depth >= uv.z)\n"
+- " if (depth >= 1.0 || depth >= newUV.z)\n"
+- " shadow += 1.0;\n"
+- " }\n"
+- " shadow /= (SHADOW_SAMPLES); \n"
+- " return shadow;\n"
+- "}\n";
+- }
+- else
+- {
+- _outStream <<
+- "float calcSimpleShadow(sampler2D shadowMap, vec4 shadowMapPos)\n"
+- "{\n"
+- " return " << textureStr << "Proj(shadowMap, shadowMapPos).x;\n"
+- "}\n";
+- }
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- Ogre::uint numTextures =
+- _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream << "float calcPSSMDepthShadow(";
+- }
+- else
+- {
+- _outStream << "float calcPSSMSimpleShadow(";
+- }
+-
+- _outStream << "\n ";
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- _outStream << "sampler2D shadowMap" << i << ", ";
+-
+- _outStream << "\n ";
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- _outStream << "vec4 lsPos" << i << ", ";
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream << "\n ";
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- _outStream << "float invShadowmapSize" << i << ", ";
+- }
+-
+- _outStream << "\n"
+- " vec4 pssmSplitPoints, float camDepth)\n"
+- "{\n"
+- " float shadow = 1.0;\n"
+- " // calculate shadow\n";
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- {
+- if (!i)
+- {
+- _outStream << " if (camDepth <= pssmSplitPoints."
+- << this->GetChannel(i) << ")\n";
+- }
+- else if (i < numTextures-1)
+- {
+- _outStream << " else if (camDepth <= pssmSplitPoints."
+- << this->GetChannel(i) << ")\n";
+- }
+- else
+- _outStream << " else\n";
+-
+- _outStream << " {\n";
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream << " shadow = calcDepthShadow(shadowMap" << i
+- << ", lsPos" << i << ", invShadowmapSize" << i << ");\n";
+- }
+- else
+- {
+- _outStream << " shadow = calcSimpleShadow(shadowMap" << i
+- << ", lsPos" << i << ");\n";
+- }
+- _outStream << " }\n";
+- }
+-
+- _outStream << " return shadow;\n"
+- "}\n\n\n";
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpDynamicShadows(
+- const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
+- TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
+-{
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- Ogre::uint numTextures =
+- _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+-
+- _outStream << " float camDepth = uvMisc.z;\n";
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream << " float rtshadow = calcPSSMDepthShadow(";
+- }
+- else
+- {
+- _outStream << " float rtshadow = calcPSSMSimpleShadow(";
+- }
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- _outStream << "shadowMap" << i << ", ";
+-
+- _outStream << "\n ";
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- _outStream << "lightSpacePos" << i << ", ";
+-
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream << "\n ";
+-
+- for (Ogre::uint i = 0; i < numTextures; ++i)
+- _outStream << "inverseShadowmapSize" << i << ", ";
+- }
+- _outStream << "\n" <<
+- " pssmSplitPoints, camDepth);\n";
+- }
+- else
+- {
+- if (_prof->getReceiveDynamicShadowsDepth())
+- {
+- _outStream <<
+- " float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, "
+- "inverseShadowmapSize0);";
+- }
+- else
+- {
+- _outStream <<
+- " float rtshadow = calcSimpleShadow(shadowMap0, lightSpacePos0);";
+- }
+- }
+-
+- _outStream << " shadow = rtshadow;//min(shadow, rtshadow);\n";
+-}
+-
+-/////////////////////////////////////////////////
+-void
+-GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFragmentProgramSource(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- this->generateFpHeader(_prof, _terrain, _tt, _outStream);
+-
+- if (_tt != LOW_LOD)
+- {
+- Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
+- Ogre::uint numLayers = std::min(maxLayers,
+- static_cast<Ogre::uint>(_terrain->getLayerCount()));
+-
+- for (Ogre::uint i = 0; i < numLayers; ++i)
+- this->generateFpLayer(_prof, _terrain, _tt, i, _outStream);
+- }
+-
+- this->generateFpFooter(_prof, _terrain, _tt, _outStream);
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::updateVpParams(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- TechniqueType _tt,
+-#else
+- TechniqueType /*_tt*/,
+-#endif
+- const Ogre::GpuProgramParametersSharedPtr &_params)
+-{
+- _params->setIgnoreMissingParams(true);
+- Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
+- Ogre::uint numLayers = std::min(maxLayers,
+- static_cast<Ogre::uint>(_terrain->getLayerCount()));
+-
+- Ogre::uint numUVMul = numLayers / 4;
+-
+- if (numLayers % 4)
+- ++numUVMul;
+-
+- for (Ogre::uint i = 0; i < numUVMul; ++i)
+- {
+- Ogre::Vector4 uvMul(
+- _terrain->getLayerUVMultiplier(i * 4),
+- _terrain->getLayerUVMultiplier(i * 4 + 1),
+- _terrain->getLayerUVMultiplier(i * 4 + 2),
+- _terrain->getLayerUVMultiplier(i * 4 + 3));
+- _params->setNamedConstant("uvMul" +
+- Ogre::StringConverter::toString(i), uvMul);
+- }
+-
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- if (_terrain->_getUseVertexCompression() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- Ogre::Real baseUVScale = 1.0f / (_terrain->getSize() - 1);
+- _params->setNamedConstant("baseUVScale", baseUVScale);
+- }
+-#endif
+-}
+-
+-/////////////////////////////////////////////////
+-Ogre::String GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::GetChannel(
+-Ogre::uint _idx)
+-{
+- Ogre::uint rem = _idx % 4;
+- switch (rem)
+- {
+- case 0:
+- default:
+- return "x";
+- case 1:
+- return "y";
+- case 2:
+- return "z";
+- case 3:
+- return "w";
+- };
+-}
+-
+-/////////////////////////////////////////////////
+-/////////////////////////////////////////////////
+-// CG Shader helper
+-/////////////////////////////////////////////////
+-/////////////////////////////////////////////////
+-
+-/////////////////////////////////////////////////
+-Ogre::HighLevelGpuProgramPtr
+-GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVertexProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt)
+-{
+- Ogre::HighLevelGpuProgramPtr ret =
+- this->createVertexProgram(_prof, _terrain, _tt);
+-
+- Ogre::StringStream sourceStr;
+- this->generateVertexProgramSource(_prof, _terrain, _tt, sourceStr);
+-
+- ret->setSource(sourceStr.str());
+- ret->load();
+- this->defaultVpParams(_prof, _terrain, _tt, ret);
+-
+- return ret;
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperCg::defaultVpParams(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, const Ogre::HighLevelGpuProgramPtr &_prog)
+-{
+- Ogre::GpuProgramParametersSharedPtr params = _prog->getDefaultParameters();
+- params->setIgnoreMissingParams(true);
+-
+- params->setNamedAutoConstant("worldMatrix",
+- Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
+-
+- params->setNamedAutoConstant("viewProjMatrix",
+- Ogre::GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
+-
+- params->setNamedAutoConstant("lodMorph",
+- Ogre::GpuProgramParameters::ACT_CUSTOM,
+- Ogre::Terrain::LOD_MORPH_CUSTOM_PARAM);
+-
+- params->setNamedAutoConstant("fogParams",
+- Ogre::GpuProgramParameters::ACT_FOG_PARAMS);
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- unsigned int numTextures = 1;
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- params->setNamedAutoConstant("texViewProjMatrix" +
+- Ogre::StringConverter::toString(i),
+- Ogre::GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
+-
+- // Don't add depth range params
+- // if (prof->getReceiveDynamicShadowsDepth())
+- // {
+- // params->setNamedAutoConstant("depthRange" +
+- // Ogre::StringConverter::toString(i),
+- // Ogre::GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
+- // }
+- }
+- }
+-
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- if (_terrain->_getUseVertexCompression() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- Ogre::Matrix4 posIndexToObjectSpace;
+- _terrain->getPointTransform(&posIndexToObjectSpace);
+- params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace);
+- }
+-#endif
+-}
+-
+-/////////////////////////////////////////////////
+-void
+-GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVpDynamicShadows(
+- const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
+- TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
+-{
+- unsigned int numTextures = 1;
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+-
+- // Calculate the position of vertex in light space
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- _outStream << " oLightSpacePos" << i << " = mul(texViewProjMatrix"
+- << i << ", worldPos);\n";
+-
+- // Don't linearize depth range: RTSS PSSM implementation uses
+- // view-space depth
+- // if (prof->getReceiveDynamicShadowsDepth())
+- // {
+- // // make linear
+- // outStream << "oLightSpacePos" << i << ".z = (oLightSpacePos" << i
+- // << ".z - depthRange" << i << ".x) * depthRange" << i
+- // << ".w;\n";
+- // }
+- }
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- _outStream << " // pass cam depth\n oUVMisc.z = oPos.z;\n";
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-unsigned int GzTerrainMatGen::SM2Profile::ShaderHelperCg::
+-generateVpDynamicShadowsParams(unsigned int _texCoord, const SM2Profile *_prof,
+- const Ogre::Terrain * /*_terrain*/, TechniqueType /*_tt*/,
+- Ogre::StringStream &_outStream)
+-{
+- // out semantics & params
+- unsigned int numTextures = 1;
+-
+- if (_prof->getReceiveDynamicShadowsPSSM())
+- {
+- numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
+- }
+-
+- for (unsigned int i = 0; i < numTextures; ++i)
+- {
+- _outStream << ", out float4 oLightSpacePos" << i
+- << " : TEXCOORD" << _texCoord++ << "\n"
+- << ", uniform float4x4 texViewProjMatrix" << i << "\n";
+-
+- // Don't add depth range params
+- // if (prof->getReceiveDynamicShadowsDepth())
+- // {
+- // _outStream << ", uniform float4 depthRange" << i
+- // << " // x = min, y = max, z = range, w = 1/range\n";
+- // }
+- }
+-
+- return _texCoord;
+-}
+-
+-/////////////////////////////////////////////////
+-// This method is identical to
+-// TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg::generateVpHeader()
+-// but is needed because generateVpDynamicShadowsParams() is not declared
+-// virtual.
+-void GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVpHeader(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- _outStream << "void main_vp(\n";
+-
+- bool compression = false;
+-
+-#if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
+- compression = _terrain->_getUseVertexCompression() &&
+- _tt != RENDER_COMPOSITE_MAP;
+-#endif
+-
+- if (compression)
+- {
+- _outStream << "float2 posIndex : POSITION,\nfloat height : TEXCOORD0,\n";
+- }
+- else
+- {
+- _outStream << "float4 pos : POSITION,\nfloat2 uv : TEXCOORD0,\n";
+- }
+-
+- if (_tt != RENDER_COMPOSITE_MAP)
+- _outStream << "float2 delta : TEXCOORD1,\n";
+-
+- _outStream <<
+- "uniform float4x4 worldMatrix,\n"
+- "uniform float4x4 viewProjMatrix,\n"
+- "uniform float2 lodMorph,\n";
+-
+- if (compression)
+- {
+- _outStream <<
+- "uniform float4x4 posIndexToObjectSpace,\n"
+- "uniform float baseUVScale,\n";
+- }
+-
+- // uv multipliers
+- Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
+- Ogre::uint numLayers = std::min(maxLayers,
+- static_cast<unsigned int>(_terrain->getLayerCount()));
+-
+- unsigned int numUVMultipliers = (numLayers / 4);
+
+- if (numLayers % 4)
+- ++numUVMultipliers;
+-
+- for (unsigned int i = 0; i < numUVMultipliers; ++i)
+- _outStream << "uniform float4 uvMul" << i << ",\n";
+-
+- _outStream <<
+- "out float4 oPos : POSITION,\n"
+- "out float4 oPosObj : TEXCOORD0\n";
+-
+- unsigned int texCoordSet = 1;
+- _outStream << ", out float4 oUVMisc : TEXCOORD" << texCoordSet++
+- << " // xy = uv, z = camDepth\n";
+-
+- // layer UV's premultiplied, packed as xy/zw
+- unsigned int numUVSets = numLayers / 2;
+-
+- if (numLayers % 2)
+- ++numUVSets;
+-
+- if (_tt != LOW_LOD)
+- {
+- for (unsigned int i = 0; i < numUVSets; ++i)
+- {
+- _outStream << ", out float4 oUV" << i
+- << " : TEXCOORD" << texCoordSet++ << "\n";
+- }
+- }
+-
+- if (_prof->getParent()->getDebugLevel() && _tt != RENDER_COMPOSITE_MAP)
+- {
+- _outStream << ", out float2 lodInfo : TEXCOORD" << texCoordSet++ << "\n";
+- }
+-
+- bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
+- _tt != RENDER_COMPOSITE_MAP;
+-
+- if (fog)
+- {
+- _outStream <<
+- ", uniform float4 fogParams\n"
+- ", out float fogVal : COLOR\n";
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- {
+- texCoordSet = generateVpDynamicShadowsParams(texCoordSet, _prof,
+- _terrain, _tt, _outStream);
+- }
+-
+- // check we haven't exceeded texture coordinates
+- if (texCoordSet > 8)
+- {
+- OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
+- "Requested options require too many texture coordinate sets! "
+- "Try reducing the number of layers.",
+- __FUNCTION__);
+- }
+-
+- _outStream <<
+- ")\n"
+- "{\n";
+-
+- if (compression)
+- {
+- _outStream << " float4 pos;\n"
+- << " pos = mul(posIndexToObjectSpace, float4(posIndex, height, 1));\n"
+- << " float2 uv = float2(posIndex.x * baseUVScale, 1.0 - "
+- << "(posIndex.y * baseUVScale));\n";
+- }
+-
+- _outStream <<
+- " float4 worldPos = mul(worldMatrix, pos);\n"
+- " oPosObj = pos;\n";
+-
+- if (_tt != RENDER_COMPOSITE_MAP)
+- {
+- // determine whether to apply the LOD morph to this vertex
+- // we store the deltas against all vertices so we only want to apply
+- // the morph to the ones which would disappear. The target LOD which is
+- // being morphed to is stored in lodMorph.y, and the LOD at which
+- // the vertex should be morphed is stored in uv.w. If we subtract
+- // the former from the latter, and arrange to only morph if the
+- // result is negative (it will only be -1 in fact, since after that
+- // the vertex will never be indexed), we will achieve our aim.
+- // sign(vertexLOD - targetLOD) == -1 is to morph
+- _outStream <<
+- " float toMorph = -min(0, sign(delta.y - lodMorph.y));\n";
+-
+- // this will either be 1 (morph) or 0 (don't morph)
+- if (_prof->getParent()->getDebugLevel())
+- {
+- // x == LOD level (-1 since value is target level, we want to
+- // display actual)
+- _outStream << "lodInfo.x = (lodMorph.y - 1) / "
+- << _terrain->getNumLodLevels() << ";\n";
+-
+- // y == LOD morph
+- _outStream << "lodInfo.y = toMorph * lodMorph.x;\n";
+- }
+-
+- // morph
+- switch (_terrain->getAlignment())
+- {
+- case Ogre::Terrain::ALIGN_X_Y:
+- _outStream << " worldPos.z += delta.x * toMorph * lodMorph.x;\n";
+- break;
+- case Ogre::Terrain::ALIGN_X_Z:
+- _outStream << " worldPos.y += delta.x * toMorph * lodMorph.x;\n";
+- break;
+- case Ogre::Terrain::ALIGN_Y_Z:
+- _outStream << " worldPos.x += delta.x * toMorph * lodMorph.x;\n";
+- break;
+- default:
+- gzerr << "Invalid alignment\n";
+- };
+- }
+-
+- // generate UVs
+- if (_tt != LOW_LOD)
+- {
+- for (unsigned int i = 0; i < numUVSets; ++i)
+- {
+- unsigned int layer = i * 2;
+- unsigned int uvMulIdx = layer / 4;
+-
+- _outStream << " oUV" << i << ".xy = " << " uv.xy * uvMul"
+- << uvMulIdx << "." << getChannel(layer) << ";\n";
+- _outStream << " oUV" << i << ".zw = " << " uv.xy * uvMul"
+- << uvMulIdx << "." << getChannel(layer+1) << ";\n";
+- }
+- }
+-}
+-
+-/////////////////////////////////////////////////
+-// This method is identical to
+-// TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg::generateVpFooter()
+-// but is needed because generateVpDynamicShadows() is not declared virtual.
+-void GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVpFooter(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt, Ogre::StringStream &_outStream)
+-{
+- _outStream << " oPos = mul(viewProjMatrix, worldPos);\n"
+- << " oUVMisc.xy = uv.xy;\n";
+-
+- bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
+- _tt != RENDER_COMPOSITE_MAP;
+- if (fog)
+- {
+- if (_terrain->getSceneManager()->getFogMode() == Ogre::FOG_LINEAR)
+- {
+- _outStream <<
+- " fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
+- }
+- else
+- {
+- _outStream <<
+- " fogVal = 1 - saturate(1 / (exp(oPos.z * fogParams.x)));\n";
+- }
+- }
+-
+- if (_prof->isShadowingEnabled(_tt, _terrain))
+- this->generateVpDynamicShadows(_prof, _terrain, _tt, _outStream);
+-
+- _outStream << "}\n";
+-}
+-
+-/////////////////////////////////////////////////
+-void GzTerrainMatGen::SM2Profile::ShaderHelperCg::
+-generateVertexProgramSource(const SM2Profile *_prof,
+- const Ogre::Terrain* _terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream)
+-{
+- this->generateVpHeader(_prof, _terrain, _tt, _outStream);
+-
+- if (_tt != LOW_LOD)
+- {
+- unsigned int maxLayers = _prof->getMaxLayers(_terrain);
+- unsigned int numLayers = std::min(maxLayers,
+- static_cast<unsigned int>(_terrain->getLayerCount()));
+-
+- for (unsigned int i = 0; i < numLayers; ++i)
+- this->generateVpLayer(_prof, _terrain, _tt, i, _outStream);
+- }
+-
+- this->generateVpFooter(_prof, _terrain, _tt, _outStream);
+-}
+-
+-/////////////////////////////////////////////////
+-Ogre::HighLevelGpuProgramPtr
+-GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateFragmentProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain, TechniqueType _tt)
+-{
+- Ogre::HighLevelGpuProgramPtr ret = this->createFragmentProgram(_prof,
+- _terrain, _tt);
+-
+- Ogre::StringStream sourceStr;
+-
+- this->generateFragmentProgramSource(_prof, _terrain, _tt, sourceStr);
+-
+- ret->setSource(sourceStr.str());
+-
+- ret->load();
+-
+- this->defaultFpParams(_prof, _terrain, _tt, ret);
+-
+- return ret;
+-}
++// /////////////////////////////////////////////////
++// GzTerrainMatGen::SM2Profile::SM2Profile(
++// Ogre::TerrainMaterialGenerator *_parent, const Ogre::String &_name,
++// const Ogre::String &_desc)
++// : TerrainMaterialGeneratorA::SM2Profile(_parent, _name, _desc)
++// {
++// this->mShaderGen = nullptr;
++// }
++//
++// /////////////////////////////////////////////////
++// GzTerrainMatGen::SM2Profile::~SM2Profile()
++// {
++// // Because the base SM2Profile has no virtual destructor:
++// delete this->mShaderGen;
++// this->mShaderGen = nullptr;
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::addTechnique(
++// const Ogre::MaterialPtr &_mat, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt)
++// {
++// // Initiate specialized mShaderGen
++// // Ogre::GpuProgramManager &gmgr = Ogre::GpuProgramManager::getSingleton();
++//
++// Ogre::HighLevelGpuProgramManager &hmgr =
++// Ogre::HighLevelGpuProgramManager::getSingleton();
++//
++// if (!this->mShaderGen)
++// {
++// // By default we use the GLSL shaders.
++// if (hmgr.isLanguageSupported("glsl"))
++// {
++// this->mShaderGen = OGRE_NEW
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL();
++// }
++// else
++// {
++// gzthrow("No supported shader languages");
++// }
++//
++// // Uncomment this to use cg shaders. I'm keeping the CG
++// // shader for reference. There is some more code to switch, located
++// // below, to enable CG shaders.
++// // if (hmgr.isLanguageSupported("cg"))
++// // {
++// // this->mShaderGen = OGRE_NEW
++// // // This will use Ogre's CG shader
++// // // Ogre::TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg();
++// // //
++// // // This will use our CG shader, which has terrain shadows
++// // GzTerrainMatGen::SM2Profile::ShaderHelperCg();
++// // }
++//
++// // check SM3 features
++// this->mSM3Available =
++// Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0");
++//
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// this->mSM4Available =
++// Ogre::GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0");
++// #endif
++// }
++//
++// // Unfortunately this doesn't work
++// // Default implementation
++// // TerrainMaterialGeneratorA::SM2Profile::addTechnique(mat, terrain, tt);
++//
++// // So we have to replicate the entire method:
++// Ogre::Technique *tech = _mat->createTechnique();
++//
++// // Only supporting one pass
++// Ogre::Pass *pass = tech->createPass();
++//
++// // Doesn't delegate to the proper method otherwise
++// Ogre::HighLevelGpuProgramPtr vprog =
++// ((GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*)this->mShaderGen)
++// // Use this line if running Ogre's CG shaders
++// // ((TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg*)this->mShaderGen)
++// // Use this line if running our CG shaders
++// // ((GzTerrainMatGen::SM2Profile::ShaderHelperCg*)this->mShaderGen)
++// ->generateVertexProgram(this, _terrain, _tt);
++//
++// // DEBUG: std::cout << "VertShader[" << vprog->getName() << "]:\n"
++// // << vprog->getSource() << "\n\n";
++//
++// Ogre::HighLevelGpuProgramPtr fprog =
++// ((GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*)this->mShaderGen)
++// // Use this line if running Ogre's CG shaders
++// // ((TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg*)this->mShaderGen)
++// // Use this line if running our CG shaders
++// // ((GzTerrainMatGen::SM2Profile::ShaderHelperCg*)this->mShaderGen)
++// ->generateFragmentProgram(this, _terrain, _tt);
++//
++// // DEBUG: std::cout << "FragShader[" << fprog->getName() << "]:\n"
++// // << fprog->getSource() << "\n\n";
++//
++// pass->setVertexProgram(vprog->getName());
++// pass->setFragmentProgram(fprog->getName());
++//
++// if (_tt == Ogre::HIGH_LOD || _tt == Ogre::RENDER_COMPOSITE_MAP)
++// {
++// // global normal map
++// Ogre::TextureUnitState* tu = pass->createTextureUnitState();
++// tu->setTextureName(_terrain->getTerrainNormalMap()->getName());
++// tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
++//
++// // global colour map
++// if (_terrain->getGlobalColourMapEnabled() &&
++// this->isGlobalColourMapEnabled())
++// {
++// tu = pass->createTextureUnitState(
++// _terrain->getGlobalColourMap()->getName());
++// tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
++// }
++//
++// // light map
++// if (this->isLightmapEnabled())
++// {
++// tu = pass->createTextureUnitState(_terrain->getLightmap()->getName());
++// tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
++// }
++//
++// // blend maps
++// unsigned int maxLayers = this->getMaxLayers(_terrain);
++//
++// unsigned int numBlendTextures = std::min(
++// _terrain->getBlendTextureCount(maxLayers),
++// _terrain->getBlendTextureCount());
++//
++// unsigned int numLayers = std::min(
++// maxLayers, static_cast<unsigned int>(_terrain->getLayerCount()));
++//
++// for (unsigned int i = 0; i < numBlendTextures; ++i)
++// {
++// tu = pass->createTextureUnitState(_terrain->getBlendTextureName(i));
++// tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
++// }
++//
++// // layer textures
++// for (unsigned int i = 0; i < numLayers; ++i)
++// {
++// // diffuse / specular
++// pass->createTextureUnitState(_terrain->getLayerTextureName(i, 0));
++//
++// // normal / height
++// pass->createTextureUnitState(_terrain->getLayerTextureName(i, 1));
++// }
++// }
++// else
++// {
++// // Ogre::LOW_LOD textures
++// // composite map
++// Ogre::TextureUnitState *tu = pass->createTextureUnitState();
++// tu->setTextureName(_terrain->getCompositeMap()->getName());
++// tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
++// }
++//
++// // Add shadow textures (always at the end)
++// if (this->isShadowingEnabled(_tt, _terrain))
++// {
++// unsigned int numTextures = 1;
++//
++// if (this->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = this->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// Ogre::TextureUnitState *tu = pass->createTextureUnitState();
++// tu->setContentType(Ogre::TextureUnitState::CONTENT_SHADOW);
++// tu->setTextureAddressingMode(Ogre::TextureUnitState::TAM_BORDER);
++// tu->setTextureBorderColour(Ogre::ColourValue::White);
++// }
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// // generate() and generateForCompositeMap() are identical to
++// // TerrainMaterialGeneratorA implementation, the only reason for repeating
++// // them is that, unfortunately, addTechnique() is not declared virtual.
++// Ogre::MaterialPtr GzTerrainMatGen::SM2Profile::generate(
++// const Ogre::Terrain *_terrain)
++// {
++// // re-use old material if exists
++// Ogre::MaterialPtr mat = _terrain->_getMaterial();
++//
++// if (mat.isNull())
++// {
++// Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton();
++//
++// // it's important that the names are deterministic for a given terrain, so
++// // use the terrain pointer as an ID
++// const Ogre::String &matName = _terrain->getMaterialName();
++// mat = matMgr.getByName(matName);
++//
++// if (mat.isNull())
++// {
++// mat = matMgr.create(matName,
++// Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
++// }
++// }
++//
++// // clear everything
++// mat->removeAllTechniques();
++//
++// // Automatically disable normal & parallax mapping if card cannot handle it
++// // We do this rather than having a specific technique for it since it's
++// // simpler.
++// Ogre::GpuProgramManager &gmgr = Ogre::GpuProgramManager::getSingleton();
++//
++// if (!gmgr.isSyntaxSupported("ps_4_0") &&
++// !gmgr.isSyntaxSupported("ps_3_0") &&
++// !gmgr.isSyntaxSupported("ps_2_x") &&
++// !gmgr.isSyntaxSupported("fp40") &&
++// !gmgr.isSyntaxSupported("arbfp1"))
++// {
++// this->setLayerNormalMappingEnabled(false);
++// this->setLayerParallaxMappingEnabled(false);
++// }
++//
++// this->addTechnique(mat, _terrain, Ogre::HIGH_LOD);
++//
++// // LOD
++// if (this->mCompositeMapEnabled)
++// {
++// this->addTechnique(mat, _terrain, Ogre::LOW_LOD);
++// Ogre::Material::LodValueList lodValues;
++// lodValues.push_back(
++// Ogre::TerrainGlobalOptions::getSingleton().getCompositeMapDistance());
++//
++// mat->setLodLevels(lodValues);
++// Ogre::Technique *lowLodTechnique = mat->getTechnique(1);
++// lowLodTechnique->setLodIndex(1);
++// }
++//
++// this->UpdateParams(mat, _terrain);
++//
++// return mat;
++// }
++//
++// /////////////////////////////////////////////////
++// Ogre::MaterialPtr GzTerrainMatGen::SM2Profile::generateForCompositeMap(
++// const Ogre::Terrain *_terrain)
++// {
++// // re-use old material if exists
++// Ogre::MaterialPtr mat = _terrain->_getCompositeMapMaterial();
++//
++// if (mat.isNull())
++// {
++// Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton();
++//
++// // it's important that the names are deterministic for a given terrain, so
++// // use the terrain pointer as an ID
++// const Ogre::String &matName = _terrain->getMaterialName() + "/comp";
++//
++// mat = matMgr.getByName(matName);
++//
++// if (mat.isNull())
++// {
++// mat = matMgr.create(matName,
++// Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
++// }
++// }
++//
++// // clear everything
++// mat->removeAllTechniques();
++//
++// this->addTechnique(mat, _terrain, Ogre::RENDER_COMPOSITE_MAP);
++//
++// this->UpdateParamsForCompositeMap(mat, _terrain);
++//
++// return mat;
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::UpdateParams(const Ogre::MaterialPtr &_mat,
++// const Ogre::Terrain *_terrain)
++// {
++// static_cast<GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*>(
++// this->mShaderGen)->updateParams(this, _mat, _terrain, false);
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::UpdateParamsForCompositeMap(
++// const Ogre::MaterialPtr &_mat, const Ogre::Terrain *_terrain)
++// {
++// static_cast<GzTerrainMatGen::SM2Profile::ShaderHelperGLSL*>(
++// this->mShaderGen)->updateParams(this, _mat, _terrain, true);
++// }
++//
++// /////////////////////////////////////////////////
++// /////////////////////////////////////////////////
++// // GLSL Shader helper
++// /////////////////////////////////////////////////
++// /////////////////////////////////////////////////
++//
++// /////////////////////////////////////////////////
++// Ogre::HighLevelGpuProgramPtr
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVertexProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt)
++// {
++// Ogre::HighLevelGpuProgramPtr ret =
++// this->createVertexProgram(_prof, _terrain, _tt);
++//
++// Ogre::StringStream sourceStr;
++// this->generateVertexProgramSource(_prof, _terrain, _tt, sourceStr);
++//
++// ret->setSource(sourceStr.str());
++// ret->load();
++// this->defaultVpParams(_prof, _terrain, _tt, ret);
++//
++// return ret;
++// }
++//
++// /////////////////////////////////////////////////
++// Ogre::HighLevelGpuProgramPtr
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFragmentProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt)
++// {
++// Ogre::HighLevelGpuProgramPtr ret = this->createFragmentProgram(_prof,
++// _terrain, _tt);
++//
++// Ogre::StringStream sourceStr;
++//
++// this->generateFragmentProgramSource(_prof, _terrain, _tt, sourceStr);
++//
++// ret->setSource(sourceStr.str());
++//
++// ret->load();
++//
++// this->defaultFpParams(_prof, _terrain, _tt, ret);
++//
++// Ogre::GpuProgramParametersSharedPtr params = ret->getDefaultParameters();
++// params->setIgnoreMissingParams(false);
++//
++// Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
++// Ogre::uint numBlendTextures = std::min(
++// _terrain->getBlendTextureCount(maxLayers),
++// _terrain->getBlendTextureCount());
++//
++// Ogre::uint numLayers = std::min(maxLayers,
++// static_cast<Ogre::uint>(_terrain->getLayerCount()));
++//
++// int samplerCounter = 0;
++//
++// if (_tt == Ogre::LOW_LOD)
++// params->setNamedConstant("compositeMap", samplerCounter++);
++// else
++// {
++// params->setNamedConstant("globalNormal", samplerCounter++);
++//
++// if (_terrain->getGlobalColourMapEnabled() &&
++// _prof->isGlobalColourMapEnabled())
++// {
++// params->setNamedConstant("globalColourMap", samplerCounter++);
++// }
++//
++// if (_prof->isLightmapEnabled())
++// params->setNamedConstant("lightMap", samplerCounter++);
++//
++// for (Ogre::uint i = 0; i < numBlendTextures; ++i)
++// {
++// params->setNamedConstant("blendTex" +
++// boost::lexical_cast<std::string>(i), samplerCounter++);
++// }
++//
++// for (Ogre::uint i = 0; i < numLayers; ++i)
++// {
++// params->setNamedConstant("difftex" +
++// boost::lexical_cast<std::string>(i), samplerCounter++);
++// params->setNamedConstant("normtex" +
++// boost::lexical_cast<std::string>(i), samplerCounter++);
++// }
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// Ogre::uint numTextures = 1;
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// {
++// params->setNamedConstant("shadowMap" +
++// boost::lexical_cast<std::string>(i), samplerCounter++);
++// }
++// }
++//
++// return ret;
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::updateParams(
++// const SM2Profile *_prof, const Ogre::MaterialPtr &_mat,
++// const Ogre::Terrain *_terrain, bool _compositeMap)
++// {
++// Ogre::Pass *p = _mat->getTechnique(0)->getPass(0);
++//
++// if (_compositeMap)
++// {
++// this->updateVpParams(_prof, _terrain, Ogre::RENDER_COMPOSITE_MAP,
++// p->getVertexProgramParameters());
++// this->updateFpParams(_prof, _terrain, Ogre::RENDER_COMPOSITE_MAP,
++// p->getFragmentProgramParameters());
++// }
++// else
++// {
++// // high lod
++// this->updateVpParams(_prof, _terrain, Ogre::HIGH_LOD,
++// p->getVertexProgramParameters());
++// this->updateFpParams(_prof, _terrain, Ogre::HIGH_LOD,
++// p->getFragmentProgramParameters());
++//
++// if (_prof->isCompositeMapEnabled())
++// {
++// // low lod
++// p = _mat->getTechnique(1)->getPass(0);
++// this->updateVpParams(_prof, _terrain, Ogre::LOW_LOD,
++// p->getVertexProgramParameters());
++// this->updateFpParams(_prof, _terrain, Ogre::LOW_LOD,
++// p->getFragmentProgramParameters());
++// }
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::
++// generateVertexProgramSource(const SM2Profile *_prof,
++// const Ogre::Terrain* _terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream)
++// {
++// this->generateVpHeader(_prof, _terrain, _tt, _outStream);
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// unsigned int maxLayers = _prof->getMaxLayers(_terrain);
++// unsigned int numLayers = std::min(maxLayers,
++// static_cast<unsigned int>(_terrain->getLayerCount()));
++//
++// for (unsigned int i = 0; i < numLayers; ++i)
++// this->generateVpLayer(_prof, _terrain, _tt, i, _outStream);
++// }
++//
++// this->generateVpFooter(_prof, _terrain, _tt, _outStream);
++// }
++//
++// /////////////////////////////////////////////////
++// // This method is identical to
++// // TerrainMaterialGeneratorA::SM2Profile::ShaderHelperGLSL::generateVpHeader()
++// // but is needed because generateVpDynamicShadowsParams() is not declared
++// // virtual.
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVpHeader(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// bool compression = false;
++//
++// _outStream << "#version " << glslVersion << "\n\n";
++//
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// compression = _terrain->_getUseVertexCompression() &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++//
++// if (compression)
++// {
++// // The parameter "in vec4 vertex;" is automatically bound by OGRE.
++// // The parameter "in vec4 uv0'" is automatically bound by OGRE.
++// _outStream << vpInStr << " vec4 vertex;\n"
++// << vpInStr << " vec4 uv0;\n";
++// }
++// else
++// #endif
++// {
++// // The parameter "in vec4 vertex;" is automatically bound by OGRE.
++// // The parameter "in vec4 uv0'" is automatically bound by OGRE.
++// _outStream << vpInStr << " vec4 vertex;\n"
++// << vpInStr << " vec4 uv0;\n";
++// }
++//
++// if (_tt != Ogre::RENDER_COMPOSITE_MAP)
++// // The parameter "in vec4 uv1'" is automatically bound by OGRE.
++// _outStream << vpInStr << " vec4 uv1;\n";
++//
++// _outStream <<
++// "uniform mat4 worldMatrix;\n"
++// "uniform mat4 viewProjMatrix;\n"
++// "uniform vec2 lodMorph;\n";
++//
++// if (compression)
++// {
++// _outStream <<
++// "uniform mat4 posIndexToObjectSpace;\n"
++// "uniform float baseUVScale;\n";
++// }
++//
++//
++// // uv multipliers
++// unsigned int maxLayers = _prof->getMaxLayers(_terrain);
++// unsigned int numLayers = std::min(maxLayers,
++// static_cast<unsigned int>(_terrain->getLayerCount()));
++//
++// unsigned int numUVMultipliers = (numLayers / 4);
++//
++// if (numLayers % 4)
++// ++numUVMultipliers;
++//
++// for (unsigned int i = 0; i < numUVMultipliers; ++i)
++// _outStream << "uniform vec4 uvMul" << i << ";\n";
++//
++// _outStream <<
++// vpOutStr << " vec4 position;\n";
++//
++// unsigned int texCoordSet = 1;
++// _outStream << vpOutStr << " vec4 uvMisc;\n";
++//
++// // layer UV's premultiplied, packed as xy/zw
++// unsigned int numUVSets = numLayers / 2;
++//
++// if (numLayers % 2)
++// ++numUVSets;
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// for (unsigned int i = 0; i < numUVSets; ++i)
++// {
++// _outStream << vpOutStr << " vec4 layerUV" << i << ";\n";
++// }
++// }
++//
++// if (_prof->getParent()->getDebugLevel() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// _outStream << vpOutStr << " vec2 lodInfo;\n";
++// }
++//
++// bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++//
++// if (fog)
++// {
++// _outStream <<
++// "uniform vec4 fogParams;\n"
++// << vpOutStr << " float fogVal;\n";
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// texCoordSet = this->generateVpDynamicShadowsParams(texCoordSet, _prof,
++// _terrain, _tt, _outStream);
++// }
++//
++// // check we haven't exceeded texture coordinates
++// if (texCoordSet > 8)
++// {
++// OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
++// "Requested options require too many texture coordinate sets! "
++// "Try reducing the number of layers.",
++// __FUNCTION__);
++// }
++//
++// _outStream << "void main()\n"
++// << "{\n";
++//
++// if (compression)
++// {
++// _outStream
++// << " vec4 pos = posIndexToObjectSpace * "
++// << "vec4(vertex.x, vertex.y, uv0.x, 1.0);\n"
++//
++// << " vec2 uv = vec2(vertex.x * baseUVScale, 1.0 - "
++// << "(vertex.y * baseUVScale));\n";
++// }
++// else
++// {
++// _outStream
++// << " vec4 pos = vertex;\n"
++// << " vec2 uv = vec2(uv0.x, uv0.y);\n";
++// }
++//
++// _outStream << " vec4 worldPos = worldMatrix * pos;\n";
++// _outStream << " position = pos;\n";
++//
++// if (_tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// // determine whether to apply the LOD morph to this vertex
++// // we store the deltas against all vertices so we only want to apply
++// // the morph to the ones which would disappear. The target LOD which is
++// // being morphed to is stored in lodMorph.y, and the LOD at which
++// // the vertex should be morphed is stored in uv.w. If we subtract
++// // the former from the latter, and arrange to only morph if the
++// // result is negative (it will only be -1 in fact, since after that
++// // the vertex will never be indexed), we will achieve our aim.
++// // sign(vertexLOD - targetLOD) == -1 is to morph
++// _outStream <<
++// " float toMorph = -min(0.0, sign(uv1.y - lodMorph.y));\n";
++//
++// // this will either be 1 (morph) or 0 (don't morph)
++// if (_prof->getParent()->getDebugLevel())
++// {
++// // x == LOD level (-1 since value is target level, we want to
++// // display actual)
++// _outStream << "lodInfo.x = (lodMorph.y - 1.0) / "
++// << _terrain->getNumLodLevels() << ";\n";
++//
++// // y == LOD morph
++// _outStream << "lodInfo.y = toMorph * lodMorph.x;\n";
++// }
++//
++// // morph
++// switch (_terrain->getAlignment())
++// {
++// case Ogre::Terrain::ALIGN_X_Y:
++// _outStream << " worldPos.z += uv1.x * toMorph * lodMorph.x;\n";
++// break;
++// case Ogre::Terrain::ALIGN_X_Z:
++// _outStream << " worldPos.y += uv1.x * toMorph * lodMorph.x;\n";
++// break;
++// case Ogre::Terrain::ALIGN_Y_Z:
++// _outStream << " worldPos.x += uv1.x * toMorph * lodMorph.x;\n";
++// break;
++// default:
++// gzerr << "Invalid alignment\n";
++// };
++// }
++//
++// // generate UVs
++// if (_tt != Ogre::LOW_LOD)
++// {
++// for (unsigned int i = 0; i < numUVSets; ++i)
++// {
++// unsigned int layer = i * 2;
++// unsigned int uvMulIdx = layer / 4;
++//
++// _outStream << " layerUV" << i << ".xy = " << " uv.xy * uvMul"
++// << uvMulIdx << "." << this->GetChannel(layer) << ";\n";
++// _outStream << " layerUV" << i << ".zw = " << " uv.xy * uvMul"
++// << uvMulIdx << "." << this->GetChannel(layer+1) << ";\n";
++// }
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// // This method is identical to
++// // TerrainMaterialGeneratorA::SM2Profile::ShaderHelperGLSL::generateVpFooter()
++// // but is needed because generateVpDynamicShadows() is not declared virtual.
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVpFooter(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// _outStream << " gl_Position = viewProjMatrix * worldPos;\n"
++// << " uvMisc.xy = uv.xy;\n";
++//
++// bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++// if (fog)
++// {
++// if (_terrain->getSceneManager()->getFogMode() == Ogre::FOG_LINEAR)
++// {
++// _outStream <<
++// " fogVal = clamp((oPos.z - fogParams.y) * fogParams.w, 0.0, 1.0);\n";
++// }
++// else
++// {
++// _outStream <<
++// " fogVal = 1 - clamp(1 / (exp(oPos.z * fogParams.x)), 0.0, 1.0);\n";
++// }
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// this->generateVpDynamicShadows(_prof, _terrain, _tt, _outStream);
++//
++// _outStream << "}\n";
++// }
++//
++// /////////////////////////////////////////////////
++// void
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateVpDynamicShadows(
++// const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
++// Ogre::TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
++// {
++// unsigned int numTextures = 1;
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++//
++// // Calculate the position of vertex in light space
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// _outStream << " lightSpacePos" << i << " = texViewProjMatrix"
++// << i << " * worldPos;\n";
++//
++// // Don't linearize depth range: RTSS PSSM implementation uses
++// // view-space depth
++// // if (prof->getReceiveDynamicShadowsDepth())
++// // {
++// // // make linear
++// // outStream << "lightSpacePos" << i << ".z = (lightSpacePos" << i
++// // << ".z - depthRange" << i << ".x) * depthRange" << i
++// // << ".w;\n";
++// // }
++// }
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// _outStream << " // pass cam depth\n uvMisc.z = gl_Position.z;\n";
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::defaultVpParams(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, const Ogre::HighLevelGpuProgramPtr &_prog)
++// {
++// Ogre::GpuProgramParametersSharedPtr params = _prog->getDefaultParameters();
++// params->setIgnoreMissingParams(true);
++//
++// params->setNamedAutoConstant("worldMatrix",
++// Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
++//
++// params->setNamedAutoConstant("viewProjMatrix",
++// Ogre::GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
++//
++// params->setNamedAutoConstant("lodMorph",
++// Ogre::GpuProgramParameters::ACT_CUSTOM,
++// Ogre::Terrain::LOD_MORPH_CUSTOM_PARAM);
++//
++// params->setNamedAutoConstant("fogParams",
++// Ogre::GpuProgramParameters::ACT_FOG_PARAMS);
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// unsigned int numTextures = 1;
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// params->setNamedAutoConstant("texViewProjMatrix" +
++// Ogre::StringConverter::toString(i),
++// Ogre::GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
++//
++// // Don't add depth range params
++// // if (prof->getReceiveDynamicShadowsDepth())
++// // {
++// // params->setNamedAutoConstant("depthRange" +
++// // Ogre::StringConverter::toString(i),
++// // Ogre::GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
++// // }
++// }
++// }
++//
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// if (_terrain->_getUseVertexCompression() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// Ogre::Matrix4 posIndexToObjectSpace;
++// _terrain->getPointTransform(&posIndexToObjectSpace);
++// params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace);
++// }
++// #endif
++// }
++//
++// /////////////////////////////////////////////////
++// unsigned int GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::
++// generateVpDynamicShadowsParams(unsigned int _texCoord, const SM2Profile *_prof,
++// const Ogre::Terrain * /*_terrain*/, Ogre::TechniqueType /*_tt*/,
++// Ogre::StringStream &_outStream)
++// {
++// // out semantics & params
++// unsigned int numTextures = 1;
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++//
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// _outStream << vpOutStr << " vec4 lightSpacePos" << i << ";\n"
++// << "uniform mat4 texViewProjMatrix" << i << ";\n";
++//
++// // Don't add depth range params
++// // if (prof->getReceiveDynamicShadowsDepth())
++// // {
++// // _outStream << ", uniform float4 depthRange" << i
++// // << " // x = min, y = max, z = range, w = 1/range\n";
++// // }
++// }
++//
++// return _texCoord;
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpHeader(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// _outStream << "#version " << glslVersion << "\n\n";
++//
++// _outStream <<
++// "vec4 expand(vec4 v)\n"
++// "{\n"
++// " return v * 2 - 1;\n"
++// "}\n\n";
++//
++// _outStream <<
++// "vec4 lit(float NdotL, float NdotH, float m)\n"
++// "{\n"
++// " float specular = (NdotL > 0) ? pow(max(0.0, NdotH), m) : 0.0;\n"
++// " return vec4(1.0, max(0.0, NdotL), specular, 1.0);\n"
++// "}\n";
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// this->generateFpDynamicShadowsHelpers(_prof, _terrain, _tt, _outStream);
++//
++// _outStream <<
++// fpInStr << " vec4 position;\n";
++//
++// Ogre::uint texCoordSet = 1;
++// _outStream << fpInStr << " vec4 uvMisc;\n";
++//
++// // UV's premultiplied, packed as xy/zw
++// Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
++// Ogre::uint numBlendTextures = std::min(
++// _terrain->getBlendTextureCount(maxLayers),
++// _terrain->getBlendTextureCount());
++// Ogre::uint numLayers = std::min(maxLayers,
++// static_cast<Ogre::uint>(_terrain->getLayerCount()));
++//
++// Ogre::uint numUVSets = numLayers / 2;
++//
++// if (numLayers % 2)
++// ++numUVSets;
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// for (Ogre::uint i = 0; i < numUVSets; ++i)
++// {
++// _outStream <<
++// fpInStr << " vec4 layerUV" << i << ";\n";
++// }
++// }
++//
++// if (_prof->getParent()->getDebugLevel() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// _outStream << fpInStr << " vec2 lodInfo;\n";
++// }
++//
++// bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++//
++// if (fog)
++// {
++// _outStream <<
++// "uniform vec3 fogColour;\n"
++// << fpInStr << " float fogVal;\n";
++// }
++//
++// Ogre::uint currentSamplerIdx = 0;
++//
++// _outStream <<
++// // Only 1 light supported in this version
++// // deferred shading profile / generator later, ok? :)
++// "uniform vec3 ambient;\n"
++// "uniform vec4 lightPosObjSpace;\n"
++// "uniform vec3 lightDiffuseColour;\n"
++// "uniform vec3 lightSpecularColour;\n"
++// "uniform vec3 eyePosObjSpace;\n"
++// // pack scale, bias and specular
++// "uniform vec4 scaleBiasSpecular;\n";
++//
++// if (_tt == Ogre::LOW_LOD)
++// {
++// // single composite map covers all the others below
++// _outStream << "uniform sampler2D compositeMap;\n";
++// }
++// else
++// {
++// _outStream << "uniform sampler2D globalNormal;\n";
++//
++// if (_terrain->getGlobalColourMapEnabled() &&
++// _prof->isGlobalColourMapEnabled())
++// {
++// _outStream << "uniform sampler2D globalColourMap;\n";
++// }
++//
++// if (_prof->isLightmapEnabled())
++// {
++// _outStream << "uniform sampler2D lightMap;\n";
++// }
++//
++// // Blend textures - sampler definitions
++// for (Ogre::uint i = 0; i < numBlendTextures; ++i)
++// {
++// _outStream << "uniform sampler2D blendTex" << i << ";\n";
++// }
++//
++// // Layer textures - sampler definitions & UV multipliers
++// for (Ogre::uint i = 0; i < numLayers; ++i)
++// {
++// _outStream << "uniform sampler2D difftex" << i << ";\n";
++// _outStream << "uniform sampler2D normtex" << i << ";\n";
++// }
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// this->generateFpDynamicShadowsParams(&texCoordSet, &currentSamplerIdx,
++// _prof, _terrain, _tt, _outStream);
++// }
++//
++// // check we haven't exceeded samplers
++// if (currentSamplerIdx > 16)
++// {
++// OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
++// "Requested options require too many texture samplers! "
++// "Try reducing the number of layers.", __FUNCTION__);
++// }
++//
++// std::string outputColTypeStr = "vec4";
++// if (glslVersion != "120")
++// {
++// _outStream << "out vec4 outputCol;\n";
++// outputColTypeStr = "";
++// }
++//
++// _outStream <<
++// "void main()\n"
++// "{\n"
++// " float shadow = 1.0;\n"
++// " vec2 uv = uvMisc.xy;\n"
++// " " << outputColTypeStr << " outputCol = vec4(0.0, 0.0, 0.0, 1.0);\n";
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// // global normal
++// _outStream << " vec3 normal = expand("
++// << textureStr << "(globalNormal, uv)).xyz;\n";
++// }
++//
++// _outStream <<
++// " vec3 lightDir =\n"
++// " lightPosObjSpace.xyz - (position.xyz * lightPosObjSpace.w);\n"
++// " vec3 eyeDir = eyePosObjSpace - position.xyz;\n"
++//
++// // set up accumulation areas
++// " vec3 diffuse = vec3(0.0, 0.0, 0.0);\n"
++// " float specular = 0.0;\n";
++//
++// if (_tt == Ogre::LOW_LOD)
++// {
++// // we just do a single calculation from composite map
++// _outStream <<
++// " vec4 composite = " << textureStr << "(compositeMap, uv);\n"
++// " diffuse = composite.xyz;\n";
++// // TODO - specular; we'll need normals for this!
++// }
++// else
++// {
++// // set up the blend values
++// for (Ogre::uint i = 0; i < numBlendTextures; ++i)
++// {
++// _outStream << " vec4 blendTexVal" << i
++// << " = " << textureStr << "(blendTex" << i << ", uv);\n";
++// }
++//
++// if (_prof->isLayerNormalMappingEnabled())
++// {
++// // derive the tangent space basis
++// // we do this in the pixel shader because we don't have per-vertex normals
++// // because of the LOD, we use a normal map
++// // tangent is always +x or -z in object space depending on alignment
++// switch (_terrain->getAlignment())
++// {
++// case Ogre::Terrain::ALIGN_X_Y:
++// case Ogre::Terrain::ALIGN_X_Z:
++// _outStream << " vec3 tangent = vec3(1.0, 0.0, 0.0);\n";
++// break;
++// case Ogre::Terrain::ALIGN_Y_Z:
++// _outStream << " vec3 tangent = vec3(0.0, 0.0, -1.0);\n";
++// break;
++// default:
++// gzerr << "Invalid terrain alignment\n";
++// break;
++// };
++//
++// _outStream << " vec3 binormal = normalize(cross(tangent, normal));\n";
++// // note, now we need to re-cross to derive tangent again because it
++// // wasn't orthonormal
++// _outStream << " tangent = normalize(cross(normal, binormal));\n";
++// // derive final matrix
++// /*_outStream << " mat3 TBN = mat3(tangent.x, tangent.y, tangent.z,"
++// "binormal.x, binormal.y, binormal.z,"
++// "normal.x, normal.y, normal.z);\n";
++// */
++//
++// // set up lighting result placeholders for interpolation
++// _outStream << " vec4 litRes, litResLayer;\n";
++// _outStream << " vec3 TSlightDir, TSeyeDir, TShalfAngle, TSnormal;\n";
++// if (_prof->isLayerParallaxMappingEnabled())
++// _outStream << " float displacement;\n";
++// // move
++// _outStream << " TSlightDir = normalize(vec3(dot(tangent, lightDir),"
++// "dot(binormal, lightDir),"
++// "dot(normal, lightDir)));\n";
++// _outStream << " TSeyeDir = normalize(vec3(dot(tangent, eyeDir),"
++// "dot(binormal, eyeDir),"
++// "dot(normal, eyeDir)));\n";
++// }
++// else
++// {
++// // simple per-pixel lighting with no normal mapping
++// _outStream << " lightDir = normalize(lightDir);\n";
++// _outStream << " eyeDir = normalize(eyeDir);\n";
++// _outStream << " vec3 halfAngle = normalize(lightDir + eyeDir);\n";
++//
++// _outStream << " vec4 litRes = lit(dot(lightDir, normal), "
++// "dot(halfAngle, normal), scaleBiasSpecular.z);\n";
++// }
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// void
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpDynamicShadowsParams(
++// Ogre::uint *_texCoord, Ogre::uint *_sampler, const SM2Profile *_prof,
++// const Ogre::Terrain * /*_terrain*/, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream)
++// {
++// if (_tt == Ogre::HIGH_LOD)
++// this->mShadowSamplerStartHi = *_sampler;
++// else if (_tt == Ogre::LOW_LOD)
++// this->mShadowSamplerStartLo = *_sampler;
++//
++// // in semantics & params
++// Ogre::uint numTextures = 1;
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// _outStream << "uniform vec4 pssmSplitPoints;\n";
++// }
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// {
++// _outStream << fpInStr <<
++// " vec4 lightSpacePos" << i << ";\n" <<
++// "uniform sampler2D shadowMap" << i << ";\n";
++//
++// *_sampler = *_sampler + 1;
++// *_texCoord = *_texCoord + 1;
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream <<
++// "uniform float inverseShadowmapSize" << i << ";\n";
++// }
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpLayer(
++// const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
++// Ogre::TechniqueType _tt, Ogre::uint _layer,
++// Ogre::StringStream &_outStream)
++// {
++// Ogre::uint uvIdx = _layer / 2;
++// Ogre::String uvChannels = (_layer % 2) ? ".zw" : ".xy";
++// Ogre::uint blendIdx = (_layer-1) / 4;
++// Ogre::String blendChannel = this->GetChannel(_layer-1);
++// Ogre::String blendWeightStr = Ogre::String("blendTexVal") +
++// Ogre::StringConverter::toString(blendIdx) + "." + blendChannel;
++//
++// // generate early-out conditional
++// // Disable - causing some issues even when trying to force the use of texldd
++// // if (layer && prof->_isSM3Available())
++// // _outStream << " if (" << blendWeightStr << " > 0.0003)\n {\n";
++//
++// // generate UV
++// _outStream << " vec2 uv" << _layer << " = layerUV" << uvIdx
++// << uvChannels << ";\n";
++//
++// // calculate lighting here if normal mapping
++// if (_prof->isLayerNormalMappingEnabled())
++// {
++// if (_prof->isLayerParallaxMappingEnabled() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// // modify UV - note we have to sample an extra time
++// _outStream << " displacement = " << textureStr << "(normtex" << _layer
++// << ", uv" << _layer << ").w\n"
++// " * scaleBiasSpecular.x + scaleBiasSpecular.y;\n";
++// _outStream << " uv" << _layer << " += TSeyeDir.xy * displacement;\n";
++// }
++//
++// // access TS normal map
++// _outStream << " TSnormal = expand(" << textureStr << "(normtex"
++// << _layer << ", uv" << _layer << ")).xyz;\n";
++// _outStream << " TShalfAngle = normalize(TSlightDir + TSeyeDir);\n";
++//
++// _outStream << " litResLayer = lit(dot(TSlightDir, TSnormal), "
++// "dot(TShalfAngle, TSnormal), scaleBiasSpecular.z);\n";
++//
++// if (!_layer)
++// _outStream << " litRes = litResLayer;\n";
++// else
++// _outStream << " litRes = mix(litRes, litResLayer, "
++// << blendWeightStr << ");\n";
++// }
++//
++// // sample diffuse texture
++// _outStream << " vec4 diffuseSpecTex" << _layer
++// << " = " << textureStr << "(difftex" << _layer << ", uv" << _layer
++// << ");\n";
++//
++// // apply to common
++// if (!_layer)
++// {
++// _outStream << " diffuse = diffuseSpecTex0.xyz;\n";
++// if (_prof->isLayerSpecularMappingEnabled())
++// _outStream << " specular = diffuseSpecTex0.w;\n";
++// }
++// else
++// {
++// _outStream << " diffuse = mix(diffuse, diffuseSpecTex" << _layer
++// << ".xyz, " << blendWeightStr << ");\n";
++//
++// if (_prof->isLayerSpecularMappingEnabled())
++// {
++// _outStream << " specular = mix(specular, diffuseSpecTex" << _layer
++// << ".w, " << blendWeightStr << ");\n";
++// }
++// }
++//
++// // End early-out
++// // Disable - causing some issues even when trying to force the use of texldd
++// // if (layer && prof->_isSM3Available())
++// // _outStream << " } // early-out blend value\n";
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpFooter(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// if (_tt == Ogre::LOW_LOD)
++// {
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// this->generateFpDynamicShadows(_prof, _terrain, _tt, _outStream);
++// _outStream << " outputCol.xyz = diffuse * rtshadow;\n";
++// }
++// else
++// {
++// _outStream << " outputCol.xyz = diffuse;\n";
++// }
++// }
++// else
++// {
++// if (_terrain->getGlobalColourMapEnabled() &&
++// _prof->isGlobalColourMapEnabled())
++// {
++// // sample colour map and apply to diffuse
++// _outStream << " diffuse *= " << textureStr
++// << "(globalColourMap, uv).xyz;\n";
++// }
++//
++// if (_prof->isLightmapEnabled())
++// {
++// // sample lightmap
++// _outStream << " shadow = " << textureStr << "(lightMap, uv).x;\n";
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// this->generateFpDynamicShadows(_prof, _terrain, _tt, _outStream);
++// }
++//
++// // diffuse lighting
++// _outStream << " outputCol.xyz += ambient * diffuse + litRes.y * "
++// "lightDiffuseColour * diffuse * shadow;\n";
++//
++// // specular default
++// if (!_prof->isLayerSpecularMappingEnabled())
++// _outStream << " specular = 1.0;\n";
++//
++// if (_tt == Ogre::RENDER_COMPOSITE_MAP)
++// {
++// // Lighting embedded in alpha
++// _outStream << " outputCol.w = shadow;\n";
++// }
++// else
++// {
++// // Apply specular
++// _outStream << " outputCol.xyz += litRes.z * lightSpecularColour * "
++// "specular * shadow;\n";
++//
++// if (_prof->getParent()->getDebugLevel())
++// {
++// _outStream << " outputCol.xy += lodInfo.xy;\n";
++// }
++// }
++// }
++//
++// bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++// if (fog)
++// {
++// _outStream << " outputCol.xyz = mix(outputCol.xyz, fogColour, fogVal);\n";
++// }
++//
++// if (glslVersion == "120")
++// _outStream << " gl_FragColor = outputCol;\n";
++//
++// // Final return
++// _outStream << "\n}\n";
++// }
++//
++// /////////////////////////////////////////////////
++// void
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpDynamicShadowsHelpers(
++// const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
++// Ogre::TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
++// {
++// // TODO make filtering configurable
++// _outStream <<
++// "// Simple PCF\n"
++// "// Number of samples in one dimension (square for total samples)\n"
++// "#define NUM_SHADOW_SAMPLES_1D 2.0\n"
++// "#define SHADOW_FILTER_SCALE 1.0\n"
++//
++// "#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D\n"
++//
++// "vec4 offsetSample(vec4 uv, vec2 offset, float invMapSize)\n"
++// "{\n"
++// " return vec4(uv.xy + offset * invMapSize * uv.w, uv.z, uv.w);\n"
++// "}\n";
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream <<
++// "float calcDepthShadow(sampler2D shadowMap, vec4 uv, "
++// "float invShadowMapSize)\n"
++// "{\n"
++// " // 4-sample PCF\n"
++// " float shadow = 0.0;\n"
++// " float offset = (NUM_SHADOW_SAMPLES_1D/2.0 - 0.5) *SHADOW_FILTER_SCALE;"
++// "\n"
++// " for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE)\n"
++// " for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE)\n"
++// " {\n"
++// " vec4 newUV = offsetSample(uv, vec2(x, y), invShadowMapSize);\n"
++// " // manually project and assign derivatives\n"
++// " // to avoid gradient issues inside loops\n"
++// " newUV = newUV / newUV.w;\n";
++// // The following line used to be:
++// // " float depth = tex2d(shadowMap, newUV.xy).x;\n"
++// if (glslVersion == "120")
++// _outStream <<
++// " float depth = texture2D(shadowMap, newUV.xy).x;\n";
++// else
++// {
++// _outStream <<
++// " float depth = textureGrad(shadowMap, newUV.xy, "
++// " vec2(1.0, 1.0), vec2(1.0, 1.0)).x;\n";
++// }
++// _outStream <<
++// // " if (depth >= 1.0 || depth >= uv.z)\n"
++// " if (depth >= 1.0 || depth >= newUV.z)\n"
++// " shadow += 1.0;\n"
++// " }\n"
++// " shadow /= (SHADOW_SAMPLES); \n"
++// " return shadow;\n"
++// "}\n";
++// }
++// else
++// {
++// _outStream <<
++// "float calcSimpleShadow(sampler2D shadowMap, vec4 shadowMapPos)\n"
++// "{\n"
++// " return " << textureStr << "Proj(shadowMap, shadowMapPos).x;\n"
++// "}\n";
++// }
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// Ogre::uint numTextures =
++// _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream << "float calcPSSMDepthShadow(";
++// }
++// else
++// {
++// _outStream << "float calcPSSMSimpleShadow(";
++// }
++//
++// _outStream << "\n ";
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// _outStream << "sampler2D shadowMap" << i << ", ";
++//
++// _outStream << "\n ";
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// _outStream << "vec4 lsPos" << i << ", ";
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream << "\n ";
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// _outStream << "float invShadowmapSize" << i << ", ";
++// }
++//
++// _outStream << "\n"
++// " vec4 pssmSplitPoints, float camDepth)\n"
++// "{\n"
++// " float shadow = 1.0;\n"
++// " // calculate shadow\n";
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// {
++// if (!i)
++// {
++// _outStream << " if (camDepth <= pssmSplitPoints."
++// << this->GetChannel(i) << ")\n";
++// }
++// else if (i < numTextures-1)
++// {
++// _outStream << " else if (camDepth <= pssmSplitPoints."
++// << this->GetChannel(i) << ")\n";
++// }
++// else
++// _outStream << " else\n";
++//
++// _outStream << " {\n";
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream << " shadow = calcDepthShadow(shadowMap" << i
++// << ", lsPos" << i << ", invShadowmapSize" << i << ");\n";
++// }
++// else
++// {
++// _outStream << " shadow = calcSimpleShadow(shadowMap" << i
++// << ", lsPos" << i << ");\n";
++// }
++// _outStream << " }\n";
++// }
++//
++// _outStream << " return shadow;\n"
++// "}\n\n\n";
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFpDynamicShadows(
++// const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
++// Ogre::TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
++// {
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// Ogre::uint numTextures =
++// _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++//
++// _outStream << " float camDepth = uvMisc.z;\n";
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream << " float rtshadow = calcPSSMDepthShadow(";
++// }
++// else
++// {
++// _outStream << " float rtshadow = calcPSSMSimpleShadow(";
++// }
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// _outStream << "shadowMap" << i << ", ";
++//
++// _outStream << "\n ";
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// _outStream << "lightSpacePos" << i << ", ";
++//
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream << "\n ";
++//
++// for (Ogre::uint i = 0; i < numTextures; ++i)
++// _outStream << "inverseShadowmapSize" << i << ", ";
++// }
++// _outStream << "\n" <<
++// " pssmSplitPoints, camDepth);\n";
++// }
++// else
++// {
++// if (_prof->getReceiveDynamicShadowsDepth())
++// {
++// _outStream <<
++// " float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, "
++// "inverseShadowmapSize0);";
++// }
++// else
++// {
++// _outStream <<
++// " float rtshadow = calcSimpleShadow(shadowMap0, lightSpacePos0);";
++// }
++// }
++//
++// _outStream << " shadow = rtshadow;//min(shadow, rtshadow);\n";
++// }
++//
++// /////////////////////////////////////////////////
++// void
++// GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::generateFragmentProgramSource(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// this->generateFpHeader(_prof, _terrain, _tt, _outStream);
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
++// Ogre::uint numLayers = std::min(maxLayers,
++// static_cast<Ogre::uint>(_terrain->getLayerCount()));
++//
++// for (Ogre::uint i = 0; i < numLayers; ++i)
++// this->generateFpLayer(_prof, _terrain, _tt, i, _outStream);
++// }
++//
++// this->generateFpFooter(_prof, _terrain, _tt, _outStream);
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::updateVpParams(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// Ogre::TechniqueType _tt,
++// #else
++// Ogre::TechniqueType /*_tt*/,
++// #endif
++// const Ogre::GpuProgramParametersSharedPtr &_params)
++// {
++// _params->setIgnoreMissingParams(true);
++// Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
++// Ogre::uint numLayers = std::min(maxLayers,
++// static_cast<Ogre::uint>(_terrain->getLayerCount()));
++//
++// Ogre::uint numUVMul = numLayers / 4;
++//
++// if (numLayers % 4)
++// ++numUVMul;
++//
++// for (Ogre::uint i = 0; i < numUVMul; ++i)
++// {
++// Ogre::Vector4 uvMul(
++// _terrain->getLayerUVMultiplier(i * 4),
++// _terrain->getLayerUVMultiplier(i * 4 + 1),
++// _terrain->getLayerUVMultiplier(i * 4 + 2),
++// _terrain->getLayerUVMultiplier(i * 4 + 3));
++// _params->setNamedConstant("uvMul" +
++// Ogre::StringConverter::toString(i), uvMul);
++// }
++//
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// if (_terrain->_getUseVertexCompression() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// Ogre::Real baseUVScale = 1.0f / (_terrain->getSize() - 1);
++// _params->setNamedConstant("baseUVScale", baseUVScale);
++// }
++// #endif
++// }
++//
++// /////////////////////////////////////////////////
++// Ogre::String GzTerrainMatGen::SM2Profile::ShaderHelperGLSL::GetChannel(
++// Ogre::uint _idx)
++// {
++// Ogre::uint rem = _idx % 4;
++// switch (rem)
++// {
++// case 0:
++// default:
++// return "x";
++// case 1:
++// return "y";
++// case 2:
++// return "z";
++// case 3:
++// return "w";
++// };
++// }
++//
++// /////////////////////////////////////////////////
++// /////////////////////////////////////////////////
++// // CG Shader helper
++// /////////////////////////////////////////////////
++// /////////////////////////////////////////////////
++//
++// /////////////////////////////////////////////////
++// Ogre::HighLevelGpuProgramPtr
++// GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVertexProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt)
++// {
++// Ogre::HighLevelGpuProgramPtr ret =
++// this->createVertexProgram(_prof, _terrain, _tt);
++//
++// Ogre::StringStream sourceStr;
++// this->generateVertexProgramSource(_prof, _terrain, _tt, sourceStr);
++//
++// ret->setSource(sourceStr.str());
++// ret->load();
++// this->defaultVpParams(_prof, _terrain, _tt, ret);
++//
++// return ret;
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperCg::defaultVpParams(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, const Ogre::HighLevelGpuProgramPtr &_prog)
++// {
++// Ogre::GpuProgramParametersSharedPtr params = _prog->getDefaultParameters();
++// params->setIgnoreMissingParams(true);
++//
++// params->setNamedAutoConstant("worldMatrix",
++// Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
++//
++// params->setNamedAutoConstant("viewProjMatrix",
++// Ogre::GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
++//
++// params->setNamedAutoConstant("lodMorph",
++// Ogre::GpuProgramParameters::ACT_CUSTOM,
++// Ogre::Terrain::LOD_MORPH_CUSTOM_PARAM);
++//
++// params->setNamedAutoConstant("fogParams",
++// Ogre::GpuProgramParameters::ACT_FOG_PARAMS);
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// unsigned int numTextures = 1;
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// params->setNamedAutoConstant("texViewProjMatrix" +
++// Ogre::StringConverter::toString(i),
++// Ogre::GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
++//
++// // Don't add depth range params
++// // if (prof->getReceiveDynamicShadowsDepth())
++// // {
++// // params->setNamedAutoConstant("depthRange" +
++// // Ogre::StringConverter::toString(i),
++// // Ogre::GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
++// // }
++// }
++// }
++//
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// if (_terrain->_getUseVertexCompression() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// Ogre::Matrix4 posIndexToObjectSpace;
++// _terrain->getPointTransform(&posIndexToObjectSpace);
++// params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace);
++// }
++// #endif
++// }
++//
++// /////////////////////////////////////////////////
++// void
++// GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVpDynamicShadows(
++// const SM2Profile *_prof, const Ogre::Terrain * /*_terrain*/,
++// Ogre::TechniqueType /*_tt*/, Ogre::StringStream &_outStream)
++// {
++// unsigned int numTextures = 1;
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++//
++// // Calculate the position of vertex in light space
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// _outStream << " oLightSpacePos" << i << " = mul(texViewProjMatrix"
++// << i << ", worldPos);\n";
++//
++// // Don't linearize depth range: RTSS PSSM implementation uses
++// // view-space depth
++// // if (prof->getReceiveDynamicShadowsDepth())
++// // {
++// // // make linear
++// // outStream << "oLightSpacePos" << i << ".z = (oLightSpacePos" << i
++// // << ".z - depthRange" << i << ".x) * depthRange" << i
++// // << ".w;\n";
++// // }
++// }
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// _outStream << " // pass cam depth\n oUVMisc.z = oPos.z;\n";
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// unsigned int GzTerrainMatGen::SM2Profile::ShaderHelperCg::
++// generateVpDynamicShadowsParams(unsigned int _texCoord, const SM2Profile *_prof,
++// const Ogre::Terrain * /*_terrain*/, Ogre::TechniqueType /*_tt*/,
++// Ogre::StringStream &_outStream)
++// {
++// // out semantics & params
++// unsigned int numTextures = 1;
++//
++// if (_prof->getReceiveDynamicShadowsPSSM())
++// {
++// numTextures = _prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
++// }
++//
++// for (unsigned int i = 0; i < numTextures; ++i)
++// {
++// _outStream << ", out float4 oLightSpacePos" << i
++// << " : TEXCOORD" << _texCoord++ << "\n"
++// << ", uniform float4x4 texViewProjMatrix" << i << "\n";
++//
++// // Don't add depth range params
++// // if (prof->getReceiveDynamicShadowsDepth())
++// // {
++// // _outStream << ", uniform float4 depthRange" << i
++// // << " // x = min, y = max, z = range, w = 1/range\n";
++// // }
++// }
++//
++// return _texCoord;
++// }
++//
++// /////////////////////////////////////////////////
++// // This method is identical to
++// // TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg::generateVpHeader()
++// // but is needed because generateVpDynamicShadowsParams() is not declared
++// // virtual.
++// void GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVpHeader(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// _outStream << "void main_vp(\n";
++//
++// bool compression = false;
++//
++// #if OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 8
++// compression = _terrain->_getUseVertexCompression() &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++// #endif
++//
++// if (compression)
++// {
++// _outStream << "float2 posIndex : POSITION,\nfloat height : TEXCOORD0,\n";
++// }
++// else
++// {
++// _outStream << "float4 pos : POSITION,\nfloat2 uv : TEXCOORD0,\n";
++// }
++//
++// if (_tt != Ogre::RENDER_COMPOSITE_MAP)
++// _outStream << "float2 delta : TEXCOORD1,\n";
++//
++// _outStream <<
++// "uniform float4x4 worldMatrix,\n"
++// "uniform float4x4 viewProjMatrix,\n"
++// "uniform float2 lodMorph,\n";
++//
++// if (compression)
++// {
++// _outStream <<
++// "uniform float4x4 posIndexToObjectSpace,\n"
++// "uniform float baseUVScale,\n";
++// }
++//
++// // uv multipliers
++// Ogre::uint maxLayers = _prof->getMaxLayers(_terrain);
++// Ogre::uint numLayers = std::min(maxLayers,
++// static_cast<unsigned int>(_terrain->getLayerCount()));
++//
++// unsigned int numUVMultipliers = (numLayers / 4);
++//
++// if (numLayers % 4)
++// ++numUVMultipliers;
++//
++// for (unsigned int i = 0; i < numUVMultipliers; ++i)
++// _outStream << "uniform float4 uvMul" << i << ",\n";
++//
++// _outStream <<
++// "out float4 oPos : POSITION,\n"
++// "out float4 oPosObj : TEXCOORD0\n";
++//
++// unsigned int texCoordSet = 1;
++// _outStream << ", out float4 oUVMisc : TEXCOORD" << texCoordSet++
++// << " // xy = uv, z = camDepth\n";
++//
++// // layer UV's premultiplied, packed as xy/zw
++// unsigned int numUVSets = numLayers / 2;
++//
++// if (numLayers % 2)
++// ++numUVSets;
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// for (unsigned int i = 0; i < numUVSets; ++i)
++// {
++// _outStream << ", out float4 oUV" << i
++// << " : TEXCOORD" << texCoordSet++ << "\n";
++// }
++// }
++//
++// if (_prof->getParent()->getDebugLevel() && _tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// _outStream << ", out float2 lodInfo : TEXCOORD" << texCoordSet++ << "\n";
++// }
++//
++// bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++//
++// if (fog)
++// {
++// _outStream <<
++// ", uniform float4 fogParams\n"
++// ", out float fogVal : COLOR\n";
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// {
++// texCoordSet = generateVpDynamicShadowsParams(texCoordSet, _prof,
++// _terrain, _tt, _outStream);
++// }
++//
++// // check we haven't exceeded texture coordinates
++// if (texCoordSet > 8)
++// {
++// OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS,
++// "Requested options require too many texture coordinate sets! "
++// "Try reducing the number of layers.",
++// __FUNCTION__);
++// }
++//
++// _outStream <<
++// ")\n"
++// "{\n";
++//
++// if (compression)
++// {
++// _outStream << " float4 pos;\n"
++// << " pos = mul(posIndexToObjectSpace, float4(posIndex, height, 1));\n"
++// << " float2 uv = float2(posIndex.x * baseUVScale, 1.0 - "
++// << "(posIndex.y * baseUVScale));\n";
++// }
++//
++// _outStream <<
++// " float4 worldPos = mul(worldMatrix, pos);\n"
++// " oPosObj = pos;\n";
++//
++// if (_tt != Ogre::RENDER_COMPOSITE_MAP)
++// {
++// // determine whether to apply the LOD morph to this vertex
++// // we store the deltas against all vertices so we only want to apply
++// // the morph to the ones which would disappear. The target LOD which is
++// // being morphed to is stored in lodMorph.y, and the LOD at which
++// // the vertex should be morphed is stored in uv.w. If we subtract
++// // the former from the latter, and arrange to only morph if the
++// // result is negative (it will only be -1 in fact, since after that
++// // the vertex will never be indexed), we will achieve our aim.
++// // sign(vertexLOD - targetLOD) == -1 is to morph
++// _outStream <<
++// " float toMorph = -min(0, sign(delta.y - lodMorph.y));\n";
++//
++// // this will either be 1 (morph) or 0 (don't morph)
++// if (_prof->getParent()->getDebugLevel())
++// {
++// // x == LOD level (-1 since value is target level, we want to
++// // display actual)
++// _outStream << "lodInfo.x = (lodMorph.y - 1) / "
++// << _terrain->getNumLodLevels() << ";\n";
++//
++// // y == LOD morph
++// _outStream << "lodInfo.y = toMorph * lodMorph.x;\n";
++// }
++//
++// // morph
++// switch (_terrain->getAlignment())
++// {
++// case Ogre::Terrain::ALIGN_X_Y:
++// _outStream << " worldPos.z += delta.x * toMorph * lodMorph.x;\n";
++// break;
++// case Ogre::Terrain::ALIGN_X_Z:
++// _outStream << " worldPos.y += delta.x * toMorph * lodMorph.x;\n";
++// break;
++// case Ogre::Terrain::ALIGN_Y_Z:
++// _outStream << " worldPos.x += delta.x * toMorph * lodMorph.x;\n";
++// break;
++// default:
++// gzerr << "Invalid alignment\n";
++// };
++// }
++//
++// // generate UVs
++// if (_tt != Ogre::LOW_LOD)
++// {
++// for (unsigned int i = 0; i < numUVSets; ++i)
++// {
++// unsigned int layer = i * 2;
++// unsigned int uvMulIdx = layer / 4;
++//
++// _outStream << " oUV" << i << ".xy = " << " uv.xy * uvMul"
++// << uvMulIdx << "." << getChannel(layer) << ";\n";
++// _outStream << " oUV" << i << ".zw = " << " uv.xy * uvMul"
++// << uvMulIdx << "." << getChannel(layer+1) << ";\n";
++// }
++// }
++// }
++//
++// /////////////////////////////////////////////////
++// // This method is identical to
++// // TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg::generateVpFooter()
++// // but is needed because generateVpDynamicShadows() is not declared virtual.
++// void GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateVpFooter(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt, Ogre::StringStream &_outStream)
++// {
++// _outStream << " oPos = mul(viewProjMatrix, worldPos);\n"
++// << " oUVMisc.xy = uv.xy;\n";
++//
++// bool fog = _terrain->getSceneManager()->getFogMode() != Ogre::FOG_NONE &&
++// _tt != Ogre::RENDER_COMPOSITE_MAP;
++// if (fog)
++// {
++// if (_terrain->getSceneManager()->getFogMode() == Ogre::FOG_LINEAR)
++// {
++// _outStream <<
++// " fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
++// }
++// else
++// {
++// _outStream <<
++// " fogVal = 1 - saturate(1 / (exp(oPos.z * fogParams.x)));\n";
++// }
++// }
++//
++// if (_prof->isShadowingEnabled(_tt, _terrain))
++// this->generateVpDynamicShadows(_prof, _terrain, _tt, _outStream);
++//
++// _outStream << "}\n";
++// }
++//
++// /////////////////////////////////////////////////
++// void GzTerrainMatGen::SM2Profile::ShaderHelperCg::
++// generateVertexProgramSource(const SM2Profile *_prof,
++// const Ogre::Terrain* _terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream)
++// {
++// this->generateVpHeader(_prof, _terrain, _tt, _outStream);
++//
++// if (_tt != Ogre::LOW_LOD)
++// {
++// unsigned int maxLayers = _prof->getMaxLayers(_terrain);
++// unsigned int numLayers = std::min(maxLayers,
++// static_cast<unsigned int>(_terrain->getLayerCount()));
++//
++// for (unsigned int i = 0; i < numLayers; ++i)
++// this->generateVpLayer(_prof, _terrain, _tt, i, _outStream);
++// }
++//
++// this->generateVpFooter(_prof, _terrain, _tt, _outStream);
++// }
++//
++// /////////////////////////////////////////////////
++// Ogre::HighLevelGpuProgramPtr
++// GzTerrainMatGen::SM2Profile::ShaderHelperCg::generateFragmentProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt)
++// {
++// Ogre::HighLevelGpuProgramPtr ret = this->createFragmentProgram(_prof,
++// _terrain, _tt);
++//
++// Ogre::StringStream sourceStr;
++//
++// this->generateFragmentProgramSource(_prof, _terrain, _tt, sourceStr);
++//
++// ret->setSource(sourceStr.str());
++//
++// ret->load();
++//
++// this->defaultFpParams(_prof, _terrain, _tt, ret);
++//
++// return ret;
++// }
+
+ /////////////////////////////////////////////////
+ /////////////////////////////////////////////////
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/HeightmapPrivate.hh patched/gazebo-9.0.0/gazebo/rendering/HeightmapPrivate.hh
+--- original/gazebo-9.0.0/gazebo/rendering/HeightmapPrivate.hh 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/HeightmapPrivate.hh 2018-06-02 22:56:03.580661743 +0200
+@@ -25,6 +25,9 @@
+
+ #include "gazebo/rendering/RenderTypes.hh"
+
++// ogre 1.11 fix
++// #include "deps/ogre111/OgreTerrainMaterialShaderHelpers.h"
++
+ namespace Ogre
+ {
+ class PageManager;
+@@ -56,183 +59,184 @@
+ /// \brief Destructor
+ public: virtual ~GzTerrainMatGen();
+
+- /// \brief Shader model 2 profile target.
+- public: class SM2Profile :
+- public Ogre::TerrainMaterialGeneratorA::SM2Profile
+- {
+- /// \brief Constructor
+- public: SM2Profile(Ogre::TerrainMaterialGenerator *_parent,
+- const Ogre::String &_name, const Ogre::String &_desc);
+-
+- /// \brief Destructor
+- public: virtual ~SM2Profile();
+-
+- public: Ogre::MaterialPtr generate(const Ogre::Terrain *_terrain);
+-
+- public: Ogre::MaterialPtr generateForCompositeMap(
+- const Ogre::Terrain *_terrain);
+-
+- public: void UpdateParams(const Ogre::MaterialPtr &_mat,
+- const Ogre::Terrain *_terrain);
+-
+- public: void UpdateParamsForCompositeMap(const Ogre::MaterialPtr &_mat,
+- const Ogre::Terrain *_terrain);
+-
+- protected: virtual void addTechnique(const Ogre::MaterialPtr &_mat,
+- const Ogre::Terrain *_terrain, TechniqueType _tt);
+-
+-#ifdef __clang__
+-#pragma clang diagnostic push
+-#pragma clang diagnostic ignored "-Woverloaded-virtual"
+-#endif // ifdef __clang__
+- /// \brief Utility class to help with generating shaders for GLSL.
+- /// The class contains a collection of functions that are used to
+- /// dynamically generate a complete vertex or fragment shader program
+- /// in a string format.
+- protected: class ShaderHelperGLSL :
+- public Ogre::TerrainMaterialGeneratorA::SM2Profile::ShaderHelperGLSL
+- {
+- public: virtual Ogre::HighLevelGpuProgramPtr generateVertexProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt);
+-
+- public: virtual Ogre::HighLevelGpuProgramPtr generateFragmentProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt);
+-
+- public: virtual void updateParams(const SM2Profile *_prof,
+- const Ogre::MaterialPtr &_mat,
+- const Ogre::Terrain *_terrain, bool _compositeMap);
+-
+- protected: virtual void generateVpHeader(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateVpFooter(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateVertexProgramSource(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void defaultVpParams(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- const Ogre::HighLevelGpuProgramPtr &_prog);
+-
+- protected: virtual unsigned int generateVpDynamicShadowsParams(
+- unsigned int _texCoordStart, const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateVpDynamicShadows(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateFpHeader(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain,
+- TechniqueType tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateFpLayer(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType tt,
+- Ogre::uint _layer,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateFpFooter(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain,
+- TechniqueType tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateFpDynamicShadowsParams(
+- Ogre::uint *_texCoord, Ogre::uint *_sampler,
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateFpDynamicShadowsHelpers(
+- const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain,
+- TechniqueType tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: void generateFpDynamicShadows(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateFragmentProgramSource(
+- const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain,
+- TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void updateVpParams(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- const Ogre::GpuProgramParametersSharedPtr &_params);
+-
+- private: Ogre::String GetChannel(Ogre::uint _idx);
+- };
+-
+- // Needed to allow access from ShaderHelperGLSL to protected members
+- // of SM2Profile.
+- friend ShaderHelperGLSL;
+-
+- /// Keeping the CG shader for reference.
+- /// \brief Utility class to help with generating shaders for Cg / HLSL.
+- /// Original implementation from Ogre that generates Cg shaders
+- protected: class ShaderHelperCg :
+- public Ogre::TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg
+- {
+- public: virtual Ogre::HighLevelGpuProgramPtr generateFragmentProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt);
+-
+- public: virtual Ogre::HighLevelGpuProgramPtr generateVertexProgram(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt);
+-
+- protected: virtual void generateVpHeader(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateVpFooter(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateVertexProgramSource(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void defaultVpParams(const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- const Ogre::HighLevelGpuProgramPtr &_prog);
+-
+- protected: virtual unsigned int generateVpDynamicShadowsParams(
+- unsigned int _texCoordStart, const SM2Profile *_prof,
+- const Ogre::Terrain *_terrain, TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+-
+- protected: virtual void generateVpDynamicShadows(
+- const SM2Profile *_prof, const Ogre::Terrain *_terrain,
+- TechniqueType _tt,
+- Ogre::StringStream &_outStream);
+- };
+-
+- // Needed to allow access from ShaderHelperCg to protected members
+- // of SM2Profile.
+- friend ShaderHelperCg;
+-
+-#ifdef __clang__
+-#pragma clang diagnostic pop
+-
+-// ifdef __clang__
+-#endif
+- };
++// /// \brief Shader model 2 profile target.
++// public: class SM2Profile :
++// public Ogre::TerrainMaterialGeneratorA::SM2Profile
++// {
++// /// \brief Constructor
++// public: SM2Profile(Ogre::TerrainMaterialGenerator *_parent,
++// const Ogre::String &_name, const Ogre::String &_desc);
++//
++// /// \brief Destructor
++// public: virtual ~SM2Profile();
++//
++// public: Ogre::MaterialPtr generate(const Ogre::Terrain *_terrain);
++//
++// public: Ogre::MaterialPtr generateForCompositeMap(
++// const Ogre::Terrain *_terrain);
++//
++// public: void UpdateParams(const Ogre::MaterialPtr &_mat,
++// const Ogre::Terrain *_terrain);
++//
++// public: void UpdateParamsForCompositeMap(const Ogre::MaterialPtr &_mat,
++// const Ogre::Terrain *_terrain);
++//
++// protected: virtual void addTechnique(const Ogre::MaterialPtr &_mat,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt);
++//
++// #ifdef __clang__
++// #pragma clang diagnostic push
++// #pragma clang diagnostic ignored "-Woverloaded-virtual"
++// #endif // ifdef __clang__
++// /// \brief Utility class to help with generating shaders for GLSL.
++// /// The class contains a collection of functions that are used to
++// /// dynamically generate a complete vertex or fragment shader program
++// /// in a string format.
++// protected: class ShaderHelperGLSL :
++// public Ogre::ShaderHelperGLSL
++// {
++// public: virtual Ogre::HighLevelGpuProgramPtr generateVertexProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt);
++//
++// public: virtual Ogre::HighLevelGpuProgramPtr generateFragmentProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt);
++//
++// public: virtual void updateParams(const SM2Profile *_prof,
++// const Ogre::MaterialPtr &_mat,
++// const Ogre::Terrain *_terrain, bool _compositeMap);
++//
++// protected: virtual void generateVpHeader(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateVpFooter(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateVertexProgramSource(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void defaultVpParams(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// const Ogre::HighLevelGpuProgramPtr &_prog);
++//
++// protected: virtual unsigned int generateVpDynamicShadowsParams(
++// unsigned int _texCoordStart, const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateVpDynamicShadows(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateFpHeader(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateFpLayer(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType tt,
++// Ogre::uint _layer,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateFpFooter(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateFpDynamicShadowsParams(
++// Ogre::uint *_texCoord, Ogre::uint *_sampler,
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateFpDynamicShadowsHelpers(
++// const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: void generateFpDynamicShadows(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateFragmentProgramSource(
++// const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void updateVpParams(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// const Ogre::GpuProgramParametersSharedPtr &_params);
++//
++// private: Ogre::String GetChannel(Ogre::uint _idx);
++// };
++//
++// // Needed to allow access from ShaderHelperGLSL to protected members
++// // of SM2Profile.
++// friend ShaderHelperGLSL;
++//
++// /// Keeping the CG shader for reference.
++// /// \brief Utility class to help with generating shaders for Cg / HLSL.
++// /// Original implementation from Ogre that generates Cg shaders
++// protected: class ShaderHelperCg :
++// public Ogre::ShaderHelperCg
++// {
++// public: virtual Ogre::HighLevelGpuProgramPtr generateFragmentProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt);
++//
++// public: virtual Ogre::HighLevelGpuProgramPtr generateVertexProgram(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt);
++//
++// protected: virtual void generateVpHeader(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateVpFooter(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateVertexProgramSource(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void defaultVpParams(const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// const Ogre::HighLevelGpuProgramPtr &_prog);
++//
++// protected: virtual unsigned int generateVpDynamicShadowsParams(
++// unsigned int _texCoordStart, const SM2Profile *_prof,
++// const Ogre::Terrain *_terrain, Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++//
++// protected: virtual void generateVpDynamicShadows(
++// const SM2Profile *_prof, const Ogre::Terrain *_terrain,
++// Ogre::TechniqueType _tt,
++// Ogre::StringStream &_outStream);
++// };
++//
++// // Needed to allow access from ShaderHelperCg to protected members
++// // of SM2Profile.
++// friend ShaderHelperCg;
++//
++// #ifdef __clang__
++// #pragma clang diagnostic pop
++//
++// // ifdef __clang__
++// #endif
++// };
+ };
+
++
+ /// \internal
+ /// \brief Custom terrain material generator.
+ /// A custom material generator that lets user specify their own material
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/InertiaVisual.cc patched/gazebo-9.0.0/gazebo/rendering/InertiaVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/InertiaVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/InertiaVisual.cc 2018-06-02 18:58:05.734368911 +0200
+@@ -104,7 +104,7 @@
+ p6 += _pose.Pos();
+
+ dPtr->crossLines = this->CreateDynamicLine(rendering::RENDERING_LINE_LIST);
+- dPtr->crossLines->setMaterial("Gazebo/Green");
++ dPtr->crossLines->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/Green"));
+ dPtr->crossLines->AddPoint(p1);
+ dPtr->crossLines->AddPoint(p2);
+ dPtr->crossLines->AddPoint(p3);
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/LaserVisual.cc patched/gazebo-9.0.0/gazebo/rendering/LaserVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/LaserVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/LaserVisual.cc 2018-06-02 19:04:35.671943290 +0200
+@@ -132,25 +132,25 @@
+ // intersected an object.
+ dPtr->rayStrips.push_back(
+ this->CreateDynamicLine(rendering::RENDERING_TRIANGLE_STRIP));
+- dPtr->rayStrips[j]->setMaterial("Gazebo/BlueLaser");
++ dPtr->rayStrips[j]->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/BlueLaser"));
+
+ // No hit ray strips fill in-between the ray lines in areas that have
+ // not intersected an object.
+ dPtr->noHitRayStrips.push_back(
+ this->CreateDynamicLine(rendering::RENDERING_TRIANGLE_STRIP));
+- dPtr->noHitRayStrips[j]->setMaterial("Gazebo/LightBlueLaser");
++ dPtr->noHitRayStrips[j]->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/LightBlueLaser"));
+
+ // Deadzone ray fans display areas that are between the sensor's origin
+ // and start of the rays.
+ dPtr->deadzoneRayFans.push_back(
+ this->CreateDynamicLine(rendering::RENDERING_TRIANGLE_FAN));
+- dPtr->deadzoneRayFans[j]->setMaterial("Gazebo/BlackTransparent");
++ dPtr->deadzoneRayFans[j]->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/BlackTransparent"));
+ dPtr->deadzoneRayFans[j]->AddPoint(ignition::math::Vector3d(0, 0, 0));
+
+ // Individual ray lines
+ dPtr->rayLines.push_back(
+ this->CreateDynamicLine(rendering::RENDERING_LINE_LIST));
+- dPtr->rayLines[j]->setMaterial("Gazebo/BlueLaser");
++ dPtr->rayLines[j]->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/BlueLaser"));
+
+ this->SetVisibilityFlags(GZ_VISIBILITY_GUI);
+ }
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/Light.cc patched/gazebo-9.0.0/gazebo/rendering/Light.cc
+--- original/gazebo-9.0.0/gazebo/rendering/Light.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/Light.cc 2018-06-02 19:11:18.886907076 +0200
+@@ -208,7 +208,7 @@
+ this->dataPtr->line =
+ this->dataPtr->visual->CreateDynamicLine(RENDERING_LINE_LIST);
+
+- this->dataPtr->line->setMaterial("Gazebo/LightOn");
++ this->dataPtr->line->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/LightOn"));
+
+ this->dataPtr->line->setVisibilityFlags(GZ_VISIBILITY_GUI);
+
+@@ -383,9 +383,9 @@
+ if (this->dataPtr->light->getType() != Ogre::Light::LT_DIRECTIONAL)
+ {
+ if (_s)
+- this->dataPtr->line->setMaterial("Gazebo/PurpleGlow");
++ this->dataPtr->line->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/PurpleGlow"));
+ else
+- this->dataPtr->line->setMaterial("Gazebo/LightOn");
++ this->dataPtr->line->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/LightOn"));
+ }
+
+ return true;
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/LogicalCameraVisual.cc patched/gazebo-9.0.0/gazebo/rendering/LogicalCameraVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/LogicalCameraVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/LogicalCameraVisual.cc 2018-06-02 19:11:04.733623728 +0200
+@@ -117,7 +117,7 @@
+ line->AddPoint(ignition::math::Vector3d(
+ _msg.far_clip(), farWidth, -farHeight));
+
+- line->setMaterial("Gazebo/WhiteGlow");
++ line->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/WhiteGlow"));
+ line->setVisibilityFlags(GZ_VISIBILITY_GUI);
+
+ // Draw green lines from the near clipping plane to the origin
+@@ -138,7 +138,7 @@
+ sourceLine->AddPoint(ignition::math::Vector3d(
+ _msg.near_clip(), nearWidth, -nearHeight));
+
+- sourceLine->setMaterial("Gazebo/PurpleGlow");
++ sourceLine->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/PurpleGlow"));
+ sourceLine->setVisibilityFlags(GZ_VISIBILITY_GUI);
+
+ this->SetVisibilityFlags(GZ_VISIBILITY_GUI);
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/ogre_gazebo.h patched/gazebo-9.0.0/gazebo/rendering/ogre_gazebo.h
+--- original/gazebo-9.0.0/gazebo/rendering/ogre_gazebo.h 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/ogre_gazebo.h 2018-06-02 22:02:45.233964005 +0200
+@@ -31,7 +31,7 @@
+ #include <OGRE/OgrePlugin.h>
+ #include <OGRE/OgreDataStream.h>
+ #include <OGRE/OgreLogManager.h>
+-#include <OGRE/OgreWindowEventUtilities.h>
++#include <OGRE/Bites/OgreWindowEventUtilities.h>
+ #include <OGRE/OgreSceneQuery.h>
+ #include <OGRE/OgreRoot.h>
+ #include <OGRE/OgreSceneManager.h>
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/OriginVisual.cc patched/gazebo-9.0.0/gazebo/rendering/OriginVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/OriginVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/OriginVisual.cc 2018-06-02 21:18:02.414946952 +0200
+@@ -54,19 +54,19 @@
+
+ dPtr->xLine = this->CreateDynamicLine(
+ rendering::RENDERING_LINE_LIST);
+- dPtr->xLine->setMaterial("Gazebo/Red");
++ dPtr->xLine->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/Red"));
+ dPtr->xLine->AddPoint(ignition::math::Vector3d::Zero);
+ dPtr->xLine->AddPoint(ignition::math::Vector3d::UnitX*dPtr->length);
+
+ dPtr->yLine = this->CreateDynamicLine(
+ rendering::RENDERING_LINE_LIST);
+- dPtr->yLine->setMaterial("Gazebo/Green");
++ dPtr->yLine->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/Green"));
+ dPtr->yLine->AddPoint(ignition::math::Vector3d::Zero);
+ dPtr->yLine->AddPoint(ignition::math::Vector3d::UnitY*dPtr->length);
+
+ dPtr->zLine = this->CreateDynamicLine(
+ rendering::RENDERING_LINE_LIST);
+- dPtr->zLine->setMaterial("Gazebo/Blue");
++ dPtr->zLine->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/Blue"));
+ dPtr->zLine->AddPoint(ignition::math::Vector3d::Zero);
+ dPtr->zLine->AddPoint(ignition::math::Vector3d::UnitZ*dPtr->length);
+
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/RenderEngine.cc patched/gazebo-9.0.0/gazebo/rendering/RenderEngine.cc
+--- original/gazebo-9.0.0/gazebo/rendering/RenderEngine.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/RenderEngine.cc 2018-06-02 21:21:19.426983596 +0200
+@@ -798,8 +798,10 @@
+
+ // int multiRenderTargetCount = capabilities->getNumMultiRenderTargets();
+
+- bool hasFBO =
+- capabilities->hasCapability(Ogre::RSC_FBO);
++ bool hasFBO = true;
++ // as of Ogre 1.10.12 (see documentation: deprecated list):
++ // »All targetted APIs by Ogre support this feature.«
++ // capabilities->hasCapability(Ogre::RSC_FBO);
+
+ bool hasGLSL =
+ std::find(profiles.begin(), profiles.end(), "glsl") != profiles.end();
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/RTShaderSystem.cc patched/gazebo-9.0.0/gazebo/rendering/RTShaderSystem.cc
+--- original/gazebo-9.0.0/gazebo/rendering/RTShaderSystem.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/RTShaderSystem.cc 2018-06-02 21:35:48.021180627 +0200
+@@ -270,7 +270,7 @@
+ try
+ {
+ success = this->dataPtr->shaderGenerator->createShaderBasedTechnique(
+- curMaterialName,
++ *Ogre::MaterialManager::getSingleton().getByName(curMaterialName),
+ Ogre::MaterialManager::DEFAULT_SCHEME_NAME,
+ this->dataPtr->scenes[s]->Name() +
+ Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
+@@ -295,7 +295,7 @@
+ this->dataPtr->shaderGenerator->getRenderState(
+ this->dataPtr->scenes[s]->Name() +
+ Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME,
+- curMaterialName, 0);
++ curMaterialName, curMaterial->getGroup(), 0);
+
+ // Remove all sub render states.
+ renderState->reset();
+@@ -394,11 +394,11 @@
+ for (; it != itEnd; ++it)
+ {
+ struct stat st;
+- if (stat((*it)->archive->getName().c_str(), &st) == 0)
++ if (stat((*it).archive->getName().c_str(), &st) == 0)
+ {
+- if ((*it)->archive->getName().find("rtshaderlib") != Ogre::String::npos)
++ if ((*it).archive->getName().find("rtshaderlib") != Ogre::String::npos)
+ {
+- coreLibsPath = (*it)->archive->getName() + "/";
++ coreLibsPath = (*it).archive->getName() + "/";
+
+ // setup patch name for rt shader cache in tmp
+ char *tmpdir;
+@@ -537,7 +537,7 @@
+ // OGRE samples. They should be compared and tested.
+ // Set up caster material - this is just a standard depth/shadow map caster
+ // sceneMgr->setShadowTextureCasterMaterial("PSSM/shadow_caster");
+- sceneMgr->setShadowTextureCasterMaterial("Gazebo/shadow_caster");
++ sceneMgr->setShadowTextureCasterMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/shadow_caster"));
+
+ // Disable fog on the caster pass.
+ // Ogre::MaterialPtr passCaterMaterial =
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/Scene.cc patched/gazebo-9.0.0/gazebo/rendering/Scene.cc
+--- original/gazebo-9.0.0/gazebo/rendering/Scene.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/Scene.cc 2018-06-02 21:37:14.570872712 +0200
+@@ -3095,7 +3095,7 @@
+ this->dataPtr->manager->setShadowTechnique(
+ Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
+ this->dataPtr->manager->setShadowTextureCasterMaterial(
+- "DeferredRendering/Shadows/RSMCaster_Spot");
++ Ogre::MaterialManager::getSingleton().getByName("DeferredRendering/Shadows/RSMCaster_Spot"));
+ this->dataPtr->manager->setShadowTextureCount(1);
+ this->dataPtr->manager->setShadowFarDistance(150);
+ // Use a value of "2" to use a different depth buffer pool and
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/DataManager.cpp patched/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/DataManager.cpp
+--- original/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/DataManager.cpp 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/DataManager.cpp 2018-06-02 21:45:47.545276142 +0200
+@@ -682,7 +682,7 @@
+ buffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);
+ const Ogre::PixelBox &pb = buffer->getCurrentLock();
+
+- Ogre::uint32 *pbptr = static_cast < Ogre::uint32*>(pb.data);
++ Ogre::uint32 *pbptr = reinterpret_cast< Ogre::uint32*>(pb.data);
+ size_t x, y, z;
+
+ for (z = pb.front; z < pb.back; z++)
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/LightningManager.cpp patched/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/LightningManager.cpp
+--- original/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/LightningManager.cpp 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/skyx/src/VClouds/LightningManager.cpp 2018-06-02 21:46:43.111668253 +0200
+@@ -283,7 +283,7 @@
+ if (k < mLightnings.size())
+ {
+ pos = mVClouds->getGeometryManager()->getSceneNode()->
+- _getFullTransform().inverseAffine() *
++ _getFullTransform().inverse() *
+ mSceneNodes.at(k)->_getDerivedPosition();
+
+ mVolCloudsLightningMaterial->
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/SonarVisual.cc patched/gazebo-9.0.0/gazebo/rendering/SonarVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/SonarVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/SonarVisual.cc 2018-06-02 21:15:41.675877345 +0200
+@@ -73,7 +73,7 @@
+ reinterpret_cast<SonarVisualPrivate *>(this->dataPtr);
+
+ dPtr->sonarRay = this->CreateDynamicLine(rendering::RENDERING_LINE_LIST);
+- dPtr->sonarRay->setMaterial("Gazebo/RedGlow");
++ dPtr->sonarRay->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/RedGlow"));
+ dPtr->sonarRay->AddPoint(0, 0, 0);
+ dPtr->sonarRay->AddPoint(0, 0, 0);
+
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/TransmitterVisual.cc patched/gazebo-9.0.0/gazebo/rendering/TransmitterVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/TransmitterVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/TransmitterVisual.cc 2018-06-02 21:38:32.640571364 +0200
+@@ -75,7 +75,7 @@
+ TransmitterVisualPrivate *dPtr =
+ reinterpret_cast<TransmitterVisualPrivate *>(this->dataPtr);
+ dPtr->points = this->CreateDynamicLine(rendering::RENDERING_POINT_LIST);
+- dPtr->points->setMaterial("Gazebo/PointCloud");
++ dPtr->points->setMaterial(Ogre::MaterialManager::getSingleton().getByName("Gazebo/PointCloud"));
+ }
+
+ /////////////////////////////////////////////////
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/Visual.cc patched/gazebo-9.0.0/gazebo/rendering/Visual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/Visual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/Visual.cc 2018-06-02 21:40:40.440038072 +0200
+@@ -1068,7 +1068,7 @@
+ Ogre::SimpleRenderable *simpleRenderable =
+ dynamic_cast<Ogre::SimpleRenderable *>(obj);
+ if (simpleRenderable)
+- simpleRenderable->setMaterial(this->dataPtr->myMaterialName);
++ simpleRenderable->setMaterial(Ogre::MaterialManager::getSingleton().getByName(this->dataPtr->myMaterialName));
+ }
+ }
+ }
+@@ -2134,7 +2134,7 @@
+ transform[3][0] = transform[3][1] = transform[3][2] = 0;
+ transform[3][3] = 1;
+ // get oriented bounding box in object's local space
+- bb.transformAffine(transform);
++ bb.transform(transform);
+
+ min = Conversions::ConvertIgn(bb.getMinimum());
+ max = Conversions::ConvertIgn(bb.getMaximum());
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/WindowManager.cc patched/gazebo-9.0.0/gazebo/rendering/WindowManager.cc
+--- original/gazebo-9.0.0/gazebo/rendering/WindowManager.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/WindowManager.cc 2018-06-02 21:44:19.255703696 +0200
+@@ -188,9 +188,8 @@
+
+ if (_windowId < this->dataPtr->windows.size())
+ {
+- float lastFPS, bestFPS, worstFPS = 0;
+- this->dataPtr->windows[_windowId]->getStatistics(
+- lastFPS, avgFPS, bestFPS, worstFPS);
++ auto stats = this->dataPtr->windows[_windowId]->getStatistics();
++ avgFPS = stats.avgFPS;
+ }
+
+ return avgFPS;
+@@ -199,8 +198,10 @@
+ //////////////////////////////////////////////////
+ uint32_t WindowManager::TriangleCount(const uint32_t _windowId) const
+ {
+- if (_windowId < this->dataPtr->windows.size())
+- return this->dataPtr->windows[_windowId]->getTriangleCount();
++ if (_windowId < this->dataPtr->windows.size()) {
++ auto stats = this->dataPtr->windows[_windowId]->getStatistics();
++ return stats.triangleCount;
++ }
+ else
+ return 0;
+ }
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/WireBox.cc patched/gazebo-9.0.0/gazebo/rendering/WireBox.cc
+--- original/gazebo-9.0.0/gazebo/rendering/WireBox.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/WireBox.cc 2018-06-02 21:39:38.540302005 +0200
+@@ -28,7 +28,7 @@
+ {
+ this->dataPtr->parent = _parent;
+ this->dataPtr->lines = new DynamicLines(RENDERING_LINE_LIST);
+- this->dataPtr->lines->setMaterial("BaseWhiteNoLighting");
++ this->dataPtr->lines->setMaterial(Ogre::MaterialManager::getSingleton().getByName("BaseWhiteNoLighting"));
+ this->dataPtr->parent->AttachObject(this->dataPtr->lines);
+ this->dataPtr->lines->setVisibilityFlags(GZ_VISIBILITY_GUI);
+
+diff -ruN original/gazebo-9.0.0/gazebo/rendering/WrenchVisual.cc patched/gazebo-9.0.0/gazebo/rendering/WrenchVisual.cc
+--- original/gazebo-9.0.0/gazebo/rendering/WrenchVisual.cc 2018-01-25 23:25:48.000000000 +0100
++++ patched/gazebo-9.0.0/gazebo/rendering/WrenchVisual.cc 2018-06-02 21:44:35.492292605 +0200
+@@ -150,7 +150,7 @@
+ dPtr->forceLine = dPtr->forceVisual->CreateDynamicLine(RENDERING_LINE_LIST);
+ dPtr->forceLine->AddPoint(ignition::math::Vector3d::Zero);
+ dPtr->forceLine->AddPoint(ignition::math::Vector3d(0, 0, 0.1));
+- dPtr->forceLine->setMaterial("__GAZEBO_TRANS_PURPLE_MATERIAL__");
++ dPtr->forceLine->setMaterial(Ogre::MaterialManager::getSingleton().getByName("__GAZEBO_TRANS_PURPLE_MATERIAL__"));
+
+ this->SetVisibilityFlags(GZ_VISIBILITY_GUI);
+ \ No newline at end of file