Rigs of Rods 2023.09
Soft-body Physics Simulation
Loading...
Searching...
No Matches
GodRaysManager.cpp
Go to the documentation of this file.
1/*
2--------------------------------------------------------------------------------
3This source file is part of sssHydrax.
4sssHydrax is a modified version of Hydrax (Copyright (C) 2008 Xavier Verguín González)
5to adapt it to SonSilentSea.
6
7This program is free software; you can redistribute it and/or modify it under
8the terms of the GNU Lesser General Public License as published by the Free Software
9Foundation; either version 2 of the License, or (at your option) any later
10version.
11
12This program is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License along with
17this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18Place - Suite 330, Boston, MA 02111-1307, USA, or go to
19http://www.gnu.org/copyleft/lesser.txt.
20
21Author: Jose Luis Cercós Pita
22--------------------------------------------------------------------------------
23*/
24
25#include <GodRaysManager.h>
26
27#include <Hydrax.h>
28
29#define _def_GodRays_Projector_Camera_Name "_Hydrax_GodRays_Projector_Camera"
30#define _def_GodRays_ManualObject_Name "_Hydrax_GodRays_ManualObject"
31#define _def_GodRays_Depth_Map "_Hydrax_GodRays_Depth_Map"
32
33#define _def_GodRays_Material_Name "_Hydrax_GodRays_Material"
34#define _def_GodRays_Shader_VP_Name "_Hydrax_GodRays_VP"
35#define _def_GodRays_Shader_FP_Name "_Hydrax_GodRays_FP"
36
37#define _def_GodRaysDepth_Material_Name "_Hydrax_GodRaysDepth_Material"
38#define _def_GodRaysDepth_Shader_VP_Name "_Hydrax_GodRaysDepth_VP"
39#define _def_GodRaysDepth_Shader_FP_Name "_Hydrax_GodRaysDepth_FP"
40
41const Ogre::Matrix4
43 0.5, 0, 0, 0.5,
44 0, -0.5, 0, 0.5,
45 0, 0, 1, 0,
46 0, 0, 0, 1);
47
48namespace Hydrax
49{
51 : mCreated(false)
52 , mManualGodRays(0)
53 , mProjectorCamera(0)
54 , mProjectorSN(0)
55 , mPerlin(0)
56 , mNoiseDerivation(3)
57 , mNoisePositionMultiplier(50)
58 , mNoiseYNormalMultiplier(10)
59 , mNoiseNormalMultiplier(0.175)
60 , mSimulationSpeed(5.0f)
61 , mNumberOfRays(100)
62 , mRaysSize(0.03f)
63 , mObjectsIntersections(false)
64 , mHydrax(h)
65 {
66 for (int k = 0; k < 2; k++)
67 {
68 mMaterials[k].reset();
69 }
70 }
71
76
78 {
79 if (mCreated)
80 {
81 remove();
82 }
83
84 // Create our perlin noise module
85 mPerlin = new Noise::Perlin(Noise::Perlin::Options(8, 0.085f, 0.49, 2, 0.672));
86 mPerlin->create();
87
88 // Initial values, some of them need to be updated each frame
90 mProjectorCamera->setProjectionType(Ogre::PT_PERSPECTIVE);
91 // Not forget to set near+far distance in materials
92 mProjectorCamera->setNearClipDistance(8);
93 mProjectorCamera->setFarClipDistance(40);
94 mProjectorCamera->setAspectRatio(1);
95 mProjectorCamera->setFOVy(Ogre::Degree(45.0f));
96 mProjectorCamera->setVisible(false);
97 mProjectorSN = mHydrax->getSceneManager()->getRootSceneNode()->createChildSceneNode();
98 mProjectorSN->setPosition(0,0,0);
99 mProjectorSN->attachObject(mProjectorCamera);
100 mProjectorSN->setDirection(0, -1, 0);
101
103 {
105 }
106
108
109 std::vector<Ogre::Technique*>::iterator TechIt;
110
111 for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++)
112 {
113 if (!(*TechIt))
114 {
115 mDepthTechniques.erase(TechIt);
116 // TechIt-- ?
117 continue;
118 }
119
120 addDepthTechnique((*TechIt), false);
121 }
122
124
125 mCreated = true;
126 }
127
129 {
131 mManualGodRays->setDynamic(true);
133
134 mManualGodRays->begin(_def_GodRays_Material_Name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
135 mManualGodRays->setRenderQueueGroup(Ogre::RENDER_QUEUE_9+1);
136
137 for(int r = 0; r < mNumberOfRays; r++)
138 {
139 // Rays are modeled as pyramids, 12 vertex each ray
140 for (int k = 0; k < 12; k++)
141 {
142 mManualGodRays->position(0, 0, 0);
143 mManualGodRays->index(k);
144 }
145 }
146
147 mManualGodRays->end();
148 mProjectorSN->attachObject(mManualGodRays);
149 }
150
152 {
153 if (!mCreated)
154 {
155 return;
156 }
157
158 delete mPerlin;
159 mPerlin = static_cast<Noise::Perlin*>(NULL);
160
161 mHydrax->getSceneManager()->destroyManualObject(mManualGodRays);
162 mManualGodRays = static_cast<Ogre::ManualObject*>(NULL);
163
164 if (Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRays_Material_Name))
165 {
166 Ogre::MaterialManager::getSingleton().remove(_def_GodRays_Material_Name);
167
168 Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRays_Shader_VP_Name);
169 Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRays_Shader_FP_Name);
170 Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRays_Shader_VP_Name);
171 Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRays_Shader_FP_Name);
172 }
173
174 if (Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRaysDepth_Material_Name))
175 {
176 Ogre::MaterialManager::getSingleton().remove(_def_GodRaysDepth_Material_Name);
177
178 Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRaysDepth_Shader_VP_Name);
179 Ogre::HighLevelGpuProgramManager::getSingleton().unload(_def_GodRaysDepth_Shader_FP_Name);
180 Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRaysDepth_Shader_VP_Name);
181 Ogre::HighLevelGpuProgramManager::getSingleton().remove(_def_GodRaysDepth_Shader_FP_Name);
182 }
183
184 for (int k = 0; k < 2; k++)
185 {
186 mMaterials[k].reset();
187 }
188
189 if (mProjectorRTT)
190 {
191 Ogre::RenderTarget* RT = mProjectorRTT->getBuffer()->getRenderTarget();
192 RT->removeAllListeners();
193 RT->removeAllViewports();
194
195 Ogre::TextureManager::getSingleton().remove(mProjectorRTT->getName());
196 mProjectorRTT.reset();
197 }
198
199 mHydrax->getSceneManager()->destroyCamera(mProjectorCamera);
200 mProjectorCamera = static_cast<Ogre::Camera*>(NULL);
201
202 mProjectorSN->detachAllObjects();
203 mProjectorSN->getParentSceneNode()->removeAndDestroyChild(mProjectorSN);
204 mProjectorSN = static_cast<Ogre::SceneNode*>(NULL);
205
206 mCreated = false;
207 }
208
209 void GodRaysManager::update(const Ogre::Real& timeSinceLastFrame)
210 {
212 {
213 return;
214 }
215
216 mPerlin->update(timeSinceLastFrame);
217
218 _updateRays();
220
222 {
224 mProjectorRTT->getBuffer()->getRenderTarget()->update();
225 }
226 }
227
229 {
230 // Get frustum corners to calculate far plane dimensions
231 const Ogre::Vector3 *FrustumCorners = mProjectorCamera->getWorldSpaceCorners();
232 // Calcule far plane dimensions
233 float FarWidth = (FrustumCorners[4] - FrustumCorners[5]).length();
234 Ogre::Real RaysLength = mProjectorCamera->getFarClipDistance();
235
236 mManualGodRays->beginUpdate(0);
237
238 Ogre::Vector2 Pos;
239 Ogre::Real Dis, RayLength;
240
241 // Rays are modeled as piramids, 12 vertex each ray
242 //
243 // // 0\\
244 // /| | |
245 // || | |
246 // || | | (0,0) (1,0)
247 // || | | A B
248 // || | |
249 // |A----|-|B (0,1) (1,1)
250 // |/ |/ C D
251 // C------D
252
253 for(int k = 0; k < mNumberOfRays; k++)
254 {
255 Pos = _calculateRayPosition(k);
256 Dis = mRaysSize*RaysLength;
257 RayLength = RaysLength*(0.95+Pos.length());
258
259 Pos *= FarWidth/2;
260
261 // 4 Planes, 3 vertices each plane, 12 vertices per ray
262 // ----> 1/4
263 // 0
264 mManualGodRays->position(0, 0, 0);
265 // A
266 mManualGodRays->position(Pos.x, Pos.y, -RayLength);
267 // B
268 mManualGodRays->position(Pos.x+Dis, Pos.y, -RayLength);
269 // ----> 2/4
270 // 0
271 mManualGodRays->position(0, 0, 0);
272 // D
273 mManualGodRays->position(Pos.x+Dis, Pos.y+Dis, -RayLength);
274 // B
275 mManualGodRays->position(Pos.x+Dis, Pos.y, -RayLength);
276 // ----> 3/4
277 // 0
278 mManualGodRays->position(0, 0, 0);
279 // C
280 mManualGodRays->position(Pos.x, Pos.y+Dis, -RayLength);
281 // D
282 mManualGodRays->position(Pos.x+Dis, Pos.y+Dis, -RayLength);
283 // ----> 4/4
284 // 0
285 mManualGodRays->position(0, 0, 0);
286 // C
287 mManualGodRays->position(Pos.x, Pos.y+Dis, -RayLength);
288 // A
289 mManualGodRays->position(Pos.x, Pos.y, -RayLength);
290 }
291
292 mManualGodRays->end();
293 }
294
295 Ogre::Vector2 GodRaysManager::_calculateRayPosition(const int& RayNumber)
296 {
297 Ogre::Real sqrt_NumberOfRays = Ogre::Math::Sqrt(mNumberOfRays);
298 Ogre::Real XCoord = RayNumber;
299
300 while (XCoord >= sqrt_NumberOfRays)
301 {
302 XCoord -= sqrt_NumberOfRays;
303 }
304
305 Ogre::Vector2 RayPos =
306 Ogre::Vector2( // X coord
307 static_cast<int>(XCoord),
308 // Y coord
309 static_cast<int>((RayNumber+sqrt_NumberOfRays)/sqrt_NumberOfRays)-1);
310
311 RayPos /= sqrt_NumberOfRays;
312 RayPos -= Ogre::Vector2(0.5, 0.5);
313 RayPos *= 2;
314
315 Ogre::Vector2 Position = RayPos*mNoisePositionMultiplier + Ogre::Vector2(mProjectorSN->getPosition().x, mProjectorSN->getPosition().z);
316
317 Ogre::Vector3
318 m_x = Ogre::Vector3(Position.x-mNoiseDerivation, mPerlin->getValue(Position.x-mNoiseDerivation,0), 0),
319 p_x = Ogre::Vector3(Position.x+mNoiseDerivation, mPerlin->getValue(Position.x+mNoiseDerivation,0), 0),
320 m_y = Ogre::Vector3(0, mPerlin->getValue(0,Position.y-mNoiseDerivation), Position.y-mNoiseDerivation),
321 p_y = Ogre::Vector3(0, mPerlin->getValue(0,Position.y+mNoiseDerivation), Position.y+mNoiseDerivation);
322
325
326 Ogre::Vector3 Normal = (p_x-m_x).crossProduct((p_y-m_y));
327
328 Normal *= mNoiseNormalMultiplier;
329
330 return RayPos + Ogre::Vector2(Normal.x, Normal.z);
331 }
332
333 void GodRaysManager::setNumberOfRays(const int& NumberOfRays)
334 {
335 mNumberOfRays = NumberOfRays;
336
337 if (!mCreated)
338 {
339 return;
340 }
341
342 mProjectorSN->detachObject(mManualGodRays);
343
344 mHydrax->getSceneManager()->destroyManualObject(mManualGodRays);
345 mManualGodRays = static_cast<Ogre::ManualObject*>(NULL);
346
348 }
349
351 {
352 mObjectsIntersections = Enable;
353
354 const HydraxComponent& Components = mHydrax->getComponents();
355
356 create(Components);
357 }
358
360 {
362 {
363 return;
364 }
365
366 Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters;
367
368 // God rays material
369 VP_Parameters = mMaterials[0]->getTechnique(0)->getPass(0)->getVertexProgramParameters();
370 FP_Parameters = mMaterials[0]->getTechnique(0)->getPass(0)->getFragmentProgramParameters();
371
372 Ogre::Matrix4 TexViewProj =
374 mProjectorCamera->getProjectionMatrixWithRSDepth() *
375 mProjectorCamera->getViewMatrix();
376
377 VP_Parameters->setNamedConstant("uTexViewProj", TexViewProj);
378
379 FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition());
380 FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance());
381
382 // Depth material
383 FP_Parameters = mMaterials[1]->getTechnique(0)->getPass(0)->getFragmentProgramParameters();
384
385 FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition());
386 FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance());
387
388 std::vector<Ogre::Technique*>::iterator TechIt;
389
390 for(TechIt = mDepthTechniques.begin(); TechIt != mDepthTechniques.end(); TechIt++)
391 {
392 if (!(*TechIt))
393 {
394 mDepthTechniques.erase(TechIt);
395 // TechIt-- ?
396 continue;
397 }
398
399 (*TechIt)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightPosition", mProjectorSN->getPosition());
400 (*TechIt)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance());
401 }
402 }
403
405 {
406 const Ogre::Vector3& SunPosition = mHydrax->getSunPosition();
407 const Ogre::Vector3& CameraPosition = mHydrax->getCamera()->getDerivedPosition();
408
409 Ogre::Plane WaterPlane = Ogre::Plane(Ogre::Vector3(0,1,0), mHydrax->getPosition());
410 Ogre::Ray SunToCameraRay = Ogre::Ray(SunPosition, CameraPosition-SunPosition);
411
412 Ogre::Vector3 WaterProjectionPoint = SunToCameraRay.getPoint(SunToCameraRay.intersects(WaterPlane).second);
413
414 mProjectorSN->setPosition(WaterProjectionPoint);
415 mProjectorCamera->setFarClipDistance((WaterProjectionPoint-CameraPosition).length());
416 mProjectorSN->setDirection(-(WaterProjectionPoint-CameraPosition).normalisedCopy(), Ogre::Node::TS_WORLD);
417 }
418
420 {
421 Ogre::String VertexProgramData, FragmentProgramData;
422 Ogre::GpuProgramParametersSharedPtr VP_Parameters, FP_Parameters;
423 Ogre::String EntryPoints[2];
425 {
426 EntryPoints[0] = Ogre::String("main");
427 EntryPoints[1] = Ogre::String("main");
428 }
429 else
430 {
431 EntryPoints[0] = Ogre::String("main_vp");
432 EntryPoints[1] = Ogre::String("main_fp");
433 }
434 Ogre::String GpuProgramsData[2]; Ogre::String GpuProgramNames[2];
435 MaterialManager *mMaterialManager = mHydrax->getMaterialManager();
436
437 int NumberOfDepthChannels = 0;
438 Ogre::String GB[2] = {"0, 1, 0", "0, 0, 1"};
439
441 {
442 NumberOfDepthChannels++;
443 }
444
445 // God Rays material
446
447 VertexProgramData = "";
448 FragmentProgramData = "";
449
450 // Vertex program
451
452 switch (mHydrax->getShaderMode())
453 {
455 {
456 VertexProgramData +=
457 Ogre::String(
458 "void main_vp(\n") +
459 // IN
460 "float4 iPosition : POSITION,\n" +
461 // OUT
462 "out float4 oPosition : POSITION,\n";
464 {
465 VertexProgramData += Ogre::String(
466 "out float3 oPosition_ : TEXCOORD0,\n") +
467 "out float4 oProjUV : TEXCOORD1,\n" +
468 // UNIFORM
469 "uniform float4x4 uWorld,\n" +
470 "uniform float4x4 uTexViewProj,\n";
471 }
472 VertexProgramData += Ogre::String(
473 "uniform float4x4 uWorldViewProj)\n") +
474 "{\n" +
475 "oPosition = mul(uWorldViewProj, iPosition);\n";
477 {
478 VertexProgramData += Ogre::String(
479 "float4 wPos = mul(uWorld, iPosition);\n")+
480 "oPosition_ = wPos.xyz;\n"+
481 "oProjUV = mul(uTexViewProj, wPos);\n";
482 }
483 VertexProgramData +=
484 "}\n";
485 }
486 break;
487
489 {
490 VertexProgramData += Ogre::String( "\n" );
491 // UNIFORMS
493 {
494 VertexProgramData += Ogre::String(
495 "uniform mat4 uWorld;\n") +
496 "uniform mat4 uTexViewProj;\n";
497 }
498 // IN
499 // OUT
501 {
502 VertexProgramData += Ogre::String(
503 "varying vec3 Position_;\n") +
504 "varying vec4 ProjUV;\n";
505 }
506 // main function
507 VertexProgramData += Ogre::String(
508 "void main()\n") +
509 "{\n" +
510 "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n";
512 {
513 VertexProgramData += Ogre::String(
514 "vec4 wPos = uWorld * gl_Vertex);\n")+
515 "Position_ = wPos.xyz;\n"+
516 "ProjUV = uTexViewProj * wPos;\n";
517 }
518 VertexProgramData +=
519 "}\n";
520 }
521 break;
522 }
523
524 // Fragment program
525
526 switch (mHydrax->getShaderMode())
527 {
529 {
531 FragmentProgramData +=
532 Ogre::String(
533 "void main_fp(\n") +
534 // IN
535 "float3 iPosition : TEXCOORD0,\n" +
536 "float4 iProjUV : TEXCOORD1,\n" +
537 // OUT
538 "out float4 oColor : COLOR,\n" +
539 // UNIFORM
540 "uniform float3 uLightPosition,\n"+
541 "uniform float uLightFarClipDistance,\n" +
542 "uniform sampler2D uDepthMap : register(s0))\n" +
543 "{\n" +
544 "iProjUV = iProjUV / iProjUV.w;\n"+
545 "float Depth = tex2D(uDepthMap, iProjUV.xy).r;\n"+
546 "if (Depth < saturate( length(iPosition-uLightPosition) / uLightFarClipDistance ))\n"+
547 "{\n"+
548 "oColor = float4(0,0,0,1);\n"+
549 "}\n"+
550 "else\n"+
551 "{\n"+
552 "oColor = float4(float3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1);\n"+
553 "}\n"+
554 "}\n";
555 else
556 FragmentProgramData +=
557 Ogre::String(
558 "void main_fp(\n") +
559 // OUT
560 "out float4 oColor : COLOR)\n" +
561 "{\n" +
562 "oColor = float4(float3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1);\n"+
563 "}\n";
564 }
565 break;
566
568 {
570 FragmentProgramData += Ogre::String( "\n" ) +
571 // UNIFORMS
572 "uniform vec3 uLightPosition;\n"+
573 "uniform float uLightFarClipDistance;\n" +
574 "uniform sampler2D uDepthMap;\n" +
575 // IN
576 "varying vec3 Position_;\n" +
577 "varying vec4 ProjUV;\n" +
578 // OUT
579 // main function
580 "void main()\n" +
581 "{\n" +
582 "ProjUV /= ProjUV.w;\n" +
583 "float Depth = texture2D(uDepthMap, ProjUV.xy).x;\n" +
584 "if(Depth < clamp( length(Position_-uLightPosition) / uLightFarClipDistance ), 0.0, 1.0)\n" +
585 "{\n"+
586 "gl_FragColor = vec4(0.0,0.0,0.0,1.0);\n"+
587 "}\n"+
588 "else\n"+
589 "{\n"+
590 "gl_FragColor = vec4(vec3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1.0);\n"+
591 "}\n"+
592 "}\n";
593 else
594 FragmentProgramData += Ogre::String( "\n" ) +
595 // UNIFORMS
596 "uniform vec3 uLightPosition;\n"+
597 "uniform float uLightFarClipDistance;\n" +
598 "uniform sampler2D uDepthMap;\n" +
599 // IN
600 "varying vec3 Position_;\n" +
601 "varying vec4 ProjUV;\n" +
602 // OUT
603 // main function
604 "void main()\n" +
605 "{\n" +
606 "gl_FragColor = vec4(vec3(" + GB[NumberOfDepthChannels] + ") * 0.1, 1.0);\n"+
607 "}\n";
608 }
609 break;
610 }
611
612 // Build our material
613 mMaterials[0] = Ogre::MaterialManager::getSingleton().
615 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
616
617 Ogre::Pass *GR_Technique0_Pass0 = mMaterials[0]->getTechnique(0)->getPass(0);
618
619 GR_Technique0_Pass0->setLightingEnabled(false);
620 GR_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE);
621 GR_Technique0_Pass0->setDepthWriteEnabled(false);
622 GR_Technique0_Pass0->setDepthCheckEnabled(mObjectsIntersections);
623 GR_Technique0_Pass0->setSceneBlending(Ogre::SBT_ADD);
624
625 GpuProgramsData[0] = VertexProgramData; GpuProgramsData[1] = FragmentProgramData;
626 GpuProgramNames[0] = _def_GodRays_Shader_VP_Name; GpuProgramNames[1] = _def_GodRays_Shader_FP_Name;
627
628 mMaterialManager->fillGpuProgramsToPass(GR_Technique0_Pass0, GpuProgramNames, mHydrax->getShaderMode(), EntryPoints, GpuProgramsData);
629
630 VP_Parameters = GR_Technique0_Pass0->getVertexProgramParameters();
631 FP_Parameters = GR_Technique0_Pass0->getFragmentProgramParameters();
632
634 {
635 VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
636 }
637
639 {
640 return;
641 }
642
643 Ogre::Matrix4 TexViewProj =
645 mProjectorCamera->getProjectionMatrixWithRSDepth() *
646 mProjectorCamera->getViewMatrix();
647
648 VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
649 VP_Parameters->setNamedConstant("uTexViewProj", TexViewProj);
650
651 FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition());
652 FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance());
653
654 int GLSLTextUnit = 0;
656 {
657 FP_Parameters->setNamedConstant("uDepthMap", GLSLTextUnit);
658 GLSLTextUnit++;
659 }
660 GR_Technique0_Pass0->createTextureUnitState(_def_GodRays_Depth_Map)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
661 GR_Technique0_Pass0->getTextureUnitState(0)->setTextureName(_def_GodRays_Depth_Map);
662
663 // Depth material
664
665 VertexProgramData = "";
666 FragmentProgramData = "";
667
668 // Vertex program
669
670 switch (mHydrax->getShaderMode())
671 {
673 {
674 VertexProgramData +=
675 Ogre::String(
676 "void main_vp(\n") +
677 // IN
678 "float4 iPosition : POSITION,\n" +
679 "float2 iUV : TEXCOORD0,\n" +
680 // OUT
681 "out float4 oPosition : POSITION,\n" +
682 "out float3 oPosition_ : TEXCOORD0,\n" +
683 // UNIFORM
684 "uniform float4x4 uWorld,\n" +
685 "uniform float4x4 uWorldViewProj)\n" +
686 "{\n" +
687 "oPosition = mul(uWorldViewProj, iPosition);\n"+
688 "float4 wPos = mul(uWorld, iPosition);\n"+
689 "oPosition_ = wPos.xyz;\n"+
690 "}\n";
691 }
692 break;
693
695 {
696 VertexProgramData += Ogre::String( "\n" ) +
697 // UNIFORMS
698 "uniform mat4 uWorld;\n" +
699 // IN
700 // OUT
701 "varying vec3 Position_;\n" +
702 // main function
703 "void main()\n" +
704 "{\n" +
705 "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"+
706 "vec4 wPos = uWorld * gl_Vertex;\n"+
707 "Position_ = wPos.xyz;\n"+
708 "}\n";
709 }
710 break;
711 }
712
713 // Fragment program
714
715 switch (mHydrax->getShaderMode())
716 {
718 {
719 FragmentProgramData +=
720 Ogre::String(
721 "void main_fp(\n") +
722 // IN
723 "float3 iPosition : TEXCOORD0,\n" +
724 // OUT
725 "out float4 oColor : COLOR,\n" +
726 // UNIFORM
727 "uniform float3 uLightPosition,\n" +
728 "uniform float uLightFarClipDistance)\n" +
729 "{\n" +
730 "float depth = saturate( length(iPosition-uLightPosition) / uLightFarClipDistance );\n"+
731 "oColor = float4(depth, 0, 0, 0);\n"+
732 "}\n";
733 }
734 break;
735
737 {
738 VertexProgramData += Ogre::String( "\n" ) +
739 // UNIFORMS
740 "uniform vec3 uLightPosition;\n" +
741 "uniform float uLightFarClipDistance;\n" +
742 // IN
743 "varying vec3 Position_;\n" +
744 // OUT
745 // main function
746 "void main()\n" +
747 "{\n" +
748 "float depth = clamp( length(Position_-uLightPosition) / uLightFarClipDistance , 0.0, 1.0);\n"+
749 "gl_FragColor = vec4(depth, 0.0, 0.0, 0.0);\n"+
750 "}\n";
751 }
752 break;
753 }
754
755 // Build our material
756 mMaterials[1] = Ogre::MaterialManager::getSingleton().
758 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
759
760 Ogre::Pass *GRD_Technique0_Pass0 = mMaterials[1]->getTechnique(0)->getPass(0);
761
762 mMaterials[1]->getTechnique(0)->setSchemeName("HydraxGodRaysDepth");
763
764 GRD_Technique0_Pass0->setLightingEnabled(false);
765 GRD_Technique0_Pass0->setCullingMode(Ogre::CULL_NONE);
766
767 GpuProgramsData[0] = VertexProgramData; GpuProgramsData[1] = FragmentProgramData;
768 GpuProgramNames[0] = _def_GodRaysDepth_Shader_VP_Name; GpuProgramNames[1] = _def_GodRaysDepth_Shader_FP_Name;
769
770 mMaterialManager->fillGpuProgramsToPass(GRD_Technique0_Pass0, GpuProgramNames, mHydrax->getShaderMode(), EntryPoints, GpuProgramsData);
771
772 VP_Parameters = GRD_Technique0_Pass0->getVertexProgramParameters();
773 FP_Parameters = GRD_Technique0_Pass0->getFragmentProgramParameters();
774
776 {
777 VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
778 }
779 VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
780
781 FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition());
782 FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance());
783 }
784
785 void GodRaysManager::addDepthTechnique(Ogre::Technique *Technique, const bool& AutoUpdate)
786 {
787 if (!Ogre::MaterialManager::getSingleton().resourceExists(_def_GodRaysDepth_Material_Name))
788 {
789 HydraxLOG("GodRaysManager::addDepthTechnique(...) Objects intersection must be enabled and Hydrax::create() already called, skipping...");
790
791 return;
792 }
793
794 Technique->removeAllPasses();
795 Technique->createPass();
796 Technique->setSchemeName("HydraxGodRaysDepth");
797
798 Ogre::Pass *DM_Technique_Pass0 = Technique->getPass(0);
799
800 DM_Technique_Pass0->setVertexProgram(_def_GodRaysDepth_Shader_VP_Name);
801 DM_Technique_Pass0->setFragmentProgram(_def_GodRaysDepth_Shader_FP_Name);
802
803 Ogre::GpuProgramParametersSharedPtr VP_Parameters = DM_Technique_Pass0->getVertexProgramParameters();
804 Ogre::GpuProgramParametersSharedPtr FP_Parameters = DM_Technique_Pass0->getFragmentProgramParameters();
805
807 {
808 VP_Parameters->setNamedAutoConstant("uWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
809 }
810 VP_Parameters->setNamedAutoConstant("uWorld", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
811
812 FP_Parameters->setNamedConstant("uLightPosition", mProjectorSN->getPosition());
813 FP_Parameters->setNamedConstant("uLightFarClipDistance", mProjectorCamera->getFarClipDistance());
814
815 if (AutoUpdate)
816 {
817 mDepthTechniques.push_back(Technique);
818 }
819 }
820
821 bool GodRaysManager::_isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const
822 {
823 if (List & ToCheck)
824 {
825 return true;
826 }
827
828 if (ToCheck == HYDRAX_COMPONENTS_NONE && List == HYDRAX_COMPONENTS_NONE)
829 {
830 return true;
831 }
832
833 if (ToCheck == HYDRAX_COMPONENTS_ALL && List == HYDRAX_COMPONENTS_ALL)
834 {
835 return true;
836 }
837
838 return false;
839 }
840
842 {
843 mProjectorRTT = Ogre::TextureManager::getSingleton()
844 .createManual(_def_GodRays_Depth_Map,
845 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
846 Ogre::TEX_TYPE_2D,
847 // 256*256 must be sufficient
848 256,
849 256,
850 0,
851 // Only one channel
852 Ogre::PF_L8,
853 Ogre::TU_RENDERTARGET);
854
855 Ogre::RenderTarget* RT_Texture = mProjectorRTT->getBuffer()->getRenderTarget();
856 RT_Texture->setAutoUpdated(false);
857
858 Ogre::Viewport *RT_Texture_Viewport = RT_Texture->addViewport(mProjectorCamera);
859 RT_Texture_Viewport->setClearEveryFrame(true);
860 RT_Texture_Viewport->setMaterialScheme("HydraxGodRaysDepth");
861 RT_Texture_Viewport->setBackgroundColour(Ogre::ColourValue::White);
862 RT_Texture_Viewport->setOverlaysEnabled(false);
863 RT_Texture_Viewport->setSkiesEnabled(false);
864 RT_Texture_Viewport->setShadowsEnabled(false);
866 RT_Texture->addListener(&mDepthMapListener);
867 }
868
869 void GodRaysManager::DepthMapListener::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
870 {
871 Ogre::SceneManager::MovableObjectIterator EntityIterator = mGodRaysManager->mHydrax->getSceneManager()->getMovableObjectIterator("Entity");
872 Ogre::Entity * CurrentEntity = NULL;
873 unsigned int k = 0;
874
875 mGodRaysManager->mHydrax->getMesh()->getEntity()->setVisible(false);
876
877 while( EntityIterator.hasMoreElements() )
878 {
879 CurrentEntity = static_cast<Ogre::Entity *>(EntityIterator.peekNextValue());
880
881 for( k = 0; k < CurrentEntity->getNumSubEntities(); k++ )
882 {
883 mMaterials.push(CurrentEntity->getSubEntity(k)->getMaterialName());
884 CurrentEntity->getSubEntity(k)->setMaterialName(_def_GodRaysDepth_Material_Name);
885 }
886
887 EntityIterator.moveNext();
888 }
889 }
890
891 void GodRaysManager::DepthMapListener::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
892 {
893 Ogre::SceneManager::MovableObjectIterator EntityIterator = mGodRaysManager->mHydrax->getSceneManager()->getMovableObjectIterator("Entity");
894 Ogre::Entity * CurrentEntity = NULL;
895 unsigned int k = 0;
896
897 mGodRaysManager->mHydrax->getMesh()->getEntity()->setVisible(true);
898
899 while( EntityIterator.hasMoreElements() )
900 {
901 CurrentEntity = static_cast<Ogre::Entity *>(EntityIterator.peekNextValue());
902
903 for( k = 0; k < CurrentEntity->getNumSubEntities(); k++ )
904 {
905 CurrentEntity->getSubEntity(k)->setMaterialName(mMaterials.front());
906 mMaterials.pop();
907 }
908
909 EntityIterator.moveNext();
910 }
911 }
912}
#define HydraxLOG(msg)
Definition Application.h:60
#define _def_GodRays_Shader_FP_Name
#define _def_GodRays_ManualObject_Name
#define _def_GodRays_Depth_Map
#define _def_GodRays_Shader_VP_Name
#define _def_GodRays_Material_Name
#define _def_GodRays_Projector_Camera_Name
#define _def_GodRaysDepth_Material_Name
#define _def_GodRaysDepth_Shader_VP_Name
const Ogre::Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(0.5, 0, 0, 0.5, 0, -0.5, 0, 0.5, 0, 0, 1, 0, 0, 0, 0, 1)
#define _def_GodRaysDepth_Shader_FP_Name
void postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
Funtion that is called after the Rtt will render.
std::queue< std::string > mMaterials
std::string to store entity's original materials name
void preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
Funtion that is called before the Rtt will render.
GodRaysManager * mGodRaysManager
God rays manager pointer.
bool mObjectsIntersections
Are god rays objects intersections active?
Ogre::ManualObject * mManualGodRays
Manual object to create god rays.
void setObjectIntersectionsEnabled(const bool &Enable)
Set objects intersections enabled.
bool mCreated
Has been create() already called?
Ogre::Vector2 _calculateRayPosition(const int &RayNumber)
Calculate the current position of a ray.
void _updateRays()
Update god rays.
void _updateProjector()
Update projector.
void _updateMaterialsParameters()
Update materials parameters.
Ogre::MaterialPtr mMaterials[2]
God rays materials 0-God rays, 1-Depth.
Ogre::Real mRaysSize
God rays size.
bool _isComponent(const HydraxComponent &List, const HydraxComponent &ToCheck) const
Is component in the given list?
Noise::Perlin * mPerlin
Our Perlin noise module.
Ogre::SceneNode * mProjectorSN
Projector scene node.
DepthMapListener mDepthMapListener
Depth RTT listener.
void update(const Ogre::Real &timeSinceLastFrame)
Call each frame.
Ogre::Real mNoiseDerivation
Noise parameters (Used in _calculateRayPosition(...))
Ogre::Real mNoiseNormalMultiplier
Normal multiplier.
Ogre::TexturePtr mProjectorRTT
For rays intersection with objects we use a depth map based technique Depth RTT texture.
Ogre::Real mNoisePositionMultiplier
PositionMultiplier value.
Ogre::Real mNoiseYNormalMultiplier
Y normal component multiplier.
void _createGodRays()
Create god rays manual object.
std::vector< Ogre::Technique * > mDepthTechniques
Technique vector for addDepthTechnique(...)
void addDepthTechnique(Ogre::Technique *Technique, const bool &AutoUpdate=true)
Add god rays depth technique to an especified material.
Hydrax * mHydrax
Hydrax parent pointer.
Ogre::Camera * mProjectorCamera
Camera used to project rays.
void create(const HydraxComponent &HC)
Create.
void _createMaterials(const HydraxComponent &HC)
Create materials that we need(God rays depth too if it's needed)
void _createDepthRTT()
Create depth RTT.
void setNumberOfRays(const int &NumberOfRays)
Set the number of god rays.
int mNumberOfRays
Number of rays.
GodRaysManager(Hydrax *h)
Constructor.
Mesh * getMesh()
Get Hydrax::Mesh.
Definition Hydrax.h:317
const HydraxComponent & getComponents() const
Get hydrax components selected.
Definition Hydrax.h:389
const Ogre::Vector3 & getSunPosition() const
Get sun position.
Definition Hydrax.h:468
Ogre::Camera * getCamera()
Get rendering camera.
Definition Hydrax.h:293
const Ogre::Vector3 & getPosition() const
Get water position.
Definition Hydrax.h:413
const MaterialManager::ShaderMode & getShaderMode() const
Get current shader mode.
Definition Hydrax.h:405
MaterialManager * getMaterialManager()
Get Hydrax::MaterialManager.
Definition Hydrax.h:325
Ogre::SceneManager * getSceneManager()
Get scene manager.
Definition Hydrax.h:309
const bool & _isCurrentFrameUnderwater() const
Is current frame underwater?
Definition Hydrax.h:621
Material/Shader manager class.
bool fillGpuProgramsToPass(Ogre::Pass *Pass, const Ogre::String GpuProgramNames[2], const ShaderMode &SM, const Ogre::String EntryPoints[2], const Ogre::String Data[2])
Fill GPU vertex and fragment program to a pass.
Ogre::Entity * getEntity()
Get entity.
Definition Mesh.h:221
Perlin noise module class.
Definition Perlin.h:74
void update(const Ogre::Real &timeSinceLastFrame)
Call it each frame.
Definition Perlin.cpp:367
void create()
Create.
Definition Perlin.cpp:63
float getValue(const float &x, const float &y)
Get the especified x/y noise value.
Definition Perlin.cpp:403
HydraxComponent
Hydrax flags to select components wich we want to use.
Definition Enums.h:58
@ HYDRAX_COMPONENTS_NONE
Definition Enums.h:70
@ HYDRAX_COMPONENTS_ALL
Definition Enums.h:71
@ HYDRAX_COMPONENT_CAUSTICS
Definition Enums.h:64
Struct wich contains Perlin noise module options.
Definition Perlin.h:79