13#include "OgreCamera.h"
14#include "OgreVector3.h"
15#include "OgreQuaternion.h"
16#include "OgreEntity.h"
17#include "OgreString.h"
18#include "OgreStringConverter.h"
19#include "OgreMaterialManager.h"
20#include "OgreMaterial.h"
21#include "OgreHardwareBufferManager.h"
22#include "OgreHardwareBuffer.h"
23#include "OgreMeshManager.h"
25#include "OgreSubMesh.h"
26#include "OgreLogManager.h"
27#include "OgreTextureManager.h"
28#include "OgreHardwarePixelBuffer.h"
29#include "OgreRenderSystem.h"
30#include "OgreRenderSystemCapabilities.h"
31#include "OgreHighLevelGpuProgram.h"
32#include "OgreHighLevelGpuProgramManager.h"
33#include <OgreTechnique.h>
34#include <OgreSceneNode.h>
69 std::list<GrassLayer*>::iterator it;
99 unsigned long currentTime =
windTimer.getMilliseconds();
100 unsigned long ellapsedTime = currentTime -
lastTime;
103 float ellapsed = ellapsedTime / 1000.0f;
106 std::list<GrassLayer*>::iterator it;
112 GpuProgramParametersSharedPtr params = layer->
material->getTechnique(0)->getPass(0)->getVertexProgramParameters();
119 params->setNamedConstant(
"time", layer->
waveCount);
120 params->setNamedConstant(
"frequency", layer->
animFreq);
123 params->setNamedConstant(
"direction", Vector4(direction.x, direction.y, direction.z, 0));
132 std::list<GrassLayer*>::iterator it;
144 Ogre::Real volume = page.
bounds.width() * page.
bounds.height();
152 float *position =
new float[grassCount*4];
163 if (grassCount != 0){
181 entity->setCastShadows(
false);
201 unsigned int quadCount;
202 quadCount = grassCount;
205 unsigned int maxUInt16 = std::numeric_limits<uint16>::max();
206 if(grassCount > maxUInt16)
208 LogManager::getSingleton().logMessage(
"grass count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) +
" (thats the maximum) grass meshes for one page");
211 if(quadCount > maxUInt16)
213 LogManager::getSingleton().logMessage(
"quad count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) +
" (thats the maximum) grass meshes for one page");
218 MeshPtr mesh = MeshManager::getSingleton().createManual(
getUniqueID(), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
219 SubMesh *subMesh = mesh->createSubMesh();
220 subMesh->useSharedVertices =
false;
223 subMesh->vertexData =
new VertexData;
224 subMesh->vertexData->vertexStart = 0;
225 subMesh->vertexData->vertexCount = 4 * quadCount;
227 VertexDeclaration* dcl = subMesh->vertexData->vertexDeclaration;
229 dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
230 offset += VertexElement::getTypeSize(VET_FLOAT3);
231 dcl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
232 offset += VertexElement::getTypeSize(VET_COLOUR);
233 dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
234 offset += VertexElement::getTypeSize(VET_FLOAT2);
237 HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
238 .createVertexBuffer(offset, subMesh->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY,
false);
239 float* pReal =
static_cast<float*
>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
245 Ogre::Real minY = Math::POS_INFINITY, maxY = Math::NEG_INFINITY;
246 const float *posPtr = grassPositions;
247 for (uint16 i = 0; i < grassCount; ++i)
261 Ogre::Real rnd = *posPtr++;
262 Ogre::Real halfScaleX = (layer->
minWidth + rndWidth * rnd) * 0.5f;
263 Ogre::Real scaleY = (layer->
minHeight + rndHeight * rnd);
266 Ogre::Real angle = *posPtr++;
267 Ogre::Real xTrans = Math::Cos(angle) * halfScaleX;
268 Ogre::Real zTrans = Math::Sin(angle) * halfScaleX;
271 Ogre::Real x1 =
x - xTrans, z1 =
z - zTrans;
272 Ogre::Real x2 =
x + xTrans, z2 =
z + zTrans;
274 Ogre::Real y1 = 0.f, y2 = 0.f;
280 if (layer->
getMaxSlope() < (Math::Abs(y1 - y2) / (halfScaleX * 2))) {
290 *pReal++ = float(y1 + scaleY);
293 *((uint32*)pReal++) = color;
294 *pReal++ = 0.f; *pReal++ = 0.f;
297 *pReal++ = float(y2 + scaleY);
299 *((uint32*)pReal++) = color;
300 *pReal++ = 1.f; *pReal++ = 0.f;
303 *pReal++ = float(y1);
305 *((uint32*)pReal++) = color;
306 *pReal++ = 0.f; *pReal++ = 1.f;
309 *pReal++ = float(y2);
311 *((uint32*)pReal++) = color;
312 *pReal++ = 1.f; *pReal++ = 1.f;
315 if (y1 < minY) minY = y1;
316 if (y2 < minY) minY = y2;
317 if (y1 + scaleY > maxY) maxY = y1 + scaleY;
318 if (y2 + scaleY > maxY) maxY = y2 + scaleY;
322 subMesh->vertexData->vertexBufferBinding->setBinding(0, vbuf);
325 subMesh->indexData->indexStart = 0;
326 subMesh->indexData->indexCount = 6 * quadCount;
327 subMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton()
328 .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, subMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
329 uint16* pI =
static_cast<uint16*
>(subMesh->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
330 for (uint16 i = 0; i < quadCount; ++i)
332 uint16 offset = i * 4;
343 subMesh->indexData->indexBuffer->unlock();
348 mesh->_setBounds(bounds);
349 Vector3 temp = bounds.getMaximum() - bounds.getMinimum();
350 mesh->_setBoundingSphereRadius(temp.length() * 0.5f);
352 LogManager::getSingleton().setLogDetail(
static_cast<LoggingLevel
>(0));
354 LogManager::getSingleton().setLogDetail(LL_NORMAL);
357 subMesh->setMaterialName(layer->
material->getName());
366 unsigned int quadCount;
367 quadCount = grassCount * 2;
370 unsigned int maxUInt16 = std::numeric_limits<uint16>::max();
371 if(grassCount > maxUInt16)
373 LogManager::getSingleton().logMessage(
"grass count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) +
" (thats the maximum) grass meshes for one page");
376 if(quadCount > maxUInt16)
378 LogManager::getSingleton().logMessage(
"quad count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) +
" (thats the maximum) grass meshes for one page");
383 MeshPtr mesh = MeshManager::getSingleton().createManual(
getUniqueID(), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
384 SubMesh *subMesh = mesh->createSubMesh();
385 subMesh->useSharedVertices =
false;
388 subMesh->vertexData =
new VertexData;
389 subMesh->vertexData->vertexStart = 0;
390 subMesh->vertexData->vertexCount = 4 * quadCount;
392 VertexDeclaration* dcl = subMesh->vertexData->vertexDeclaration;
394 dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
395 offset += VertexElement::getTypeSize(VET_FLOAT3);
396 dcl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
397 offset += VertexElement::getTypeSize(VET_COLOUR);
398 dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
399 offset += VertexElement::getTypeSize(VET_FLOAT2);
402 HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
403 .createVertexBuffer(offset, subMesh->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY,
false);
404 float* pReal =
static_cast<float*
>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
409 Ogre::Real minY = Math::POS_INFINITY, maxY = Math::NEG_INFINITY;
411 const float *posPtr = grassPositions;
412 for (uint16 i = 0; i < grassCount; ++i)
415 Ogre::Real
x = *posPtr++;
416 Ogre::Real
z = *posPtr++;
426 Ogre::Real rnd = *posPtr++;
427 Ogre::Real halfScaleX = (layer->
minWidth + rndWidth * rnd) * 0.5f;
428 Ogre::Real scaleY = (layer->
minHeight + rndHeight * rnd);
431 Ogre::Real angle = *posPtr++;
432 Ogre::Real xTrans = Math::Cos(angle) * halfScaleX;
433 Ogre::Real zTrans = Math::Sin(angle) * halfScaleX;
436 Ogre::Real x1 =
x - xTrans, z1 =
z - zTrans;
437 Ogre::Real x2 =
x + xTrans, z2 =
z + zTrans;
439 Ogre::Real y1 = 0.f, y2 = 0.f;
445 if (layer->
getMaxSlope() < (Math::Abs(y1 - y2) / (halfScaleX * 2)))
456 *pReal++ = float(y1 + scaleY);
458 *((uint32*)pReal++) = color;
459 *pReal++ = 0.f; *pReal++ = 0.f;
462 *pReal++ = float(y2 + scaleY);
464 *((uint32*)pReal++) = color;
465 *pReal++ = 1.f; *pReal++ = 0.f;
468 *pReal++ = float(y1);
470 *((uint32*)pReal++) = color;
471 *pReal++ = 0.f; *pReal++ = 1.f;
474 *pReal++ = float(y2);
476 *((uint32*)pReal++) = color;
477 *pReal++ = 1.f; *pReal++ = 1.f;
480 if (y1 < minY) minY = y1;
481 if (y2 < minY) minY = y2;
482 if (y1 + scaleY > maxY) maxY = y1 + scaleY;
483 if (y2 + scaleY > maxY) maxY = y2 + scaleY;
486 Ogre::Real x3 =
x + zTrans, z3 =
z - xTrans;
487 Ogre::Real x4 =
x - zTrans, z4 =
z + xTrans;
489 Ogre::Real y3 = 0.f, y4 = 0.f;
492 if (layer->
getMaxSlope() < (Math::Abs(y1 - y2) / (halfScaleX * 2)))
506 *pReal++ = float(y3 + scaleY);
508 *((uint32*)pReal++) = color;
509 *pReal++ = 0.f; *pReal++ = 0.f;
512 *pReal++ = float(y4 + scaleY);
514 *((uint32*)pReal++) = color;
515 *pReal++ = 1.f; *pReal++ = 0.f;
518 *pReal++ = float(y3);
520 *((uint32*)pReal++) = color;
521 *pReal++ = 0.f; *pReal++ = 1.f;
524 *pReal++ = float(y4);
526 *((uint32*)pReal++) = color;
527 *pReal++ = 1.f; *pReal++ = 1.f;
530 if (y3 < minY) minY = y1;
531 if (y4 < minY) minY = y2;
532 if (y3 + scaleY > maxY) maxY = y3 + scaleY;
533 if (y4 + scaleY > maxY) maxY = y4 + scaleY;
537 subMesh->vertexData->vertexBufferBinding->setBinding(0, vbuf);
540 subMesh->indexData->indexStart = 0;
541 subMesh->indexData->indexCount = 6 * quadCount;
542 subMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton()
543 .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, subMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
544 uint16* pI =
static_cast<uint16*
>(subMesh->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
545 for (uint16 i = 0; i < quadCount; ++i)
547 uint16 offset = i * 4;
558 subMesh->indexData->indexBuffer->unlock();
564 mesh->_setBounds(bounds);
565 Vector3 temp = bounds.getMaximum() - bounds.getMinimum();
566 mesh->_setBoundingSphereRadius(temp.length() * 0.5f);
568 LogManager::getSingleton().setLogDetail(
static_cast<LoggingLevel
>(0));
570 LogManager::getSingleton().setLogDetail(LL_NORMAL);
573 subMesh->setMaterialName(layer->
material->getName());
582 unsigned int quadCount;
583 quadCount = grassCount;
586 unsigned int maxUInt16 = std::numeric_limits<uint16>::max();
587 if(grassCount > maxUInt16)
589 LogManager::getSingleton().logMessage(
"grass count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) +
" (thats the maximum) grass meshes for one page");
592 if(quadCount > maxUInt16)
594 LogManager::getSingleton().logMessage(
"quad count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) +
" (thats the maximum) grass meshes for one page");
599 MeshPtr mesh = MeshManager::getSingleton().createManual(
getUniqueID(), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
600 SubMesh *subMesh = mesh->createSubMesh();
601 subMesh->useSharedVertices =
false;
604 subMesh->vertexData =
new VertexData;
605 subMesh->vertexData->vertexStart = 0;
606 subMesh->vertexData->vertexCount = 4 * quadCount;
608 VertexDeclaration* dcl = subMesh->vertexData->vertexDeclaration;
610 dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
611 offset += VertexElement::getTypeSize(VET_FLOAT3);
612 dcl->addElement(0, offset, VET_FLOAT4, VES_NORMAL);
613 offset += VertexElement::getTypeSize(VET_FLOAT4);
614 dcl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
615 offset += VertexElement::getTypeSize(VET_COLOUR);
616 dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
617 offset += VertexElement::getTypeSize(VET_FLOAT2);
620 HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
621 .createVertexBuffer(offset, subMesh->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY,
false);
622 float* pReal =
static_cast<float*
>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
627 Ogre::Real minY = Math::POS_INFINITY, maxY = Math::NEG_INFINITY;
629 const float *posPtr = grassPositions;
630 for (uint16 i = 0; i < grassCount; ++i)
644 float rnd = *posPtr++;
645 float halfXScale = float(layer->
minWidth + rndWidth * rnd) * 0.5f;
646 float scaleY = float(layer->
minHeight + rndHeight * rnd);
649 float uvLeft = 1.f, uvRight = 0.f;
650 if (*posPtr++ > 0.5f)
657 *pReal++ = x1; *pReal++ =
y; *pReal++ = z1;
658 *pReal++ = -halfXScale; *pReal++ = scaleY; *pReal++ = 0.f; *pReal++ = 0.f;
659 *((uint32*)pReal++) = color;
660 *pReal++ = uvLeft; *pReal++ = 0.f;
662 *pReal++ = x1; *pReal++ =
y; *pReal++ = z1;
663 *pReal++ = +halfXScale; *pReal++ = scaleY; *pReal++ = 0.f; *pReal++ = 0.f;
664 *((uint32*)pReal++) = color;
665 *pReal++ = uvRight; *pReal++ = 0.f;
667 *pReal++ = x1; *pReal++ =
y; *pReal++ = z1;
668 *pReal++ = -halfXScale; *pReal++ = 0.f; *pReal++ = 0.f; *pReal++ = 0.f;
669 *((uint32*)pReal++) = color;
670 *pReal++ = uvLeft; *pReal++ = 1.f;
672 *pReal++ = x1; *pReal++ =
y; *pReal++ = z1;
673 *pReal++ = +halfXScale; *pReal++ = 0.f; *pReal++ = 0.f; *pReal++ = 0.f;
674 *((uint32*)pReal++) = color;
675 *pReal++ = uvRight; *pReal++ = 1.f;
678 if (
y < minY) minY =
y;
679 if (
y + scaleY > maxY) maxY =
y + scaleY;
683 subMesh->vertexData->vertexBufferBinding->setBinding(0, vbuf);
686 subMesh->indexData->indexStart = 0;
687 subMesh->indexData->indexCount = 6 * quadCount;
688 subMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton()
689 .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, subMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
690 uint16* pI =
static_cast<uint16*
>(subMesh->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
691 for (uint16 i = 0; i < quadCount; ++i)
693 uint16 offset = i * 4;
704 subMesh->indexData->indexBuffer->unlock();
709 mesh->_setBounds(bounds);
710 Vector3 temp = bounds.getMaximum() - bounds.getMinimum();
711 mesh->_setBoundingSphereRadius(temp.length() * 0.5f);
713 LogManager::getSingleton().setLogDetail(
static_cast<LoggingLevel
>(0));
715 LogManager::getSingleton().setLogDetail(LL_NORMAL);
718 subMesh->setMaterialName(layer->
material->getName());
762 material = Ogre::static_pointer_cast<Material>(MaterialManager::getSingleton().getByName(matName));
764 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
"The specified grass material does not exist",
"GrassLayer::setMaterialName()");
848 float *posPtr = posBuff;
856 for (
unsigned int i = 0; i < grassCount; ++i)
881 if (
minY) min =
minY;
else min = Math::NEG_INFINITY;
882 if (
maxY) max =
maxY;
else max = Math::POS_INFINITY;
884 for (
unsigned int i = 0; i < grassCount; ++i){
893 if (
y >= min &&
y <= max){
910 grassCount = (posPtr - posBuff) / 4;
916 float *posPtr = posBuff;
923 for (
unsigned int i = 0; i < grassCount; ++i){
947 if (
minY) min =
minY;
else min = Math::NEG_INFINITY;
948 if (
maxY) max =
maxY;
else max = Math::POS_INFINITY;
950 for (
unsigned int i = 0; i < grassCount; ++i){
962 if (
y >= min &&
y <= max){
983 grassCount = (posPtr - posBuff) / 4;
989 float *posPtr = posBuff;
995 for (
unsigned int i = 0; i < grassCount; ++i){
1019 if (
minY) min =
minY;
else min = Math::NEG_INFINITY;
1020 if (
maxY) max =
maxY;
else max = Math::POS_INFINITY;
1022 for (
unsigned int i = 0; i < grassCount; ++i){
1034 if (
y >= min &&
y <= max){
1055 grassCount = (posPtr - posBuff) / 4;
1096 const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities();
1101 float fadeRange = farViewDist / 1.2247449f;
1107 Ogre::StringStream tmpName;
1108 tmpName <<
"GrassVS_";
1112 tmpName <<
"blend_";
1114 tmpName <<
"lighting_";
1119 tmpName << farViewDist <<
"_";
1121 const String vsName = tmpName.str();
1124 const String matName =
material->getName() +
"_" + vsName;
1127 MaterialPtr tmpMat = MaterialManager::getSingleton().getByName(matName);
1134 tmpMat->setLightingEnabled(
false);
1138 String shaderLanguage;
1139 HighLevelGpuProgramPtr vertexShader = Ogre::static_pointer_cast<HighLevelGpuProgram>(HighLevelGpuProgramManager::getSingleton().getByName(vsName));
1142 HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
1143 if (mgr.isLanguageSupported(
"hlsl"))
1144 shaderLanguage =
"hlsl";
1145 else if(mgr.isLanguageSupported(
"glsl"))
1146 shaderLanguage =
"glsl";
1148 shaderLanguage =
"cg";
1151 String vertexProgSource;
1153 if(!shaderLanguage.compare(
"hlsl") || !shaderLanguage.compare(
"cg"))
1158 " float4 iPosition : POSITION, \n"
1159 " float4 iColor : COLOR, \n"
1160 " float2 iUV : TEXCOORD0, \n"
1161 " out float4 oPosition : POSITION, \n"
1162 " out float4 oColor : COLOR, \n"
1163 " out float2 oUV : TEXCOORD0, \n";
1166 " uniform float4 objSpaceLight, \n"
1167 " uniform float4 lightDiffuse, \n"
1168 " uniform float4 lightAmbient, \n";
1170 if (
animate) vertexProgSource +=
1171 " uniform float time, \n"
1172 " uniform float frequency, \n"
1173 " uniform float4 direction, \n";
1176 " uniform float grassHeight, \n";
1179 " float4 iNormal : NORMAL, \n";
1182 " uniform float4x4 worldViewProj, \n"
1183 " uniform float3 camPos, \n"
1184 " uniform float fadeRange ) \n"
1186 " oColor.rgb = iColor.rgb; \n"
1187 " float4 position = iPosition; \n"
1188 " float dist = distance(camPos.xz, position.xz); \n";
1193 " float3 light = normalize(objSpaceLight.xyz - (iPosition.xyz * objSpaceLight.w)); \n"
1194 " float diffuseFactor = max(dot(float4(0,1,0,0), light), 0); \n"
1195 " oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n";
1200 " oColor.rgb = iColor.rgb; \n";
1205 " oColor.a = 2.0f - (2.0f * dist / fadeRange); \n";
1206 else vertexProgSource +=
1207 " oColor.a = 1.0f; \n";
1210 " float oldposx = position.x; \n";
1214 " float3 dirVec = (float3)position - (float3)camPos; \n"
1215 " float3 p = normalize(cross(float4(0,1,0,0), dirVec)); \n"
1216 " position += float4(p.x * iNormal.x, iNormal.y, p.z * iNormal.x, 0); \n";
1218 if (
animate) vertexProgSource +=
1219 " if (iUV.y == 0.0f){ \n"
1221 " float offset = sin(time + oldposx * frequency); \n"
1222 " position += direction * offset; \n"
1227 else if (
blend) vertexProgSource +=
1228 " if (iUV.y != 0.0f){ \n";
1230 if (
blend) vertexProgSource +=
1232 " oColor.a = clamp(oColor.a, 0, 1) * 4.0f * ((dist / fadeRange) - 0.1f); \n"
1236 " float offset = (2.0f * dist / fadeRange) - 1.0f; \n"
1237 " position.y -= grassHeight * clamp(offset, 0, 1); ";
1240 " oPosition = mul(worldViewProj, position); \n";
1252 "uniform vec4 objSpaceLight; \n"
1253 "uniform vec4 lightDiffuse; \n"
1254 "uniform vec4 lightAmbient; \n";
1260 "uniform float time; \n"
1261 "uniform float frequency; \n"
1262 "uniform vec4 direction; \n";
1268 "uniform float grassHeight; \n";
1272 "uniform mat4 worldViewProj; \n"
1273 "uniform vec3 camPos; \n"
1274 "uniform float fadeRange; \n"
1278 " vec4 color = gl_Color; \n"
1279 " vec4 position = gl_Vertex; \n"
1280 " float dist = distance(camPos.xz, position.xz); \n";
1285 " vec3 light = normalize(objSpaceLight.xyz - (gl_Vertex.xyz * objSpaceLight.w)); \n"
1286 " float diffuseFactor = max( dot( vec3(0.0,1.0,0.0), light), 0.0); \n"
1287 " color = (lightAmbient + diffuseFactor * lightDiffuse) * gl_Color; \n";
1292 " color.xyz = gl_Color.xyz; \n";
1299 " color.w = 2.0 - (2.0 * dist / fadeRange); \n";
1304 " color.w = 1.0; \n";
1311 " vec3 dirVec = position.xyz - camPos.xyz; \n"
1312 " vec3 p = normalize(cross(vec3(0.0,1.0,0.0), dirVec)); \n"
1313 " position += vec4(p.x * gl_Normal.x, gl_Normal.y, p.z * gl_Normal.x, 0.0); \n";
1319 " if (gl_MultiTexCoord0.y == 0.0) \n"
1322 " position += direction * sin(time + gl_Vertex.x * frequency); \n"
1335 " if (gl_MultiTexCoord0.y != 0.0) \n"
1343 " color.w = clamp(color.w, 0.0, 1.0) * 4.0 * ((dist / fadeRange) - 0.1); \n"
1350 " position.y -= grassHeight * clamp((2.0 * dist / fadeRange) - 1.0, 0.0, 1.0); \n";
1354 " gl_Position = worldViewProj * position; \n"
1355 " gl_FrontColor = color; \n"
1356 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
1357 " gl_FogFragCoord = gl_Position.z; \n"
1361 vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram(
1363 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
1364 shaderLanguage, GPT_VERTEX_PROGRAM);
1366 vertexShader->setSource(vertexProgSource);
1368 if (shaderLanguage ==
"hlsl")
1370 vertexShader->setParameter(
"target",
"vs_1_1");
1371 vertexShader->setParameter(
"entry_point",
"main");
1373 else if(shaderLanguage ==
"cg")
1375 vertexShader->setParameter(
"profiles",
"vs_1_1 arbvp1");
1376 vertexShader->setParameter(
"entry_point",
"main");
1380 vertexShader->load();
1383 shaderLanguage = vertexShader->getLanguage();
1390 Pass *pass = tmpMat->getTechnique(0)->getPass(0);
1391 pass->setVertexProgram(vsName);
1392 GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();
1393 params->setNamedAutoConstant(
"worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
1394 params->setNamedAutoConstant(
"camPos", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
1395 params->setNamedAutoConstant(
"fadeRange", GpuProgramParameters::ACT_CUSTOM, 1);
1398 params->setNamedAutoConstant(
"time", GpuProgramParameters::ACT_CUSTOM, 1);
1399 params->setNamedAutoConstant(
"frequency", GpuProgramParameters::ACT_CUSTOM, 1);
1400 params->setNamedAutoConstant(
"direction", GpuProgramParameters::ACT_CUSTOM, 4);
1404 params->setNamedAutoConstant(
"objSpaceLight", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
1405 params->setNamedAutoConstant(
"lightDiffuse", GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR);
1406 params->setNamedAutoConstant(
"lightAmbient", GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR);
1410 params->setNamedAutoConstant(
"grassHeight", GpuProgramParameters::ACT_CUSTOM, 1);
1411 params->setNamedConstant(
"grassHeight",
maxHeight * 1.05f);
1414 pass->getVertexProgramParameters()->setNamedConstant(
"fadeRange", fadeRange);
1439void GrassPage::addEntity(Entity *entity,
const Vector3 &position,
const Quaternion &rotation,
const Vector3 &scale,
const Ogre::ColourValue &color)
1441 SceneNode *node =
rootNode->createChildSceneNode();
1442 node->setPosition(position);
1445 entity->setCastShadows(
false);
1446 node->attachObject(entity);
1451 std::list<SceneNode*>::iterator i;
1454 SceneNode *node = *i;
1455 int numObjs = node->numAttachedObjects();
1456 for(
int j = 0; j < numObjs; j++)
1458 Entity *ent =
static_cast<Entity*
>(node->getAttachedObject(j));
1461 MeshManager::getSingleton().remove(ent->getMesh()->getName());
1473 std::list<SceneNode*>::iterator i;
1475 SceneNode *node = *i;
1476 node->setVisible(visible);
#define ROR_ASSERT(_EXPR)
static ColorMap * load(const Ogre::String &fileName, MapChannel channel=CHANNEL_COLOR)
void setFilter(MapFilter filter)
Sets the filtering mode used for this color map.
Ogre::uint32 getColorAt(Ogre::Real x, Ogre::Real z, const Ogre::TRect< Ogre::Real > &mapBounds)
Gets the color value at the specified position.
Ogre::Real _getDensityAt_Bilinear(Ogre::Real x, Ogre::Real z, const Ogre::TRect< Ogre::Real > &mapBounds)
MapFilter getFilter()
Returns the filtering mode being used for this density map.
static DensityMap * load(const Ogre::String &fileName, MapChannel channel=CHANNEL_COLOR)
void setFilter(MapFilter filter)
Sets the filtering mode used for this density map.
Ogre::Real _getDensityAt_Unfiltered(Ogre::Real x, Ogre::Real z, const Ogre::TRect< Ogre::Real > &mapBounds)
A data structure giving you full control over grass properties.
void setColorMapFilter(MapFilter filter)
Sets the filtering mode used for color maps.
GrassTechnique renderTechnique
void setMaximumSize(float width, float height)
Sets the maximum size that grass quads/billboards will be.
Ogre::MaterialPtr material
void setDensityMapFilter(MapFilter filter)
Sets the filtering mode used for density maps.
void setColorMap(const Ogre::String &mapFile, MapChannel channel=CHANNEL_COLOR)
Sets the color map used for this grass layer.
GrassLayer(PagedGeometry *geom, GrassLoader *ldr)
Do not create a GrassLayer directly - use GrassLoader->addLayer()
MapFilter densityMapFilter
Ogre::Real getMaxSlope() const
Get the maximum slope a grass blade can be placed on (as set by setMaxSlope()).
void setLightingEnabled(bool enabled)
Enables/disables lighting on this layer.
void setRenderTechnique(GrassTechnique style, bool blendBase=false)
Sets the technique used to render this grass layer.
unsigned int _populateGrassList_BilinearDM(PageInfo page, float *posBuff, unsigned int grassCount)
unsigned int _populateGrassList_UnfilteredDM(PageInfo page, float *posBuff, unsigned int grassCount)
void setMinimumSize(float width, float height)
Sets the minimum size that grass quads/billboards will be.
~GrassLayer()
Do not delete a GrassLayer yourself - the GrassLoader will do this automatically when it's deleted.
void setFadeTechnique(FadeTechnique style)
Sets the technique used when fading out distant grass.
FadeTechnique fadeTechnique
void setAnimationEnabled(bool enabled)
Enables/disables animation on this layer.
void setDensityMap(const Ogre::String &mapFile, MapChannel channel=CHANNEL_COLOR)
Sets the density map used for this grass layer.
unsigned int _populateGrassList_Uniform(PageInfo page, float *posBuff, unsigned int grassCount)
void setMaterialName(const Ogre::String &matName)
Sets the material that is applied to all grass billboards/quads.
A PageLoader-derived object you can use with PagedGeometry to produce realistic grass.
static unsigned long GUID
void deleteLayer(GrassLayer *layer)
Removes and deletes a grass layer from the scene.
void * heightFunctionUserData
static Ogre::String getUniqueID()
Ogre::Real(* heightFunction)(Ogre::Real x, Ogre::Real z, void *userData)
GrassLoader(PagedGeometry *geom)
Creates a new GrassLoader object.
void frameUpdate()
INTERNAL FUNCTION - DO NOT USE.
Ogre::Mesh * generateGrass_QUAD(PageInfo &page, GrassLayer *layer, const float *grassPositions, unsigned int grassCount)
Ogre::Mesh * generateGrass_CROSSQUADS(PageInfo &page, GrassLayer *layer, const float *grassPositions, unsigned int grassCount)
Ogre::Mesh * generateGrass_SPRITE(PageInfo &page, GrassLayer *layer, const float *grassPositions, unsigned int grassCount)
void unloadPage(PageInfo &page)
INTERNAL FUNCTION - DO NOT USE.
void loadPage(PageInfo &page)
INTERNAL FUNCTION - DO NOT USE.
GrassLayer * addLayer(const Ogre::String &material)
Adds a grass layer to the scene.
std::list< GrassLayer * > layerList
Ogre::SceneNode * rootNode
void addEntity(Ogre::Entity *ent, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, const Ogre::Vector3 &scale, const Ogre::ColourValue &color)
Add an entity to the page, at the specified position, rotation, and scale.
std::list< Ogre::SceneNode * > nodeList
Ogre::SceneManager * sceneMgr
void removeEntities()
Remove all geometry/entities from the page completely.
void init(PagedGeometry *geom, const Ogre::Any &data)
Prepare a geometry page for use.
void setVisible(bool visible)
Toggle the entire page's visibility.
static unsigned long GUID
void addEntity(Ogre::Entity *ent, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, const Ogre::Vector3 &scale=Ogre::Vector3::UNIT_SCALE, const Ogre::ColourValue &color=Ogre::ColourValue::White)
Call this from loadPage() to add an entity to the page being loaded.
A class providing highly optimized methods for rendering massive amounts of geometry.
Ogre::uint8 getRenderQueue() const
Returns the rendering queue that paged geometry was constructed with.
const std::list< GeometryPageManager * > & getDetailLevels()
Returns a reference to a list of all added detail levels.
Ogre::SceneNode * getSceneNode() const
Gets the scene node to which all PagedGeometry geometry is attached.
Ogre::SceneManager * getSceneManager() const
Gets the scene manager which is being used to display the geometry.
Ogre::Camera * getCamera() const
Gets the camera which is used to calculate levels of detail.
float getRangeRandom(float start, float end)
MapFilter
Specifies the filtering method used to interpret property maps.
@ MAPFILTER_NONE
Use no filtering - fast, but may appear blocky.
@ MAPFILTER_BILINEAR
Use bilinear filtering - slower, but will appear less blocky.
GrassTechnique
A technique used to render grass.
@ GRASSTECH_QUAD
Grass constructed of randomly placed and rotated quads.
@ GRASSTECH_CROSSQUADS
Grass constructed of two quads forming a "X" cross shape.
@ GRASSTECH_SPRITE
Grass constructed of camera-facing billboard quads.
FadeTechnique
A technique used to fade grass into the distance.
@ FADETECH_ALPHAGROW
Grass that fades in by slowly becoming opaque while it "grows" up out of the ground....
@ FADETECH_ALPHA
Grass that fades into the distance with transparency. Fairly effective in most cases.
@ FADETECH_GROW
Grass that fades in by "growing" up out of the ground. Very effective when grass fades in against the...
MapChannel
Specifies which color channel(s) to extract from an image.
Useful page information supplied to a pageloader.
Ogre::Vector3 centerPoint
The center of the page (simply the middle of the bounds).
TBounds bounds
The page boundaries in which all entities should be placed.
std::vector< Ogre::Mesh * > meshList