2
Copyright (C) 2004 Erik Hjortsberg
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
#include "TerrainShader.h"
24
#include <OgreIteratorWrappers.h>
25
#include "TerrainLayerDefinition.h"
29
TerrainShader::TerrainShader(Mercator::Terrain* terrain, int terrainIndex, const TerrainLayerDefinition* layerDef, Mercator::Shader* shader)
33
, mTerrainIndex(terrainIndex)
38
mTerrain->addShader(shader, mTerrainIndex);
43
TerrainShader::TerrainShader(Mercator::Terrain* terrain, int terrainIndex, Ogre::MaterialPtr material, Mercator::Shader* shader)
47
, mTerrainIndex(terrainIndex)
51
mTerrain->addShader(shader, mTerrainIndex);
54
TerrainShader::~TerrainShader()
58
//mTerrain->removeShader(mShader)
61
Ogre::ushort TerrainShader::getMaxTextureUnits() const
63
return std::min<unsigned short>(4, Ogre::Root::getSingleton().getRenderSystem()->getCapabilities()->getNumTextureUnits());
66
Mercator::Shader* TerrainShader::getShader() const
71
// const Ogre::String& TerrainShader::getTextureName() const
73
// return mTextureName;
76
const TerrainLayerDefinition* TerrainShader::getLayerDefinition() const
82
void TerrainShader::addTextureUnitsToPass(Ogre::Pass* pass, const Ogre::String& splatTextureName) {
84
/* if (getMaxTextureUnits() - pass->getNumTextureUnitStates() < 2 || pass->getParent()->getNumPasses() > 1) {
85
addPassToTechnique(pass->getParent(), splatTextureName);
86
// S_LOG_WARNING("Trying to add texture units to pass with too few available texture unit states.");
90
S_LOG_VERBOSE("Adding new texture unit (detailtexture: " << mTextureName << " alphatexture: " << splatTextureName << ") to pass nr " << pass->getIndex() << " in technique for material " << pass->getParent()->getParent()->getName());*/
92
/* pass->setSelfIllumination(Ogre::ColourValue(1,1,1));
93
pass->setAmbient(Ogre::ColourValue(1,1,1));
94
pass->setDiffuse(Ogre::ColourValue(1,1,1));
95
pass->setLightingEnabled(true);*/
96
/* Ogre::TextureUnitState * textureUnitStateSplat = pass->createTextureUnitState();
97
textureUnitStateSplat->setTextureName(splatTextureName);
99
textureUnitStateSplat->setTextureCoordSet(0);
100
textureUnitStateSplat->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
101
textureUnitStateSplat->setAlphaOperation(Ogre::LBX_SOURCE1, Ogre::LBS_TEXTURE, Ogre::LBS_TEXTURE);
102
textureUnitStateSplat->setColourOperationEx(Ogre::LBX_SOURCE1, Ogre::LBS_CURRENT, Ogre::LBS_CURRENT);
103
textureUnitStateSplat->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);*/
104
// textureUnitStateSplat->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE);
105
// textureUnitStateSplat->setColourOperationEx(Ogre::LBX_BLEND_TEXTURE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE);
107
/* Ogre::TextureUnitState * textureUnitState = pass->createTextureUnitState();
108
textureUnitState->setTextureName(mTextureName);
109
textureUnitState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP);*/
110
/* textureUnitState->setTextureCoordSet(0);*/
111
/* textureUnitState->setTextureScale(0.025, 0.025);
112
textureUnitState->setColourOperationEx(Ogre::LBX_BLEND_CURRENT_ALPHA, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);*/
114
/* Ogre::TextureUnitState * alphaTextureState= pass->createTextureUnitState();
115
alphaTextureState->setTextureName(mTextureName);
116
// alphaTextureState->setTextureName(splatTextureName);
117
alphaTextureState->setTextureCoordSet(0);
118
alphaTextureState->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
119
alphaTextureState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
120
alphaTextureState->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE);
124
// detailTextureState->setAlphaOperation(Ogre::LBX_SOURCE1, Ogre::LBS_TEXTURE, Ogre::LBS_TEXTURE);
125
// detailTextureState->setColourOperationEx(Ogre::LBX_SOURCE1, Ogre::LBS_CURRENT, Ogre::LBS_CURRENT);
127
Ogre::TextureUnitState * detailTextureState = pass->createTextureUnitState();
128
detailTextureState ->setTextureName(splatTextureName);
129
// detailTextureState ->setTextureName(mTextureName);
130
detailTextureState ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP);
131
detailTextureState ->setTextureCoordSet(0);
132
detailTextureState ->setTextureScale(0.01, 0.01);
133
//detailTextureState ->setColourOperationEx(Ogre::LBX_BLEND_CURRENT_ALPHA, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);*/
137
Ogre::Pass* TerrainShader::addPassToTechnique(Ogre::Technique* technique, const Ogre::String& splatTextureName) {
139
///check if we instead can reuse the existing pass
140
// if (technique->getNumPasses() != 0) {
141
// Ogre::Pass* pass = technique->getPass(technique->getNumPasses() - 1);
142
// if (4 - pass->getNumTextureUnitStates() >= 2) {
143
// ///there's more than two texture units available, use those instead of creating a new pass
144
// S_LOG_VERBOSE("Reusing existing pass. ("<< pass->getNumTextureUnitStates() << " of "<< mNumberOfTextureUnitsOnCard << " texture unit used)");
145
// addTextureUnitsToPass(pass, splatTextureName);
152
// Ogre::Pass* pass = technique->createPass();
154
// S_LOG_VERBOSE("Adding new pass (" << mTextureName << ") to technique for material " << technique->getParent()->getName() << ". Number of passes in this technique: " << technique->getNumPasses());
156
// pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
157
// pass->setLightingEnabled(false);
160
// Ogre::TextureUnitState * textureUnitStateSplat = pass->createTextureUnitState();
161
// textureUnitStateSplat->setTextureName(splatTextureName);
163
// textureUnitStateSplat->setTextureCoordSet(0);
164
// // textureUnitStateSplat->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
165
// textureUnitStateSplat->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
166
// textureUnitStateSplat->setTextureFiltering(Ogre::TFO_ANISOTROPIC);
167
// // textureUnitStateSplat->setAlphaOperation(Ogre::LBX_SOURCE1, Ogre::LBS_TEXTURE, Ogre::LBS_TEXTURE);
168
// textureUnitStateSplat->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE);
170
// Ogre::TextureUnitState * textureUnitState = pass->createTextureUnitState();
171
// textureUnitState->setTextureName(mTextureName);
172
// textureUnitState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP);
173
// textureUnitState->setTextureCoordSet(0);
174
// textureUnitState->setTextureScale(0.025, 0.025);
178
// textureUnitState->setColourOperationEx(LBX_BLEND_CURRENT_ALPHA, LBS_TEXTURE, LBS_CURRENT);
182
void TerrainShader::addMaterialToTechnique(Ogre::Technique* technique, const Ogre::String& splatTextureName) {
184
// if (!mMaterial->getNumSupportedTechniques()) {
188
// Ogre::Technique* sourceTech = mMaterial->getSupportedTechnique(0);
189
// Ogre::Technique::PassIterator I = sourceTech->getPassIterator();
190
// bool isFirstPass = true;
191
// while (I.hasMoreElements()) {
192
// Ogre::Pass* sourcePass = I.getNext();
195
// ///if there's only one pass, check if we can fit that into the existing pass
196
// if (isFirstPass && technique->getNumPasses() == 1) {
197
// isFirstPass = false;
198
// if (technique->getNumPasses() != 0) {
199
// Ogre::Pass* existingPass = technique->getPass(technique->getNumPasses() - 1);
200
// if (getMaxTextureUnits() - existingPass->getNumTextureUnitStates() >= sourcePass->getNumTextureUnitStates()) {
201
// ///there's more than two texture units available, use those instead of creating a new pass
202
// ///now iterate through all textures, copy the texture units to the existing splat and look for the splat
203
// Ogre::Pass::TextureUnitStateIterator J = sourcePass->getTextureUnitStateIterator();
204
// while (J.hasMoreElements()) {
205
// Ogre::TextureUnitState* newTexUnitState = new Ogre::TextureUnitState(existingPass, *J.getNext());
206
// //Ogre::TextureUnitState* texUnitState = J.getNext();
207
// ///clone the texture unit state
208
// //*newTexUnitState = *texUnitState;
209
// if (newTexUnitState->getTextureName() == "splat") {
210
// newTexUnitState->setTextureName(splatTextureName);
219
// Ogre::Pass* destPass = technique->createPass();
221
// //just make a copy of the source pass
222
// *destPass = *sourcePass;
223
// destPass->setName("");
225
// S_LOG_VERBOSE("Added new pass from template material(" << mMaterial->getName()<< ") to technique for material " << technique->getParent()->getName() << ". Number of passes in this technique: " << technique->getNumPasses());
227
// //now iterate through all textures and look for the splat
228
// Ogre::Pass::TextureUnitStateIterator J = destPass->getTextureUnitStateIterator();
229
// while (J.hasMoreElements()) {
230
// Ogre::TextureUnitState* texUnitState = J.getNext();
231
// texUnitState->setName("");
232
// if (texUnitState->getTextureName() == "splat") {
233
// texUnitState->setTextureName(splatTextureName);
239
void TerrainShader::addSplatToTechnique(Ogre::Technique* technique, const Ogre::String& splatTextureName) {
240
/* if (!mMaterial.isNull()) {
241
addMaterialToTechnique(technique, splatTextureName);
243
addTextureUnitsToPass(technique->getPass(technique->getNumPasses() - 1) , splatTextureName);
244
// Ogre::Pass* pass = addPassToTechnique(technique, splatTextureName);
245
//pass->setLightingEnabled(false);
246
//pass->setSelfIllumination(Ogre::ColourValue(1,1,1));
251
Mercator::Surface* TerrainShader::getSurfaceForSegment(Mercator::Segment* segment) const
254
Mercator::Surface* surface = 0;
255
if (segment->getSurfaces().find(getTerrainIndex()) != segment->getSurfaces().end()) {
256
surface = segment->getSurfaces().find(getTerrainIndex())->second;