RigsofRods
Soft-body Physics Simulation
AtmosphereManager.cpp
Go to the documentation of this file.
1 /*
2 --------------------------------------------------------------------------------
3 This source file is part of SkyX.
4 Visit http://www.paradise-studios.net/products/skyx/
5 
6 Copyright (C) 2009-2012 Xavier Verguín González <xavyiy@gmail.com>
7 
8 This program is free software; you can redistribute it and/or modify it under
9 the terms of the GNU Lesser General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12 
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20 http://www.gnu.org/copyleft/lesser.txt.
21 --------------------------------------------------------------------------------
22 */
23 
24 #include "AtmosphereManager.h"
25 
26 #include "SkyX.h"
27 
28 #include "GPUManager.h"
29 
30 namespace SkyX
31 {
33  : mSkyX(s)
34  , mOptions(Options())
35  {
36  }
37 
39  {
40  }
41 
42  void AtmosphereManager::_update(const Options& NewOptions, const bool& ForceToUpdateAll)
43  {
44  GPUManager *mGPUManager = mSkyX->getGPUManager();
45 
46  if (NewOptions.InnerRadius != mOptions.InnerRadius ||
47  NewOptions.OuterRadius != mOptions.OuterRadius ||
48  ForceToUpdateAll)
49  {
50  mOptions.InnerRadius = NewOptions.InnerRadius;
51  mOptions.OuterRadius = NewOptions.OuterRadius;
52 
53  float Scale = 1.0f / (mOptions.OuterRadius - mOptions.InnerRadius),
54  ScaleDepth = (mOptions.OuterRadius - mOptions.InnerRadius) / 2.0f,
55  ScaleOverScaleDepth = Scale / ScaleDepth;
56 
59 
60  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScale", Scale);
61  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScaleDepth", ScaleDepth);
62  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uScaleOverScaleDepth", ScaleOverScaleDepth);
63  }
64 
65  if (NewOptions.HeightPosition != mOptions.HeightPosition ||
66  ForceToUpdateAll)
67  {
69 
71  }
72 
74  NewOptions.SunIntensity != mOptions.SunIntensity ||
75  ForceToUpdateAll)
76  {
78 
79  float Kr4PI = mOptions.RayleighMultiplier * 4.0f * Ogre::Math::PI,
81 
82  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKr4PI", Kr4PI);
83  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKrESun", KrESun);
84  }
85 
86  if (NewOptions.MieMultiplier != mOptions.MieMultiplier ||
87  NewOptions.SunIntensity != mOptions.SunIntensity ||
88  ForceToUpdateAll)
89  {
91 
92  float Km4PI = mOptions.MieMultiplier * 4.0f * Ogre::Math::PI,
94 
95  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKm4PI", Km4PI);
96  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uKmESun", KmESun, false);
97  }
98 
99  if (NewOptions.NumberOfSamples != mOptions.NumberOfSamples ||
100  ForceToUpdateAll)
101  {
103 
104  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uNumberOfSamples", mOptions.NumberOfSamples);
105  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uSamples", static_cast<Ogre::Real>(mOptions.NumberOfSamples));
106  }
107 
108  if (NewOptions.WaveLength != mOptions.WaveLength ||
109  ForceToUpdateAll)
110  {
111  mOptions.WaveLength = NewOptions.WaveLength;
112 
113  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_VERTEX, "uInvWaveLength",
114  Ogre::Vector3(1.0f / Ogre::Math::Pow(mOptions.WaveLength.x, 4.0f),
115  1.0f / Ogre::Math::Pow(mOptions.WaveLength.y, 4.0f),
116  1.0f / Ogre::Math::Pow(mOptions.WaveLength.z, 4.0f)));
117  }
118 
119  if (NewOptions.G != mOptions.G ||
120  ForceToUpdateAll)
121  {
122  mOptions.G = NewOptions.G;
123 
124  mGPUManager->setGpuProgramParameter(GPUManager::GPUP_FRAGMENT, "uG", mOptions.G, false);
126  }
127 
128  if (NewOptions.Exposure != mOptions.Exposure ||
129  ForceToUpdateAll)
130  {
131  mOptions.Exposure = NewOptions.Exposure;
132 
134  }
135 
137  }
138 
139  const float AtmosphereManager::_scale(const float& cos, const float& uScaleDepth) const
140  {
141  float x = 1 - cos;
142  return uScaleDepth * Ogre::Math::Exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
143  }
144 
145  const Ogre::Vector3 AtmosphereManager::getColorAt(const Ogre::Vector3& Direction) const
146  {
147  /*if (Direction.y < 0)
148  {
149  return Ogre::Vector3(0,0,0);
150  }*/
151 
152  // Parameters
153  double Scale = 1.0f / (mOptions.OuterRadius - mOptions.InnerRadius),
154  ScaleDepth = (mOptions.OuterRadius - mOptions.InnerRadius) / 2.0f,
155  ScaleOverScaleDepth = Scale / ScaleDepth,
156  Kr4PI = mOptions.RayleighMultiplier * 4.0f * Ogre::Math::PI,
158  Km4PI = mOptions.MieMultiplier * 4.0f * Ogre::Math::PI,
160 
161  // --- Start vertex program simulation ---
162  Ogre::Vector3
163  uLightDir = mSkyX->getController()->getSunDirection(),
164  v3Pos = Direction.normalisedCopy(),
165  uCameraPos = Ogre::Vector3(0, mOptions.InnerRadius + (mOptions.OuterRadius-mOptions.InnerRadius)*mOptions.HeightPosition, 0),
166  uInvWaveLength = Ogre::Vector3(
167  1.0f / Ogre::Math::Pow(mOptions.WaveLength.x, 4.0f),
168  1.0f / Ogre::Math::Pow(mOptions.WaveLength.y, 4.0f),
169  1.0f / Ogre::Math::Pow(mOptions.WaveLength.z, 4.0f));
170 
171  // Get the ray from the camera to the vertex, and it's length (far point)
172  v3Pos.y += mOptions.InnerRadius;
173  Ogre::Vector3 v3Ray = v3Pos - uCameraPos;
174  double fFar = v3Ray.length();
175  v3Ray /= fFar;
176 
177  // Calculate the ray's starting position, then calculate its scattering offset
178  Ogre::Vector3 v3Start = uCameraPos;
179  double fHeight = uCameraPos.y,
180  fStartAngle = v3Ray.dotProduct(v3Start) / fHeight,
181  fDepth = Ogre::Math::Exp(ScaleOverScaleDepth * (mOptions.InnerRadius - uCameraPos.y)),
182  fStartOffset = fDepth * _scale(fStartAngle, ScaleDepth);
183 
184  // Init loop variables
185  double fSampleLength = fFar /(double)mOptions.NumberOfSamples,
186  fScaledLength = fSampleLength * Scale,
187  fHeight_, fDepth_, fLightAngle, fCameraAngle, fScatter;
188  Ogre::Vector3 v3SampleRay = v3Ray * fSampleLength,
189  v3SamplePoint = v3Start + v3SampleRay * 0.5f,
190  color = Ogre::Vector3(0,0,0), v3Attenuate;
191 
192  // Loop the ray
193  for (int i = 0; i < mOptions.NumberOfSamples; i++)
194  {
195  fHeight_ = v3SamplePoint.length();
196  fDepth_ = Ogre::Math::Exp(ScaleOverScaleDepth * (mOptions.InnerRadius-fHeight_));
197 
198  fLightAngle = uLightDir.dotProduct(v3SamplePoint) / fHeight_;
199  fCameraAngle = v3Ray.dotProduct(v3SamplePoint) / fHeight_;
200 
201  fScatter = (fStartOffset + fDepth*(_scale(fLightAngle, ScaleDepth) - _scale(fCameraAngle, ScaleDepth)));
202 
203  v3Attenuate = Ogre::Vector3(
204  Ogre::Math::Exp(-fScatter * (uInvWaveLength.x * Kr4PI + Km4PI)),
205  Ogre::Math::Exp(-fScatter * (uInvWaveLength.y * Kr4PI + Km4PI)),
206  Ogre::Math::Exp(-fScatter * (uInvWaveLength.z * Kr4PI + Km4PI)));
207 
208  // Accumulate color
209  v3Attenuate *= (fDepth_ * fScaledLength);
210  color += v3Attenuate;
211 
212  // Next sample point
213  v3SamplePoint += v3SampleRay;
214  }
215 
216  // Outputs
217  Ogre::Vector3 oRayleighColor = color * (uInvWaveLength * KrESun),
218  oMieColor = color * KmESun,
219  oDirection = uCameraPos - v3Pos;
220 
221  // --- End vertex program simulation ---
222  // --- Start fragment program simulation ---
223 
224  double cos = uLightDir.dotProduct(oDirection) / oDirection.length(),
225  cos2 = cos*cos,
226  rayleighPhase = 0.75 * (1.0 + 0.5*cos2),
227  g2 = mOptions.G*mOptions.G,
228  miePhase = 1.5f * ((1.0f - g2) / (2.0f + g2)) *
229  (1.0f + cos2) / Ogre::Math::Pow(1.0f + g2 - 2.0f * mOptions.G * cos, 1.5f);
230 
231  Ogre::Vector3 oColor;
232 
234  {
235  oColor = Ogre::Vector3(
236  1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.x + miePhase * oMieColor.x)),
237  1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.y + miePhase * oMieColor.y)),
238  1 - Ogre::Math::Exp(-mOptions.Exposure * (rayleighPhase * oRayleighColor.z + miePhase * oMieColor.z)));
239 
240  // For night rendering
241  oColor += Ogre::Math::Clamp<Ogre::Real>(((1 - std::max(oColor.x, std::max(oColor.y, oColor.z))*10)), 0, 1)
242  * (Ogre::Vector3(0.05, 0.05, 0.1)
243  * (2-0.75f*Ogre::Math::Clamp<Ogre::Real>(-uLightDir.y, 0, 1)) * Ogre::Math::Pow(1-Direction.y, 3));
244  }
245  else
246  {
247  oColor = mOptions.Exposure * (rayleighPhase * oRayleighColor + miePhase * oMieColor);
248 
249  Ogre::Real nightmult = Ogre::Math::Clamp<Ogre::Real>(((1 - std::max(oColor.x, std::max(oColor.y, oColor.z))*10)), 0, 1);
250 
251  // For night rendering
252  Ogre::Vector3 nightCol = Ogre::Vector3(0.05, 0.05, 0.1) * (2-0.75f*Ogre::Math::Clamp<Ogre::Real>(-uLightDir.y, 0, 1)) * Ogre::Math::Pow(1-Direction.y, 3);
253  nightCol.x = Ogre::Math::Pow(nightCol.x, 2.2);
254  nightCol.y = Ogre::Math::Pow(nightCol.y, 2.2);
255  nightCol.z = Ogre::Math::Pow(nightCol.z, 2.2);
256 
257  oColor += nightmult*nightCol;
258  }
259 
260  // --- End fragment program simulation ---
261 
262  // Output color
263  return oColor;
264  }
265 }
SkyX::AtmosphereManager::Options::G
Ogre::Real G
Phase function.
Definition: AtmosphereManager.h:59
SkyX::AtmosphereManager::~AtmosphereManager
~AtmosphereManager()
Destructor.
Definition: AtmosphereManager.cpp:38
SkyX::AtmosphereManager::Options::Exposure
Ogre::Real Exposure
Exposure coeficient.
Definition: AtmosphereManager.h:62
SkyX::AtmosphereManager::getColorAt
const Ogre::Vector3 getColorAt(const Ogre::Vector3 &Direction) const
Get current atmosphere color at the given direction.
Definition: AtmosphereManager.cpp:145
SkyX::AtmosphereManager::Options::HeightPosition
Ogre::Real HeightPosition
Height position, in [0, 1] range, 0=InnerRadius, 1=OuterRadius.
Definition: AtmosphereManager.h:46
SkyX::AtmosphereManager::mSkyX
SkyX * mSkyX
SkyX parent pointer.
Definition: AtmosphereManager.h:169
SkyX::SkyX::getLightingMode
const LightingMode & getLightingMode() const
Get lighting mode.
Definition: SkyX.h:275
SkyX::SkyX::getController
Controller * getController() const
Get current controller.
Definition: SkyX.h:244
SkyX::SkyX::LM_LDR
@ LM_LDR
Low dynamic range.
Definition: SkyX.h:99
SkyX
Definition: AtmosphereManager.cpp:30
SkyX::AtmosphereManager::Options::InnerRadius
Ogre::Real InnerRadius
Inner atmosphere radius.
Definition: AtmosphereManager.h:42
SkyX::GPUManager::setGpuProgramParameter
void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const int &Value, const bool &UpdateGroundPasses=true)
Set gpu program int parameter.
Definition: GPUManager.cpp:99
GPUManager.h
Exp
quaternion Exp() const
SkyX::AtmosphereManager::_scale
const float _scale(const float &cos, const float &uScaleDepth) const
Shader scale funtion.
Definition: AtmosphereManager.cpp:139
SkyX.h
AtmosphereManager.h
SkyX::SkyX::getGPUManager
GPUManager * getGPUManager()
Get GPU manager.
Definition: SkyX.h:199
SkyX::SkyX::getCloudsManager
CloudsManager * getCloudsManager()
Get clouds manager.
Definition: SkyX.h:215
SkyX::AtmosphereManager::Options
Atmosphere options.
Definition: AtmosphereManager.h:39
SkyX::GPUManager::GPUP_VERTEX
@ GPUP_VERTEX
Definition: GPUManager.h:41
SkyX::AtmosphereManager::_update
void _update(const Options &NewOptions, const bool &ForceToUpdateAll=false)
Update atmoshpere.
Definition: AtmosphereManager.cpp:42
SkyX::AtmosphereManager::Options::SunIntensity
Ogre::Real SunIntensity
Sun intensity.
Definition: AtmosphereManager.h:53
SkyX::AtmosphereManager::AtmosphereManager
AtmosphereManager(SkyX *s)
Constructor.
Definition: AtmosphereManager.cpp:32
SkyX::CloudsManager::update
void update()
Update cloud layers.
Definition: CloudsManager.cpp:312
SkyX::GPUManager::GPUP_FRAGMENT
@ GPUP_FRAGMENT
Definition: GPUManager.h:43
SkyX::Controller::getSunDirection
virtual Ogre::Vector3 getSunDirection()=0
Get sun direction.
SkyX::AtmosphereManager::Options::NumberOfSamples
int NumberOfSamples
Number of samples.
Definition: AtmosphereManager.h:65
SkyX::AtmosphereManager::Options::OuterRadius
Ogre::Real OuterRadius
Outer atmosphere radius.
Definition: AtmosphereManager.h:44
SkyX::AtmosphereManager::Options::WaveLength
Ogre::Vector3 WaveLength
WaveLength for RGB channels.
Definition: AtmosphereManager.h:56
SkyX::AtmosphereManager::Options::RayleighMultiplier
Ogre::Real RayleighMultiplier
Rayleigh multiplier.
Definition: AtmosphereManager.h:49
x
float x
Definition: (ValueTypes) quaternion.h:5
SkyX::GPUManager
Definition: GPUManager.h:33
SkyX::AtmosphereManager::Options::MieMultiplier
Ogre::Real MieMultiplier
Mie multiplier.
Definition: AtmosphereManager.h:51
SkyX::AtmosphereManager::mOptions
Options mOptions
Our options.
Definition: AtmosphereManager.h:166