Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
AtmosphereManager.cpp
Go to the documentation of this file.
1/*
2--------------------------------------------------------------------------------
3This source file is part of SkyX.
4Visit http://www.paradise-studios.net/products/skyx/
5
6Copyright (C) 2009-2012 Xavier Vergu�n Gonz�lez <xavyiy@gmail.com>
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt.
21--------------------------------------------------------------------------------
22*/
23
24#include "AtmosphereManager.h"
25
26#include "SkyX.h"
27
28#include "GPUManager.h"
29
30namespace SkyX
31{
33 : mSkyX(s)
34 , mOptions(Options())
35 {
36 }
37
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
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
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(),
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}
AtmosphereManager(SkyX *s)
Constructor.
const float _scale(const float &cos, const float &uScaleDepth) const
Shader scale funtion.
void _update(const Options &NewOptions, const bool &ForceToUpdateAll=false)
Update atmoshpere.
const Ogre::Vector3 getColorAt(const Ogre::Vector3 &Direction) const
Get current atmosphere color at the given direction.
SkyX * mSkyX
SkyX parent pointer.
Options mOptions
Our options.
void update()
Update cloud layers.
virtual Ogre::Vector3 getSunDirection()=0
Get sun direction.
void setGpuProgramParameter(const GpuProgram &GpuP, const Ogre::String &Name, const int &Value, const bool &UpdateGroundPasses=true)
Set gpu program int parameter.
CloudsManager * getCloudsManager()
Get clouds manager.
Definition SkyX.h:215
@ LM_LDR
Low dynamic range.
Definition SkyX.h:99
const LightingMode & getLightingMode() const
Get lighting mode.
Definition SkyX.h:275
GPUManager * getGPUManager()
Get GPU manager.
Definition SkyX.h:199
Controller * getController() const
Get current controller.
Definition SkyX.h:244
Ogre::Real Exposure
Exposure coeficient.
Ogre::Real G
Phase function.
Ogre::Real HeightPosition
Height position, in [0, 1] range, 0=InnerRadius, 1=OuterRadius.
Ogre::Real SunIntensity
Sun intensity.
Ogre::Real OuterRadius
Outer atmosphere radius.
Ogre::Vector3 WaveLength
WaveLength for RGB channels.
Ogre::Real MieMultiplier
Mie multiplier.
Ogre::Real InnerRadius
Inner atmosphere radius.
Ogre::Real RayleighMultiplier
Rayleigh multiplier.
int NumberOfSamples
Number of samples.