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