]> git.lizzy.rs Git - minetest.git/blob - src/sky.cpp
a9fb90122c3a6e078bb9463b7967b3442a418358
[minetest.git] / src / sky.cpp
1 #include "sky.h"
2 #include "IVideoDriver.h"
3 #include "ISceneManager.h"
4 #include "ICameraSceneNode.h"
5 #include "S3DVertex.h"
6 #include "tile.h" // getTexturePath
7 #include "noise.h" // easeCurve
8 #include "main.h" // g_profiler
9 #include "profiler.h"
10 #include "util/numeric.h" // MYMIN
11 #include <cmath>
12
13 //! constructor
14 Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, LocalPlayer* player):
15                 scene::ISceneNode(parent, mgr, id),
16                 m_first_update(true),
17                 m_brightness(0.5),
18                 m_cloud_brightness(0.5),
19                 m_bgcolor_bright_f(1,1,1,1),
20                 m_skycolor_bright_f(1,1,1,1),
21                 m_cloudcolor_bright_f(1,1,1,1),
22                 m_player(player)
23 {
24         setAutomaticCulling(scene::EAC_OFF);
25         Box.MaxEdge.set(0,0,0);
26         Box.MinEdge.set(0,0,0);
27
28         // create material
29
30         video::SMaterial mat;
31         mat.Lighting = false;
32         mat.ZBuffer = video::ECFN_NEVER;
33         mat.ZWriteEnable = false;
34         mat.AntiAliasing=0;
35         mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
36         mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
37         mat.BackfaceCulling = false;
38
39         m_materials[0] = mat;
40
41         m_materials[1] = mat;
42         //m_materials[1].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
43         m_materials[1].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
44
45         m_materials[2] = mat;
46         m_materials[2].setTexture(0, mgr->getVideoDriver()->getTexture(
47                         getTexturePath("sunrisebg.png").c_str()));
48         m_materials[2].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
49         //m_materials[2].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
50
51         for(u32 i=0; i<SKY_STAR_COUNT; i++){
52                 m_stars[i] = v3f(
53                         myrand_range(-10000,10000),
54                         myrand_range(-10000,10000),
55                         myrand_range(-10000,10000)
56                 );
57                 m_stars[i].normalize();
58         }
59 }
60
61 void Sky::OnRegisterSceneNode()
62 {
63         if (IsVisible)
64                 SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
65
66         scene::ISceneNode::OnRegisterSceneNode();
67 }
68
69 const core::aabbox3d<f32>& Sky::getBoundingBox() const
70 {
71         return Box;
72 }
73
74 //! renders the node.
75 void Sky::render()
76 {
77         video::IVideoDriver* driver = SceneManager->getVideoDriver();
78         scene::ICameraSceneNode* camera = SceneManager->getActiveCamera();
79
80         if (!camera || !driver)
81                 return;
82         
83         ScopeProfiler sp(g_profiler, "Sky::render()", SPT_AVG);
84
85         // draw perspective skybox
86
87         core::matrix4 translate(AbsoluteTransformation);
88         translate.setTranslation(camera->getAbsolutePosition());
89
90         // Draw the sky box between the near and far clip plane
91         const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f;
92         core::matrix4 scale;
93         scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance));
94
95         driver->setTransform(video::ETS_WORLD, translate * scale);
96
97         if(m_sunlight_seen)
98         {
99                 float sunsize = 0.07;
100                 video::SColorf suncolor_f(1, 1, 0, 1);
101                 suncolor_f.r = 1;
102                 suncolor_f.g = MYMAX(0.3, MYMIN(1.0, 0.7+m_time_brightness*(0.5)));
103                 suncolor_f.b = MYMAX(0.0, m_brightness*0.95);
104                 video::SColorf suncolor2_f(1, 1, 1, 1);
105                 suncolor_f.r = 1;
106                 suncolor_f.g = MYMAX(0.3, MYMIN(1.0, 0.85+m_time_brightness*(0.5)));
107                 suncolor_f.b = MYMAX(0.0, m_brightness);
108
109                 float moonsize = 0.04;
110                 video::SColorf mooncolor_f(0.50, 0.57, 0.65, 1);
111                 video::SColorf mooncolor2_f(0.85, 0.875, 0.9, 1);
112                 
113                 float nightlength = 0.415;
114                 float wn = nightlength / 2;
115                 float wicked_time_of_day = 0;
116                 if(m_time_of_day > wn && m_time_of_day < 1.0 - wn)
117                         wicked_time_of_day = (m_time_of_day - wn)/(1.0-wn*2)*0.5 + 0.25;
118                 else if(m_time_of_day < 0.5)
119                         wicked_time_of_day = m_time_of_day / wn * 0.25;
120                 else
121                         wicked_time_of_day = 1.0 - ((1.0-m_time_of_day) / wn * 0.25);
122                 /*std::cerr<<"time_of_day="<<m_time_of_day<<" -> "
123                                 <<"wicked_time_of_day="<<wicked_time_of_day<<std::endl;*/
124
125                 video::SColor suncolor = suncolor_f.toSColor();
126                 video::SColor suncolor2 = suncolor2_f.toSColor();
127                 video::SColor mooncolor = mooncolor_f.toSColor();
128                 video::SColor mooncolor2 = mooncolor2_f.toSColor();
129
130                 const f32 t = 1.0f;
131                 const f32 o = 0.0f;
132                 static const u16 indices[4] = {0,1,2,3};
133                 video::S3DVertex vertices[4];
134                 
135                 driver->setMaterial(m_materials[1]);
136                 
137                 //video::SColor cloudyfogcolor(255,255,255,255);
138                 video::SColor cloudyfogcolor = m_bgcolor;
139                 //video::SColor cloudyfogcolor = m_bgcolor.getInterpolated(m_skycolor, 0.5);
140                 
141                 // Draw far cloudy fog thing
142                 for(u32 j=0; j<4; j++)
143                 {
144                         video::SColor c = cloudyfogcolor.getInterpolated(m_skycolor, 0.45);
145                         vertices[0] = video::S3DVertex(-1, 0.08,-1, 0,0,1, c, t, t);
146                         vertices[1] = video::S3DVertex( 1, 0.08,-1, 0,0,1, c, o, t);
147                         vertices[2] = video::S3DVertex( 1, 0.12,-1, 0,0,1, c, o, o);
148                         vertices[3] = video::S3DVertex(-1, 0.12,-1, 0,0,1, c, t, o);
149                         for(u32 i=0; i<4; i++){
150                                 if(j==0)
151                                         // Don't switch
152                                         {}
153                                 else if(j==1)
154                                         // Switch from -Z (south) to +X (east)
155                                         vertices[i].Pos.rotateXZBy(90);
156                                 else if(j==2)
157                                         // Switch from -Z (south) to -X (west)
158                                         vertices[i].Pos.rotateXZBy(-90);
159                                 else
160                                         // Switch from -Z (south) to -Z (north)
161                                         vertices[i].Pos.rotateXZBy(-180);
162                         }
163                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
164                 }
165                 for(u32 j=0; j<4; j++)
166                 {
167                         video::SColor c = cloudyfogcolor;
168                         vertices[0] = video::S3DVertex(-1,-1.0,-1, 0,0,1, c, t, t);
169                         vertices[1] = video::S3DVertex( 1,-1.0,-1, 0,0,1, c, o, t);
170                         vertices[2] = video::S3DVertex( 1, 0.08,-1, 0,0,1, c, o, o);
171                         vertices[3] = video::S3DVertex(-1, 0.08,-1, 0,0,1, c, t, o);
172                         for(u32 i=0; i<4; i++){
173                                 if(j==0)
174                                         // Don't switch
175                                         {}
176                                 else if(j==1)
177                                         // Switch from -Z (south) to +X (east)
178                                         vertices[i].Pos.rotateXZBy(90);
179                                 else if(j==2)
180                                         // Switch from -Z (south) to -X (west)
181                                         vertices[i].Pos.rotateXZBy(-90);
182                                 else
183                                         // Switch from -Z (south) to -Z (north)
184                                         vertices[i].Pos.rotateXZBy(-180);
185                         }
186                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
187                 }
188
189                 driver->setMaterial(m_materials[2]);
190
191                 {
192                         float mid1 = 0.25;
193                         float mid = (wicked_time_of_day < 0.5 ? mid1 : (1.0 - mid1));
194                         float a_ = 1.0 - fabs(wicked_time_of_day - mid) * 35.0;
195                         float a = easeCurve(MYMAX(0, MYMIN(1, a_)));
196                         //std::cerr<<"a_="<<a_<<" a="<<a<<std::endl;
197                         video::SColor c(255,255,255,255);
198                         float y = -(1.0 - a) * 0.2;
199                         vertices[0] = video::S3DVertex(-1,-0.05+y,-1, 0,0,1, c, t, t);
200                         vertices[1] = video::S3DVertex( 1,-0.05+y,-1, 0,0,1, c, o, t);
201                         vertices[2] = video::S3DVertex( 1, 0.2+y,-1, 0,0,1, c, o, o);
202                         vertices[3] = video::S3DVertex(-1, 0.2+y,-1, 0,0,1, c, t, o);
203                         for(u32 i=0; i<4; i++){
204                                 if(wicked_time_of_day < 0.5)
205                                         // Switch from -Z (south) to +X (east)
206                                         vertices[i].Pos.rotateXZBy(90);
207                                 else
208                                         // Switch from -Z (south) to -X (west)
209                                         vertices[i].Pos.rotateXZBy(-90);
210                         }
211                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
212                 }
213
214                 driver->setMaterial(m_materials[1]);
215                 
216                 // Draw sun
217                 if(wicked_time_of_day > 0.15 && wicked_time_of_day < 0.85)
218                 {
219                         float d = sunsize * 1.7;
220                         video::SColor c = suncolor;
221                         c.setAlpha(0.05*255);
222                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
223                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
224                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
225                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
226                         for(u32 i=0; i<4; i++){
227                                 // Switch from -Z (south) to +X (east)
228                                 vertices[i].Pos.rotateXZBy(90);
229                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
230                         }
231                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
232
233                         d = sunsize * 1.2;
234                         c = suncolor;
235                         c.setAlpha(0.15*255);
236                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
237                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
238                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
239                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
240                         for(u32 i=0; i<4; i++){
241                                 // Switch from -Z (south) to +X (east)
242                                 vertices[i].Pos.rotateXZBy(90);
243                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
244                         }
245                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
246
247                         d = sunsize;
248                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, suncolor, t, t);
249                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, suncolor, o, t);
250                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, suncolor, o, o);
251                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, suncolor, t, o);
252                         for(u32 i=0; i<4; i++){
253                                 // Switch from -Z (south) to +X (east)
254                                 vertices[i].Pos.rotateXZBy(90);
255                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
256                         }
257                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
258
259                         d = sunsize * 0.7;
260                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, suncolor2, t, t);
261                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, suncolor2, o, t);
262                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, suncolor2, o, o);
263                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, suncolor2, t, o);
264                         for(u32 i=0; i<4; i++){
265                                 // Switch from -Z (south) to +X (east)
266                                 vertices[i].Pos.rotateXZBy(90);
267                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
268                         }
269                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
270                 }
271                 // Draw moon
272                 if(wicked_time_of_day < 0.3 || wicked_time_of_day > 0.7)
273                 {
274                         float d = moonsize * 1.9;
275                         video::SColor c = mooncolor;
276                         c.setAlpha(0.05*255);
277                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
278                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
279                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
280                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
281                         for(u32 i=0; i<4; i++){
282                                 // Switch from -Z (south) to -X (west)
283                                 vertices[i].Pos.rotateXZBy(-90);
284                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
285                         }
286                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
287                         
288                         d = moonsize * 1.3;
289                         c = mooncolor;
290                         c.setAlpha(0.15*255);
291                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, c, t, t);
292                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, c, o, t);
293                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, c, o, o);
294                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, c, t, o);
295                         for(u32 i=0; i<4; i++){
296                                 // Switch from -Z (south) to -X (west)
297                                 vertices[i].Pos.rotateXZBy(-90);
298                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
299                         }
300                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
301                         
302                         d = moonsize;
303                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, mooncolor, t, t);
304                         vertices[1] = video::S3DVertex( d,-d,-1, 0,0,1, mooncolor, o, t);
305                         vertices[2] = video::S3DVertex( d, d,-1, 0,0,1, mooncolor, o, o);
306                         vertices[3] = video::S3DVertex(-d, d,-1, 0,0,1, mooncolor, t, o);
307                         for(u32 i=0; i<4; i++){
308                                 // Switch from -Z (south) to -X (west)
309                                 vertices[i].Pos.rotateXZBy(-90);
310                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
311                         }
312                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
313                         
314                         float d2 = moonsize * 0.6;
315                         vertices[0] = video::S3DVertex(-d,-d,-1, 0,0,1, mooncolor2, t, t);
316                         vertices[1] = video::S3DVertex( d2,-d,-1, 0,0,1, mooncolor2, o, t);
317                         vertices[2] = video::S3DVertex( d2, d2,-1, 0,0,1, mooncolor2, o, o);
318                         vertices[3] = video::S3DVertex(-d, d2,-1, 0,0,1, mooncolor2, t, o);
319                         for(u32 i=0; i<4; i++){
320                                 // Switch from -Z (south) to -X (west)
321                                 vertices[i].Pos.rotateXZBy(-90);
322                                 vertices[i].Pos.rotateXYBy(wicked_time_of_day * 360 - 90);
323                         }
324                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
325                 }
326                 // Stars
327                 do{
328                         float starbrightness = MYMAX(0, MYMIN(1,
329                                         (0.285 - fabs(wicked_time_of_day < 0.5 ?
330                                         wicked_time_of_day : (1.0 - wicked_time_of_day))) * 10));
331                         float f = starbrightness;
332                         float d = 0.007;
333                         video::SColor starcolor(255, f*90,f*90,f*90);
334                         if(starcolor.getBlue() < m_skycolor.getBlue())
335                                 break;
336                         u16 indices[SKY_STAR_COUNT*4];
337                         video::S3DVertex vertices[SKY_STAR_COUNT*4];
338                         for(u32 i=0; i<SKY_STAR_COUNT; i++){
339                                 indices[i*4+0] = i*4+0;
340                                 indices[i*4+1] = i*4+1;
341                                 indices[i*4+2] = i*4+2;
342                                 indices[i*4+3] = i*4+3;
343                                 v3f p = m_stars[i];
344                                 core::CMatrix4<f32> a;
345                                 a.buildRotateFromTo(v3f(0,1,0), v3f(d,1+d/2,0));
346                                 v3f p1 = p;
347                                 a.rotateVect(p1);
348                                 a.buildRotateFromTo(v3f(0,1,0), v3f(d,1,d));
349                                 v3f p2 = p;
350                                 a.rotateVect(p2);
351                                 a.buildRotateFromTo(v3f(0,1,0), v3f(0,1-d/2,d));
352                                 v3f p3 = p;
353                                 a.rotateVect(p3);
354                                 p.rotateXYBy(wicked_time_of_day * 360 - 90);
355                                 p1.rotateXYBy(wicked_time_of_day * 360 - 90);
356                                 p2.rotateXYBy(wicked_time_of_day * 360 - 90);
357                                 p3.rotateXYBy(wicked_time_of_day * 360 - 90);
358                                 vertices[i*4+0].Pos = p;
359                                 vertices[i*4+0].Color = starcolor;
360                                 vertices[i*4+1].Pos = p1;
361                                 vertices[i*4+1].Color = starcolor;
362                                 vertices[i*4+2].Pos = p2;
363                                 vertices[i*4+2].Color = starcolor;
364                                 vertices[i*4+3].Pos = p3;
365                                 vertices[i*4+3].Color = starcolor;
366                         }
367                         driver->drawVertexPrimitiveList(vertices, SKY_STAR_COUNT*4,
368                                         indices, SKY_STAR_COUNT, video::EVT_STANDARD,
369                                         scene::EPT_QUADS, video::EIT_16BIT);
370                 }while(0);
371                 
372                 for(u32 j=0; j<2; j++)
373                 {
374                         //video::SColor c = m_skycolor;
375                         video::SColor c = cloudyfogcolor;
376                         vertices[0] = video::S3DVertex(-1,-1.0,-1, 0,0,1, c, t, t);
377                         vertices[1] = video::S3DVertex( 1,-1.0,-1, 0,0,1, c, o, t);
378                         vertices[2] = video::S3DVertex( 1,-0.02,-1, 0,0,1, c, o, o);
379                         vertices[3] = video::S3DVertex(-1,-0.02,-1, 0,0,1, c, t, o);
380                         for(u32 i=0; i<4; i++){
381                                 //if(wicked_time_of_day < 0.5)
382                                 if(j==0)
383                                         // Switch from -Z (south) to +X (east)
384                                         vertices[i].Pos.rotateXZBy(90);
385                                 else
386                                         // Switch from -Z (south) to -X (west)
387                                         vertices[i].Pos.rotateXZBy(-90);
388                         }
389                         driver->drawIndexedTriangleFan(&vertices[0], 4, indices, 2);
390                 }
391         }
392 }
393
394 void Sky::update(float time_of_day, float time_brightness,
395                 float direct_brightness, bool sunlight_seen)
396 {
397         // Stabilize initial brightness and color values by flooding updates
398         if(m_first_update){
399                 /*dstream<<"First update with time_of_day="<<time_of_day
400                                 <<" time_brightness="<<time_brightness
401                                 <<" direct_brightness="<<direct_brightness
402                                 <<" sunlight_seen="<<sunlight_seen<<std::endl;*/
403                 m_first_update = false;
404                 for(u32 i=0; i<100; i++){
405                         update(time_of_day, time_brightness, direct_brightness,
406                                         sunlight_seen);
407                 }
408                 return;
409         }
410
411         m_time_of_day = time_of_day;
412         m_time_brightness = time_brightness;
413         m_sunlight_seen = sunlight_seen;
414         
415         bool is_dawn = (time_brightness >= 0.20 && time_brightness < 0.35);
416
417         //video::SColorf bgcolor_bright_normal_f(170./255,200./255,230./255, 1.0);
418         video::SColorf bgcolor_bright_normal_f(155./255,193./255,240./255, 1.0);
419         video::SColorf bgcolor_bright_indoor_f(100./255,100./255,100./255, 1.0);
420         //video::SColorf bgcolor_bright_dawn_f(0.666,200./255*0.7,230./255*0.5,1.0);
421         //video::SColorf bgcolor_bright_dawn_f(0.666,0.549,0.220,1.0);
422         //video::SColorf bgcolor_bright_dawn_f(0.666*1.2,0.549*1.0,0.220*1.0, 1.0);
423         //video::SColorf bgcolor_bright_dawn_f(0.666*1.2,0.549*1.0,0.220*1.2,1.0);
424         video::SColorf bgcolor_bright_dawn_f
425                         (155./255*1.2,193./255,240./255, 1.0);
426
427         video::SColorf skycolor_bright_normal_f =
428                         video::SColor(255, 140, 186, 250);
429         video::SColorf skycolor_bright_dawn_f =
430                         video::SColor(255, 180, 186, 250);
431         
432         video::SColorf cloudcolor_bright_normal_f =
433                         video::SColor(255, 240,240,255);
434         //video::SColorf cloudcolor_bright_dawn_f(1.0, 0.591, 0.4);
435         //video::SColorf cloudcolor_bright_dawn_f(1.0, 0.65, 0.44);
436         //video::SColorf cloudcolor_bright_dawn_f(1.0, 0.7, 0.5);
437         video::SColorf cloudcolor_bright_dawn_f(1.0, 0.875, 0.75);
438
439         float cloud_color_change_fraction = 0.95;
440         if(sunlight_seen){
441                 if(fabs(time_brightness - m_brightness) < 0.2){
442                         m_brightness = m_brightness * 0.95 + time_brightness * 0.05;
443                 } else {
444                         m_brightness = m_brightness * 0.80 + time_brightness * 0.20;
445                         cloud_color_change_fraction = 0.0;
446                 }
447         }
448         else{
449                 if(direct_brightness < m_brightness)
450                         m_brightness = m_brightness * 0.95 + direct_brightness * 0.05;
451                 else
452                         m_brightness = m_brightness * 0.98 + direct_brightness * 0.02;
453         }
454         
455         m_clouds_visible = true;
456         float color_change_fraction = 0.98;
457         if(sunlight_seen){
458                 if(is_dawn){
459                         m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated(
460                                         bgcolor_bright_dawn_f, color_change_fraction);
461                         m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated(
462                                         skycolor_bright_dawn_f, color_change_fraction);
463                         m_cloudcolor_bright_f = m_cloudcolor_bright_f.getInterpolated(
464                                         cloudcolor_bright_dawn_f, color_change_fraction);
465                 } else {
466                         m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated(
467                                         bgcolor_bright_normal_f, color_change_fraction);
468                         m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated(
469                                         skycolor_bright_normal_f, color_change_fraction);
470                         m_cloudcolor_bright_f = m_cloudcolor_bright_f.getInterpolated(
471                                         cloudcolor_bright_normal_f, color_change_fraction);
472                 }
473         } else {
474                 m_bgcolor_bright_f = m_bgcolor_bright_f.getInterpolated(
475                                 bgcolor_bright_indoor_f, color_change_fraction);
476                 m_skycolor_bright_f = m_skycolor_bright_f.getInterpolated(
477                                 bgcolor_bright_indoor_f, color_change_fraction);
478                 m_cloudcolor_bright_f = m_cloudcolor_bright_f.getInterpolated(
479                                 cloudcolor_bright_normal_f, color_change_fraction);
480                 m_clouds_visible = false;
481         }
482
483         // Horizon coloring based on sun and moon direction during sunset and sunrise
484         video::SColor pointcolor = video::SColor(255, 255, 255, m_bgcolor.getAlpha());
485         if (m_horizon_blend() != 0)
486         {
487                 // calculate hemisphere value from yaw
488                 f32 pointcolor_blend = wrapDegrees_0_360(m_player->getYaw() + 90);
489                 if (pointcolor_blend > 180)
490                         pointcolor_blend = 360 - pointcolor_blend;
491                 pointcolor_blend /= 180;
492                 // bound view angle to determine where transition starts and ends
493                 pointcolor_blend = rangelim(1 - pointcolor_blend * 1.375, 0, 1 / 1.375) * 1.375;
494                 // combine the colors when looking up or down, otherwise turning looks weird
495                 pointcolor_blend += (0.5 - pointcolor_blend) * (1 - MYMIN((90 - std::abs(m_player->getPitch())) / 90 * 1.5, 1));
496                 // invert direction to match where the sun and moon are rising
497                 if (m_time_of_day > 0.5)
498                         pointcolor_blend = 1 - pointcolor_blend;
499
500                 // horizon colors of sun and moon
501                 f32 pointcolor_light = rangelim(m_time_brightness * 3, 0.2, 1);
502                 video::SColorf pointcolor_sun_f(1, 1, 1, 1);
503                 pointcolor_sun_f.r = pointcolor_light * 1;
504                 pointcolor_sun_f.b = pointcolor_light * (0.25 + (rangelim(m_time_brightness, 0.25, 0.75) - 0.25) * 2 * 0.75);
505                 pointcolor_sun_f.g = pointcolor_light * (pointcolor_sun_f.b * 0.375 + (rangelim(m_time_brightness, 0.05, 0.15) - 0.05) * 10 * 0.625);
506                 video::SColorf pointcolor_moon_f(0.5 * pointcolor_light, 0.6 * pointcolor_light, 0.8 * pointcolor_light, 1);
507                 video::SColor pointcolor_sun = pointcolor_sun_f.toSColor();
508                 video::SColor pointcolor_moon = pointcolor_moon_f.toSColor();
509                 // calculate the blend color
510                 pointcolor = m_mix_scolor(pointcolor_moon, pointcolor_sun, pointcolor_blend);
511         }
512
513         video::SColor bgcolor_bright = m_bgcolor_bright_f.toSColor();
514         m_bgcolor = video::SColor(
515                 255,
516                 bgcolor_bright.getRed() * m_brightness,
517                 bgcolor_bright.getGreen() * m_brightness,
518                 bgcolor_bright.getBlue() * m_brightness);
519         m_bgcolor = m_mix_scolor(m_bgcolor, pointcolor, m_horizon_blend() * 0.5);
520
521         video::SColor skycolor_bright = m_skycolor_bright_f.toSColor();
522         m_skycolor = video::SColor(
523                 255,
524                 skycolor_bright.getRed() * m_brightness,
525                 skycolor_bright.getGreen() * m_brightness,
526                 skycolor_bright.getBlue() * m_brightness);
527         m_skycolor = m_mix_scolor(m_skycolor, pointcolor, m_horizon_blend() * 0.25);
528
529         float cloud_direct_brightness = 0;
530         if(sunlight_seen){
531                 cloud_direct_brightness = MYMIN(m_horizon_blend() * 0.15 + m_time_brightness, 1);
532         } else {
533                 cloud_direct_brightness = direct_brightness;
534         }
535         m_cloud_brightness = m_cloud_brightness * cloud_color_change_fraction +
536                         cloud_direct_brightness * (1.0 - cloud_color_change_fraction);
537         m_cloudcolor_f = video::SColorf(
538                         m_cloudcolor_bright_f.r * m_cloud_brightness,
539                         m_cloudcolor_bright_f.g * m_cloud_brightness,
540                         m_cloudcolor_bright_f.b * m_cloud_brightness,
541                         1.0);
542         m_cloudcolor_f = m_mix_scolorf(m_cloudcolor_f, video::SColorf(pointcolor), m_horizon_blend() * 0.75);
543
544 }
545
546