aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvosky.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llvosky.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llvosky.cpp2448
1 files changed, 2448 insertions, 0 deletions
diff --git a/linden/indra/newview/llvosky.cpp b/linden/indra/newview/llvosky.cpp
new file mode 100644
index 0000000..927b784
--- /dev/null
+++ b/linden/indra/newview/llvosky.cpp
@@ -0,0 +1,2448 @@
1/**
2 * @file llvosky.cpp
3 * @brief LLVOSky class implementation
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llvosky.h"
31
32#include "imageids.h"
33#include "llviewercontrol.h"
34#include "llframetimer.h"
35#include "timing.h"
36
37#include "llagent.h"
38#include "lldrawable.h"
39#include "llface.h"
40#include "llcubemap.h"
41#include "lldrawpoolsky.h"
42#include "lldrawpoolwater.h"
43#include "llglheaders.h"
44#include "llsky.h"
45#include "llviewercamera.h"
46#include "llviewerimagelist.h"
47#include "llviewerobjectlist.h"
48#include "llviewerregion.h"
49#include "llworld.h"
50#include "pipeline.h"
51#include "viewer.h" // for gSunTextureID
52
53const S32 NUM_TILES_X = 8;
54const S32 NUM_TILES_Y = 4;
55const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
56
57// Heavenly body constants
58const F32 SUN_DISK_RADIUS = 0.5f;
59const F32 MOON_DISK_RADIUS = SUN_DISK_RADIUS * 0.9f;
60const F32 SUN_INTENSITY = 1e5;
61const F32 SUN_DISK_INTENSITY = 24.f;
62
63
64// Texture coordinates:
65const LLVector2 TEX00 = LLVector2(0.f, 0.f);
66const LLVector2 TEX01 = LLVector2(0.f, 1.f);
67const LLVector2 TEX10 = LLVector2(1.f, 0.f);
68const LLVector2 TEX11 = LLVector2(1.f, 1.f);
69
70//static
71LLColor3 LLHaze::sAirScaSeaLevel;
72
73class LLFastLn
74{
75public:
76 LLFastLn()
77 {
78 mTable[0] = 0;
79 for( S32 i = 1; i < 257; i++ )
80 {
81 mTable[i] = log((F32)i);
82 }
83 }
84
85 F32 ln( F32 x )
86 {
87 const F32 OO_255 = 0.003921568627450980392156862745098f;
88 const F32 LN_255 = 5.5412635451584261462455391880218f;
89
90 if( x < OO_255 )
91 {
92 return log(x);
93 }
94 else
95 if( x < 1 )
96 {
97 x *= 255.f;
98 S32 index = llfloor(x);
99 F32 t = x - index;
100 F32 low = mTable[index];
101 F32 high = mTable[index + 1];
102 return low + t * (high - low) - LN_255;
103 }
104 else
105 if( x <= 255 )
106 {
107 S32 index = llfloor(x);
108 F32 t = x - index;
109 F32 low = mTable[index];
110 F32 high = mTable[index + 1];
111 return low + t * (high - low);
112 }
113 else
114 {
115 return log( x );
116 }
117 }
118
119 F32 pow( F32 x, F32 y )
120 {
121 return (F32)LL_FAST_EXP(y * ln(x));
122 }
123
124
125private:
126 F32 mTable[257]; // index 0 is unused
127};
128
129LLFastLn gFastLn;
130
131
132// Functions used a lot.
133
134inline F32 LLHaze::calcPhase(const F32 cos_theta) const
135{
136 const F32 g2 = mG * mG;
137 const F32 den = 1 + g2 - 2 * mG * cos_theta;
138 return (1 - g2) * gFastLn.pow(den, -1.5);
139}
140
141inline void color_pow(LLColor3 &col, const F32 e)
142{
143 col.mV[0] = gFastLn.pow(col.mV[0], e);
144 col.mV[1] = gFastLn.pow(col.mV[1], e);
145 col.mV[2] = gFastLn.pow(col.mV[2], e);
146}
147
148inline LLColor3 color_norm(const LLColor3 &col)
149{
150 const F32 m = color_max(col);
151 if (m > 1.f)
152 {
153 return 1.f/m * col;
154 }
155 else return col;
156}
157
158inline LLColor3 color_norm_fog(const LLColor3 &col)
159{
160 const F32 m = color_max(col);
161 if (m > 0.75f)
162 {
163 return 0.75f/m * col;
164 }
165 else return col;
166}
167
168
169inline LLColor4 color_norm_abs(const LLColor4 &col)
170{
171 const F32 m = color_max(col);
172 if (m > 1e-6)
173 {
174 return 1.f/m * col;
175 }
176 else
177 {
178 return col;
179 }
180}
181
182
183inline F32 color_intens ( const LLColor4 &col )
184{
185 return col.mV[0] + col.mV[1] + col.mV[2];
186}
187
188
189inline F32 color_avg ( const LLColor3 &col )
190{
191 return color_intens(col) / 3;
192}
193
194inline void color_gamma_correct(LLColor3 &col)
195{
196 const F32 gamma_inv = 1.f/1.2f;
197 if (col.mV[0] != 0.f)
198 {
199 col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv);
200 }
201 if (col.mV[1] != 0.f)
202 {
203 col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv);
204 }
205 if (col.mV[2] != 0.f)
206 {
207 col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv);
208 }
209}
210
211inline F32 min_intens_factor( LLColor3& col, F32 min_intens, BOOL postmultiply = FALSE);
212inline F32 min_intens_factor( LLColor3& col, F32 min_intens, BOOL postmultiply)
213{
214 const F32 intens = color_intens(col);
215 F32 factor = 1;
216 if (0 == intens)
217 {
218 return 0;
219 }
220
221 if (intens < min_intens)
222 {
223 factor = min_intens / intens;
224 if (postmultiply)
225 col *= factor;
226 }
227 return factor;
228}
229
230inline LLVector3 move_vec(const LLVector3& v, const F32 cos_max_angle)
231{
232 LLVector3 v_norm = v;
233 v_norm.normVec();
234
235 LLVector2 v_norm_proj(v_norm.mV[0], v_norm.mV[1]);
236 const F32 projection2 = v_norm_proj.magVecSquared();
237 const F32 scale = sqrt((1 - cos_max_angle * cos_max_angle) / projection2);
238 return LLVector3(scale * v_norm_proj.mV[0], scale * v_norm_proj.mV[1], cos_max_angle);
239}
240
241
242/***************************************
243 Transparency Map
244***************************************/
245
246void LLTranspMap::init(const F32 elev, const F32 step, const F32 h, const LLHaze* const haze)
247{
248 mHaze = haze;
249 mAtmHeight = h;
250 mElevation = elev;
251 mStep = step;
252 mStepInv = 1.f / step;
253 F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mElevation);
254 mCosMaxAngle = -sqrt(1 - sin_angle * sin_angle);
255 mMapSize = S32(ceil((1 - mCosMaxAngle) * mStepInv + 1) + 0.5);
256 delete mT;
257 mT = new LLColor3[mMapSize];
258
259 for (S32 i = 0; i < mMapSize; ++i)
260 {
261 const F32 cos_a = 1 - i*mStep;
262 const LLVector3 dir(0, sqrt(1-cos_a*cos_a), cos_a);
263 mT[i] = calcAirTranspDir(mElevation, dir);
264 }
265}
266
267
268
269LLColor3 LLTranspMap::calcAirTranspDir(const F32 elevation, const LLVector3 &dir) const
270{
271 LLColor3 opt_depth(0, 0, 0);
272 const LLVector3 point(0, 0, EARTH_RADIUS + elevation);
273 F32 dist = -dir * point;
274 LLVector3 cur_point;
275 S32 s;
276
277 if (dist > 0)
278 {
279 cur_point = point + dist * dir;
280// const F32 K = log(dist * INV_FIRST_STEP + 1) * INV_NO_STEPS;
281// const F32 e_pow_k = LL_FAST_EXP(K);
282 const F32 e_pow_k = gFastLn.pow( dist * INV_FIRST_STEP + 1, INV_NO_STEPS );
283 F32 step = FIRST_STEP * (1 - 1 / e_pow_k);
284
285 for (s = 0; s < NO_STEPS; ++s)
286 {
287 const F32 h = cur_point.magVec() - EARTH_RADIUS;
288 step *= e_pow_k;
289 opt_depth += calcSigExt(h) * step;
290 cur_point -= dir * step;
291 }
292 opt_depth *= 2;
293 cur_point = point + 2 * dist * dir;
294 }
295 else
296 {
297 cur_point = point;
298 }
299
300 dist = hitsAtmEdge(cur_point, dir);
301// const F32 K = log(dist * INV_FIRST_STEP + 1) * INV_NO_STEPS;
302// const F32 e_pow_k = LL_FAST_EXP(K);
303 const F32 e_pow_k = gFastLn.pow( dist * INV_FIRST_STEP + 1, INV_NO_STEPS );
304 F32 step = FIRST_STEP * (1 - 1 / e_pow_k);
305
306 for (s = 0; s < NO_STEPS; ++s)
307 {
308 const F32 h = cur_point.magVec() - EARTH_RADIUS;
309 step *= e_pow_k;
310 opt_depth += calcSigExt(h) * step;
311 cur_point += dir * step;
312 }
313
314 opt_depth *= -4.0f*F_PI;
315 opt_depth.exp();
316 return opt_depth;
317}
318
319
320
321F32 LLTranspMap::hitsAtmEdge(const LLVector3& X, const LLVector3& dir) const
322{
323 const F32 tca = -dir * X;
324 const F32 R = EARTH_RADIUS + mAtmHeight;
325 const F32 thc2 = R * R - X.magVecSquared() + tca * tca;
326 return tca + sqrt ( thc2 );
327}
328
329
330
331
332
333void LLTranspMapSet::init(const S32 size, const F32 first_step, const F32 media_height, const LLHaze* const haze)
334{
335 const F32 angle_step = 0.005f;
336 mSize = size;
337 mMediaHeight = media_height;
338
339 delete[] mTransp;
340 mTransp = new LLTranspMap[mSize];
341
342 delete[] mHeights;
343 mHeights = new F32[mSize];
344
345 F32 h = 0;
346 mHeights[0] = h;
347 mTransp[0].init(h, angle_step, mMediaHeight, haze);
348 const F32 K = log(mMediaHeight / first_step + 1) / (mSize - 1);
349 const F32 e_pow_k = exp(K);
350 F32 step = first_step * (e_pow_k - 1);
351
352 for (S32 s = 1; s < mSize; ++s)
353 {
354 h += step;
355 mHeights[s] = h;
356 mTransp[s].init(h, angle_step, mMediaHeight, haze);
357 step *= e_pow_k;
358 }
359}
360
361LLTranspMapSet::~LLTranspMapSet()
362{
363 delete[] mTransp;
364 mTransp = NULL;
365 delete[] mHeights;
366 mHeights = NULL;
367}
368
369
370
371/***************************************
372 SkyTex
373***************************************/
374
375S32 LLSkyTex::sComponents = 4;
376S32 LLSkyTex::sResolution = 64;
377F32 LLSkyTex::sInterpVal = 0.f;
378S32 LLSkyTex::sCurrent = 0;
379
380
381LLSkyTex::LLSkyTex()
382{
383}
384
385void LLSkyTex::init()
386{
387 mSkyData = new LLColor3[sResolution * sResolution];
388 mSkyDirs = new LLVector3[sResolution * sResolution];
389
390 for (S32 i = 0; i < 2; ++i)
391 {
392 mImageGL[i] = new LLImageGL(FALSE);
393 mImageGL[i]->setClamp(TRUE, TRUE);
394 mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents);
395
396 initEmpty(i);
397 }
398}
399
400void LLSkyTex::cleanupGL()
401{
402 mImageGL[0] = NULL;
403 mImageGL[1] = NULL;
404}
405
406void LLSkyTex::restoreGL()
407{
408 for (S32 i = 0; i < 2; i++)
409 {
410 mImageGL[i] = new LLImageGL(FALSE);
411 mImageGL[i]->setClamp(TRUE, TRUE);
412 }
413}
414
415LLSkyTex::~LLSkyTex()
416{
417 delete[] mSkyData;
418 mSkyData = NULL;
419
420 delete[] mSkyDirs;
421 mSkyDirs = NULL;
422}
423
424
425void LLSkyTex::initEmpty(const S32 tex)
426{
427 U8* data = mImageRaw[tex]->getData();
428 for (S32 i = 0; i < sResolution; ++i)
429 {
430 for (S32 j = 0; j < sResolution; ++j)
431 {
432 const S32 basic_offset = (i * sResolution + j);
433 S32 offset = basic_offset * sComponents;
434 data[offset] = 0;
435 data[offset+1] = 0;
436 data[offset+2] = 0;
437 data[offset+3] = 255;
438
439 mSkyData[basic_offset].setToBlack();
440 }
441 }
442
443 createTexture(tex);
444}
445
446
447void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt)
448{
449 U8* data = mImageRaw[sCurrent]->getData();
450 for (S32 i = 0; i < sResolution; ++i)
451 {
452 for (S32 j = 0; j < sResolution; ++j)
453 {
454 const S32 basic_offset = (i * sResolution + j);
455 S32 offset = basic_offset * sComponents;
456 LLColor3 col(mSkyData[basic_offset]);
457 if (getDir(i, j).mV[VZ] >= -0.02f) {
458 col += 0.1f * multiscatt;
459 col *= brightness_scale;
460 col.clamp();
461 color_gamma_correct(col);
462 }
463
464 U32* pix = (U32*)(data + offset);
465 LLColor4 temp = LLColor4(col);
466 LLColor4U temp1 = LLColor4U(temp);
467 *pix = temp1.mAll;
468 }
469 }
470 createTexture(sCurrent);
471}
472
473void LLSkyTex::createTexture(S32 which)
474{
475 mImageGL[which]->createGLTexture(0, mImageRaw[which]);
476 mImageGL[which]->setClamp(TRUE, TRUE);
477}
478
479void LLSkyTex::bindTexture(BOOL curr)
480{
481 mImageGL[getWhich(curr)]->bind();
482}
483
484/***************************************
485 Sky
486***************************************/
487
488F32 LLHeavenBody::sInterpVal = 0;
489
490F32 LLVOSky::sNighttimeBrightness = 1.5f;
491
492S32 LLVOSky::sResolution = LLSkyTex::getResolution();
493S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X;
494S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y;
495
496LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
497: LLViewerObject(id, pcode, regionp),
498 mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS),
499 mBrightnessScale(1.f),
500 mBrightnessScaleNew(0.f),
501 mBrightnessScaleGuess(1.f),
502 mWeatherChange(FALSE),
503 mCloudDensity(0.2f),
504 mWind(0.f),
505 mForceUpdate(FALSE),
506 mWorldScale(1.f)
507{
508 mInitialized = FALSE;
509 mbCanSelect = FALSE;
510 mUpdateTimer.reset();
511
512 for (S32 i = 0; i < 6; i++)
513 {
514 mSkyTex[i].init();
515 }
516 for (S32 i=0; i<FACE_COUNT; i++)
517 {
518 mFace[i] = NULL;
519 }
520
521 mCameraPosAgent = gAgent.getCameraPositionAgent();
522 mAtmHeight = ATM_HEIGHT;
523 mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
524 updateHaze();
525
526 mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition");
527 if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition"))
528 {
529 initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0));
530 }
531 mAmbientScale = gSavedSettings.getF32("SkyAmbientScale");
532 mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift");
533 mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f;
534 mFogColor.mV[VALPHA] = 0.0f;
535 mFogRatio = 1.2f;
536
537 mSun.setIntensity(SUN_INTENSITY);
538 mMoon.setIntensity(0.1f * SUN_INTENSITY);
539
540 mCubeMap = NULL;
541
542 mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
543 mSunTexturep->setClamp(TRUE, TRUE);
544 mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
545 mMoonTexturep->setClamp(TRUE, TRUE);
546 mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
547 mBloomTexturep->setClamp(TRUE, TRUE);
548}
549
550
551LLVOSky::~LLVOSky()
552{
553 // Don't delete images - it'll get deleted by gImageList on shutdown
554 // This needs to be done for each texture
555
556 delete mCubeMap;
557 mCubeMap = NULL;
558}
559
560void LLVOSky::initClass()
561{
562 LLHaze::initClass();
563}
564
565
566void LLVOSky::init()
567{
568 // index of refraction calculation.
569 mTransp.init(NO_STEPS+1+4, FIRST_STEP, mAtmHeight, &mHaze);
570
571 const F32 haze_int = color_intens(mHaze.calcSigSca(0));
572 mHazeConcentration = haze_int /
573 (color_intens(LLHaze::calcAirSca(0)) + haze_int);
574
575 mBrightnessScaleNew = 0;
576
577 // Initialize the cached normalized direction vectors
578 for (S32 side = 0; side < 6; ++side)
579 {
580 for (S32 tile = 0; tile < NUM_TILES; ++tile)
581 {
582 initSkyTextureDirs(side, tile);
583 createSkyTexture(side, tile);
584 }
585 }
586
587 calcBrightnessScaleAndColors();
588 initCubeMap();
589}
590
591void LLVOSky::initCubeMap()
592{
593 std::vector<LLPointer<LLImageRaw> > images;
594 for (S32 side = 0; side < 6; side++)
595 {
596 images.push_back(mSkyTex[side].getImageRaw());
597 }
598 if (mCubeMap != NULL)
599 {
600 mCubeMap->init(images);
601 }
602 else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap)
603 {
604 mCubeMap = new LLCubeMap();
605 mCubeMap->init(images);
606 }
607}
608
609
610void LLVOSky::cleanupGL()
611{
612 S32 i;
613 for (i = 0; i < 6; i++)
614 {
615 mSkyTex[i].cleanupGL();
616 }
617 if (getCubeMap())
618 {
619 getCubeMap()->destroyGL();
620 }
621}
622
623void LLVOSky::restoreGL()
624{
625 S32 i;
626 for (i = 0; i < 6; i++)
627 {
628 mSkyTex[i].restoreGL();
629 }
630 mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
631 mSunTexturep->setClamp(TRUE, TRUE);
632 mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
633 mMoonTexturep->setClamp(TRUE, TRUE);
634 mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
635 mBloomTexturep->setClamp(TRUE, TRUE);
636
637 calcBrightnessScaleAndColors();
638
639 // Water is currently broken on Mac.
640 if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap)
641 {
642 LLCubeMap* cube_map = getCubeMap();
643
644 std::vector<LLPointer<LLImageRaw> > images;
645 for (S32 side = 0; side < 6; side++)
646 {
647 images.push_back(mSkyTex[side].getImageRaw());
648 }
649
650 if(cube_map)
651 {
652 cube_map->init(images);
653 mForceUpdate = TRUE;
654 }
655 }
656
657 if (mDrawable)
658 {
659 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
660 }
661
662}
663
664
665void LLVOSky::updateHaze()
666{
667 time_t timer;
668 time(&timer);
669 static LLRand WeatherRandomNumber(gmtime(&timer)->tm_mday);
670 if (gSavedSettings.getBOOL("FixedWeather"))
671 {
672 WeatherRandomNumber.seed(8008135);
673 }
674
675 const F32 fo_upper_bound = 5;
676 const F32 sca_upper_bound = 6;
677 const F32 fo = 1 + WeatherRandomNumber.llfrand(fo_upper_bound - 1);
678 const static F32 upper = 0.5f / gFastLn.ln(fo_upper_bound);
679 mHaze.setFalloff(fo);
680 mHaze.setG(WeatherRandomNumber.llfrand(0.0f + upper * gFastLn.ln(fo)));
681 LLColor3 sca;
682 const F32 cd = mCloudDensity * 3;
683 F32 min_r = cd - 1;
684 if (min_r < 0)
685 {
686 min_r = 0;
687 }
688 F32 max_r = cd + 1;
689 if (max_r > sca_upper_bound)
690 {
691 max_r = sca_upper_bound;
692 }
693
694 sca.mV[0] = min_r + WeatherRandomNumber.llfrand(max_r - min_r);//frand(6);
695
696 min_r = sca.mV[0] - 0.1f;
697 if (min_r < 0)
698 {
699 min_r = 0;
700 }
701 max_r = sca.mV[0] + 0.5f;
702 if (max_r > sca_upper_bound)
703 {
704 max_r = sca_upper_bound;
705 }
706
707 sca.mV[1] = min_r + WeatherRandomNumber.llfrand(max_r - min_r);
708
709 min_r = sca.mV[1];
710 if (min_r < 0)
711 {
712 min_r = 0;
713 }
714 max_r = sca.mV[1] + 1;
715 if (max_r > sca_upper_bound)
716 {
717 max_r = sca_upper_bound;
718 }
719
720 sca.mV[2] = min_r + WeatherRandomNumber.llfrand(max_r - min_r);
721
722 sca = AIR_SCA_AVG * sca;
723
724 mHaze.setSigSca(sca);
725}
726
727void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile)
728{
729 S32 tile_x = tile % NUM_TILES_X;
730 S32 tile_y = tile / NUM_TILES_X;
731
732 S32 tile_x_pos = tile_x * sTileResX;
733 S32 tile_y_pos = tile_y * sTileResY;
734
735 F32 coeff[3] = {0, 0, 0};
736 const S32 curr_coef = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
737 const S32 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
738 const S32 x_coef = (curr_coef + 1) % 3;
739 const S32 y_coef = (x_coef + 1) % 3;
740
741 coeff[curr_coef] = (F32)side_dir;
742
743 F32 inv_res = 1.f/sResolution;
744 S32 x, y;
745 for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
746 {
747 for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
748 {
749 coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f;
750 coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f;
751 LLVector3 dir(coeff[0], coeff[1], coeff[2]);
752 dir.normVec();
753 mSkyTex[side].setDir(dir, x, y);
754 }
755 }
756}
757
758void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
759{
760 S32 tile_x = tile % NUM_TILES_X;
761 S32 tile_y = tile / NUM_TILES_X;
762
763 S32 tile_x_pos = tile_x * sTileResX;
764 S32 tile_y_pos = tile_y * sTileResY;
765
766 S32 x, y;
767 for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
768 {
769 for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
770 {
771 mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y);
772 }
773 }
774}
775
776
777LLColor3 LLVOSky::calcSkyColorInDir(const LLVector3 &dir)
778{
779 LLColor3 col, transp;
780
781 if (dir.mV[VZ] < -0.02)
782 {
783 col = LLColor3(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.27f));
784 float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]);
785 x *= x;
786 col.mV[0] *= x*x;
787 col.mV[1] *= powf(x, 2.5f);
788 col.mV[2] *= x*x*x;
789 return col;
790 }
791
792
793 calcSkyColorInDir(col, transp, dir);
794 F32 br = color_max(col);
795 if (br > mBrightnessScaleNew)
796 {
797 mBrightnessScaleNew = br;
798 mBrightestPointNew = col;
799 }
800 return col;
801}
802
803
804LLColor4 LLVOSky::calcInScatter(LLColor4& transp, const LLVector3 &point, F32 exager = 1) const
805{
806 LLColor3 col, tr;
807 calcInScatter(col, tr, point, exager);
808 col *= mBrightnessScaleGuess;
809 transp = LLColor4(tr);
810 return LLColor4(col);
811}
812
813
814
815void LLVOSky::calcSkyColorInDir(LLColor3& res, LLColor3& transp, const LLVector3& dir) const
816{
817 const LLVector3& tosun = getToSunLast();
818 res.setToBlack();
819 LLColor3 haze_res(0.f, 0.f, 0.f);
820 transp.setToWhite();
821 LLVector3 step_v ;
822 LLVector3 cur_pos = mCameraPosAgent;
823 F32 h;
824
825 F32 dist = calcHitsAtmEdge(mCameraPosAgent, dir);
826// const F32 K = log(dist / FIRST_STEP + 1) / NO_STEPS;
827 const F32 K = gFastLn.ln(dist / FIRST_STEP + 1) / NO_STEPS;
828 const F32 e_pow_k = (F32)LL_FAST_EXP(K);
829 F32 step = FIRST_STEP * (1 - 1 / e_pow_k);
830
831 for (S32 s = 0; s < NO_STEPS; ++s)
832 {
833 h = calcHeight(cur_pos);
834 step *= e_pow_k;
835 LLColor3 air_sca_opt_depth;
836 LLHaze::calcAirSca(h, air_sca_opt_depth);
837 air_sca_opt_depth *= step;
838
839 LLColor3 haze_sca_opt_depth;
840 mHaze.calcSigSca(h, haze_sca_opt_depth);
841 haze_sca_opt_depth *= step;
842
843 LLColor3 haze_ext_opt_depth = haze_sca_opt_depth;
844 haze_ext_opt_depth *= (1.f + mHaze.getAbsCoef());
845
846 if (calcHitsEarth(cur_pos, tosun) < 0) // calculates amount of in-scattered light from the sun
847 {
848 //visibility check is too expensive
849 LLColor3 air_transp;
850 mTransp.calcTransp(calcUpVec(cur_pos) * tosun, h, air_transp);
851 air_transp *= transp;
852 res += air_sca_opt_depth * air_transp;
853 haze_res += haze_sca_opt_depth * air_transp;
854 }
855 LLColor3 temp(-4.f * F_PI * (air_sca_opt_depth + haze_ext_opt_depth));
856 temp.exp();
857 transp *= temp;
858 step_v = dir * step;
859 cur_pos += step_v;
860 }
861 const F32 cos_dir = dir * tosun;
862 res *= calcAirPhaseFunc(cos_dir);
863 res += haze_res * mHaze.calcPhase(cos_dir);
864 res *= mSun.getIntensity();
865}
866
867
868
869
870void LLVOSky::calcInScatter(LLColor3& res, LLColor3& transp,
871 const LLVector3& P, const F32 exaggeration) const
872{
873 const LLVector3& tosun = getToSunLast();
874 res.setToBlack();
875 transp.setToWhite();
876
877 LLVector3 lower, upper;
878 LLVector3 dir = P - mCameraPosAgent;
879
880 F32 dist = exaggeration * dir.normVec();
881
882 const F32 cos_dir = dir * tosun;
883
884 if (dir.mV[VZ] > 0)
885 {
886 lower = mCameraPosAgent;
887 upper = P;
888 }
889 else
890 {
891 lower = P;
892 upper = mCameraPosAgent;
893 dir = -dir;
894 }
895
896 const F32 lower_h = calcHeight(lower);
897 const F32 upper_h = calcHeight(upper);
898 const LLVector3 up_upper = calcUpVec(upper);
899 const LLVector3 up_lower = calcUpVec(lower);
900
901 transp = color_div(mTransp.calcTransp(up_lower * dir, lower_h),
902 mTransp.calcTransp(up_upper * dir, upper_h));
903 color_pow(transp, exaggeration);
904
905 if (calcHitsEarth(upper, tosun) > 0)
906 {
907 const F32 avg = color_avg(transp);
908 //const F32 avg = llmin(1.f, 1.2f * color_avg(transp));
909 transp.setVec(avg, avg, avg);
910 return;
911 }
912
913 LLColor3 air_sca_opt_depth = LLHaze::calcAirSca(upper_h);
914 LLColor3 haze_sca_opt_depth = mHaze.calcSigSca(upper_h);
915 LLColor3 sun_transp;
916 mTransp.calcTransp(up_upper * tosun, upper_h, sun_transp);
917
918 if (calcHitsEarth(lower, tosun) < 0)
919 {
920 air_sca_opt_depth += LLHaze::calcAirSca(lower_h);
921 air_sca_opt_depth *= 0.5;
922 haze_sca_opt_depth += mHaze.calcSigSca(lower_h);
923 haze_sca_opt_depth *= 0.5;
924 sun_transp += mTransp.calcTransp(up_lower * tosun, lower_h);
925 sun_transp *= 0.5;
926 }
927
928 res = calcAirPhaseFunc(cos_dir) * air_sca_opt_depth;
929 res += mHaze.calcPhase(cos_dir) * haze_sca_opt_depth;
930 res = mSun.getIntensity() * dist * sun_transp * res;
931}
932
933
934
935
936
937
938F32 LLVOSky::calcHitsEarth(const LLVector3& orig, const LLVector3& dir) const
939{
940 const LLVector3 from_earth_center = mEarthCenter - orig;
941 const F32 tca = dir * from_earth_center;
942 if ( tca < 0 )
943 {
944 return -1;
945 }
946
947 const F32 thc2 = EARTH_RADIUS * EARTH_RADIUS -
948 from_earth_center.magVecSquared() + tca * tca;
949 if (thc2 < 0 )
950 {
951 return -1;
952 }
953
954 return tca - sqrt ( thc2 );
955}
956
957F32 LLVOSky::calcHitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const
958{
959 const LLVector3 from_earth_center = mEarthCenter - orig;
960 const F32 tca = dir * from_earth_center;
961
962 const F32 thc2 = (EARTH_RADIUS + mAtmHeight) * (EARTH_RADIUS + mAtmHeight) -
963 from_earth_center.magVecSquared() + tca * tca;
964 return tca + sqrt(thc2);
965}
966
967
968void LLVOSky::updateBrightestDir()
969{
970 LLColor3 br_pt, transp;
971 const S32 test_no = 5;
972 const F32 step = F_PI_BY_TWO / (test_no + 1);
973 for (S32 i = 0; i < test_no; ++i)
974 {
975 F32 cos_dir = cos ((i + 1) * step);
976 calcSkyColorInDir(br_pt, transp, move_vec(getToSunLast(), cos_dir));
977 const F32 br = color_max(br_pt);
978 if (br > mBrightnessScaleGuess)
979 {
980 mBrightnessScaleGuess = br;
981 mBrightestPointGuess = br_pt;
982 }
983 }
984}
985
986
987void LLVOSky::calcBrightnessScaleAndColors()
988{
989 // new correct normalization.
990 if (mBrightnessScaleNew < 1e-7)
991 {
992 mBrightnessScale = 1;
993 mBrightestPoint.setToBlack();
994 }
995 else
996 {
997 mBrightnessScale = 1.f/mBrightnessScaleNew;
998 mBrightestPoint = mBrightestPointNew;
999 }
1000
1001 mBrightnessScaleNew = 0;
1002 // and addition
1003
1004 // Calculate Sun and Moon color
1005 const F32 h = llmax(0.0f, mCameraPosAgent.mV[2]);
1006 const LLColor3 sun_color = mSun.getIntensity() * mTransp.calcTransp(getToSunLast().mV[2], h);
1007 const LLColor3 moon_color = mNightColorShift *
1008 mMoon.getIntensity() * mTransp.calcTransp(getToMoonLast().mV[2], h);
1009
1010 F32 intens = color_intens(sun_color);
1011 F32 increase_sun_br = (intens > 0) ? 1.2f * color_intens(mBrightestPoint) / intens : 1;
1012
1013 intens = color_intens(moon_color);
1014 F32 increase_moon_br = (intens > 0) ? 1.2f * llmax(1.0f, color_intens(mBrightestPoint) / intens) : 1;
1015
1016 mSun.setColor(mBrightnessScale * increase_sun_br * sun_color);
1017 mMoon.setColor(mBrightnessScale * increase_moon_br * moon_color);
1018
1019 const LLColor3 haze_col = color_norm_abs(mHaze.getSigSca());
1020 for (S32 i = 0; i < 6; ++i)
1021 {
1022 mSkyTex[i].create(mBrightnessScale, mHazeConcentration * mBrightestPoint * haze_col);
1023 }
1024
1025 mBrightnessScaleGuess = mBrightnessScale;
1026 mBrightestPointGuess = mBrightestPoint;
1027
1028// calculateColors(); // MSMSM Moving this down to before generateScatterMap(), per Milo Lindens suggestion, to fix orange flashing bug.
1029
1030 mSun.renewDirection();
1031 mSun.renewColor();
1032 mMoon.renewDirection();
1033 mMoon.renewColor();
1034
1035 LLColor3 transp;
1036
1037 if (calcHitsEarth(mCameraPosAgent, getToSunLast()) < 0)
1038 {
1039 calcSkyColorInDir(mBrightestPointGuess, transp, getToSunLast());
1040 mBrightnessScaleGuess = color_max(mBrightestPointGuess);
1041 updateBrightestDir();
1042 mBrightnessScaleGuess = 1.f / llmax(1.0f, mBrightnessScaleGuess);
1043 }
1044 else if (getToSunLast().mV[2] > -0.5)
1045 {
1046 const LLVector3 almost_to_sun = toHorizon(getToSunLast());
1047 calcSkyColorInDir(mBrightestPointGuess, transp, almost_to_sun);
1048 mBrightnessScaleGuess = color_max(mBrightestPointGuess);
1049 updateBrightestDir();
1050 mBrightnessScaleGuess = 1.f / llmax(1.0f, mBrightnessScaleGuess);
1051 }
1052 else
1053 {
1054 mBrightestPointGuess.setToBlack();
1055 mBrightnessScaleGuess = 1;
1056 }
1057
1058 calculateColors(); // MSMSM Moved this down here per Milo Lindens suggestion, to fix orange flashing bug at sunset.
1059 generateScatterMap();
1060}
1061
1062
1063
1064void LLVOSky::calculateColors()
1065{
1066 const F32 h = -0.1f;
1067 const LLVector3& tosun = getToSunLast();
1068
1069 F32 full_on, full_off, on, on_cl;
1070 F32 sun_factor = 1;
1071
1072 // Sun Diffuse
1073 if (calcHitsEarth(mCameraPosAgent, tosun) < 0)
1074 {
1075 mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(tosun.mV[2], h);
1076 }
1077 else
1078 {
1079 mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(0, h);
1080 }
1081 mSunDiffuse = 1.0f * color_norm(mSunDiffuse);
1082
1083 // Sun Ambient
1084 full_off = -0.3f;
1085 full_on = -0.03f;
1086 if (tosun.mV[2] < full_off)
1087 {
1088 mSunAmbient.setToBlack();
1089 }
1090 else
1091 {
1092 on = (tosun.mV[2] - full_off) / (full_on - full_off);
1093 sun_factor = llmax(0.0f, llmin(on, 1.0f));
1094
1095 LLColor3 sun_amb = mAmbientScale * (0.8f * mSunDiffuse +
1096 0.2f * mBrightnessScaleGuess * mBrightestPointGuess);
1097
1098 color_norm_pow(sun_amb, 0.1f, TRUE);
1099 sun_factor *= min_intens_factor(sun_amb, 1.9f);
1100 mSunAmbient = LLColor4(sun_factor * sun_amb);
1101 }
1102
1103
1104 // Moon Diffuse
1105 full_on = 0.3f;
1106 full_off = 0.01f;
1107 if (getToMoonLast().mV[2] < full_off)
1108 {
1109 mMoonDiffuse.setToBlack();
1110 }
1111 else
1112 {
1113 // Steve: Added moonlight diffuse factor scalar (was constant .3)
1114 F32 diffuse_factor = .1f + sNighttimeBrightness * .2f; // [.1, .5] default = .3
1115 on = (getToMoonLast().mV[2] - full_off) / (full_on - full_off);
1116 on_cl = llmin(on, 1.0f);
1117 mMoonDiffuse = on_cl * mNightColorShift * diffuse_factor;
1118 }
1119
1120 // Moon Ambient
1121
1122 F32 moon_amb_factor = 1.f;
1123
1124 if (gAgent.inPrelude())
1125 {
1126 moon_amb_factor *= 2.0f;
1127 }
1128
1129 full_on = 0.30f;
1130 full_off = 0.01f;
1131 if (getToMoonLast().mV[2] < full_off)
1132 {
1133 mMoonAmbient.setToBlack();
1134 }
1135 else
1136 {
1137 on = (getToMoonLast().mV[2] - full_off) / (full_on - full_off);
1138 on_cl = llmax(0.0f, llmin(on, 1.0f));
1139 mMoonAmbient = on_cl * moon_amb_factor * mMoonDiffuse;
1140 }
1141
1142
1143 // Sun Diffuse
1144 full_off = -0.05f;
1145 full_on = -0.00f;
1146 if (tosun.mV[2] < full_off)
1147 {
1148 mSunDiffuse.setToBlack();
1149 }
1150 else
1151 {
1152 on = (getToSunLast().mV[2] - full_off) / (full_on - full_off);
1153 sun_factor = llmax(0.0f, llmin(on, 1.0f));
1154
1155 color_norm_pow(mSunDiffuse, 0.12f, TRUE);
1156 sun_factor *= min_intens_factor(mSunDiffuse, 2.1f);
1157 mSunDiffuse *= sun_factor;
1158 }
1159
1160
1161 mTotalAmbient = mSunAmbient + mMoonAmbient;
1162 mTotalAmbient.setAlpha(1);
1163 //llinfos << "MoonDiffuse: " << mMoonDiffuse << llendl;
1164 //llinfos << "TotalAmbient: " << mTotalAmbient << llendl;
1165
1166 mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f;
1167 mFadeColor.setAlpha(0);
1168}
1169
1170
1171BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
1172{
1173 return TRUE;
1174}
1175
1176BOOL LLVOSky::updateSky()
1177{
1178 if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
1179 {
1180 return TRUE;
1181 }
1182
1183 if (mDead)
1184 {
1185 // It's dead. Don't update it.
1186 return TRUE;
1187 }
1188 if (gGLManager.mIsDisabled)
1189 {
1190 return TRUE;
1191 }
1192
1193 setPositionAgent(gAgent.getCameraPositionAgent());
1194
1195 static S32 next_frame = 0;
1196 const S32 total_no_tiles = 6 * NUM_TILES;
1197 const S32 cycle_frame_no = total_no_tiles + 1;
1198
1199// if (mUpdateTimer.getElapsedTimeF32() > 0.1f)
1200 {
1201 mUpdateTimer.reset();
1202 const S32 frame = next_frame;
1203
1204 ++next_frame;
1205 next_frame = next_frame % cycle_frame_no;
1206
1207 sInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no;
1208 LLSkyTex::setInterpVal( sInterpVal );
1209 LLHeavenBody::setInterpVal( sInterpVal );
1210 calculateColors();
1211 if (mForceUpdate || total_no_tiles == frame)
1212 {
1213 calcBrightnessScaleAndColors();
1214 LLSkyTex::stepCurrent();
1215
1216 const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f);
1217 const static F32 COLOR_CHANGE_THRESHOLD = 0.01f;
1218
1219 LLVector3 direction = mSun.getDirection();
1220 direction.normVec();
1221 const F32 dot_lighting = direction * mLastLightingDirection;
1222
1223 LLColor3 delta_color;
1224 delta_color.setVec(mLastTotalAmbient.mV[0] - mTotalAmbient.mV[0],
1225 mLastTotalAmbient.mV[1] - mTotalAmbient.mV[1],
1226 mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]);
1227
1228 if ( mForceUpdate
1229 || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
1230 || (delta_color.magVec() > COLOR_CHANGE_THRESHOLD)
1231 || !mInitialized)
1232 && !direction.isExactlyZero())
1233 {
1234 mLastLightingDirection = direction;
1235 mLastTotalAmbient = mTotalAmbient;
1236 mInitialized = TRUE;
1237
1238 if (mCubeMap)
1239 {
1240 if (mForceUpdate)
1241 {
1242 updateFog(gCamera->getFar());
1243 for (int side = 0; side < 6; side++)
1244 {
1245 for (int tile = 0; tile < NUM_TILES; tile++)
1246 {
1247 createSkyTexture(side, tile);
1248 }
1249 }
1250
1251 calcBrightnessScaleAndColors();
1252
1253 for (int side = 0; side < 6; side++)
1254 {
1255 LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE);
1256 LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE);
1257 raw2->copy(raw1);
1258 mSkyTex[side].createTexture(mSkyTex[side].getWhich(FALSE));
1259 }
1260 next_frame = 0;
1261 //llSkyTex::stepCurrent();
1262 }
1263
1264 std::vector<LLPointer<LLImageRaw> > images;
1265 for (S32 side = 0; side < 6; side++)
1266 {
1267 images.push_back(mSkyTex[side].getImageRaw(FALSE));
1268 }
1269 mCubeMap->init(images);
1270 }
1271 }
1272
1273 mForceUpdate = FALSE;
1274 }
1275 else
1276 {
1277 const S32 side = frame / NUM_TILES;
1278 const S32 tile = frame % NUM_TILES;
1279 createSkyTexture(side, tile);
1280 }
1281 }
1282
1283
1284 if (mDrawable)
1285 {
1286 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
1287 }
1288 return TRUE;
1289}
1290
1291
1292void LLVOSky::updateTextures(LLAgent &agent)
1293{
1294 if (mSunTexturep)
1295 {
1296 mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
1297 mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
1298 mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
1299 }
1300}
1301
1302LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
1303{
1304 pipeline->allocDrawable(this);
1305 mDrawable->setLit(FALSE);
1306
1307 LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
1308 poolp->setSkyTex(mSkyTex);
1309 poolp->setSun(&mSun);
1310 poolp->setMoon(&mMoon);
1311
1312 for (S32 i = 0; i < 6; ++i)
1313 {
1314 mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
1315 }
1316
1317 mFace[FACE_SUN] = mDrawable->addFace(poolp, mSunTexturep);
1318 mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
1319 mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
1320
1321 //mDrawable->addFace(poolp, LLViewerImage::sDefaultImagep);
1322 gPipeline.markMaterialed(mDrawable);
1323
1324 return mDrawable;
1325}
1326
1327BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
1328{
1329 if (mFace[FACE_REFLECTION] == NULL)
1330 {
1331 mFace[FACE_REFLECTION] = drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL);
1332 }
1333
1334 mCameraPosAgent = drawable->getPositionAgent();
1335 mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
1336 mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
1337
1338
1339 LLVector3 v_agent[8];
1340 for (S32 i = 0; i < 8; ++i)
1341 {
1342 F32 x_sgn = (i&1) ? 1.f : -1.f;
1343 F32 y_sgn = (i&2) ? 1.f : -1.f;
1344 F32 z_sgn = (i&4) ? 1.f : -1.f;
1345 v_agent[i] = mCameraPosAgent + HORIZON_DIST * LLVector3(x_sgn, y_sgn, z_sgn);
1346 }
1347
1348 LLStrider<LLVector3> verticesp;
1349 LLStrider<LLVector3> normalsp;
1350 LLStrider<LLVector2> texCoordsp;
1351 U32 *indicesp;
1352 S32 index_offset;
1353 LLFace *face;
1354
1355 for (S32 side = 0; side < 6; ++side)
1356 {
1357 face = mFace[FACE_SIDE0 + side];
1358 face->setPrimType(LLTriangles);
1359 face->setSize(4, 6);
1360 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1361 if (-1 == index_offset)
1362 {
1363 return TRUE;
1364 }
1365
1366 S32 vtx = 0;
1367 S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
1368 S32 side_dir = side & 1; // even - 0, odd - 1
1369 S32 i_bit = (curr_bit + 2) % 3;
1370 S32 j_bit = (i_bit + 2) % 3;
1371
1372 LLVector3 axis;
1373 axis.mV[curr_bit] = 1;
1374 face->mCenterAgent = mCameraPosAgent + (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
1375
1376 vtx = side_dir << curr_bit;
1377 *(verticesp++) = v_agent[vtx];
1378 *(verticesp++) = v_agent[vtx | 1 << j_bit];
1379 *(verticesp++) = v_agent[vtx | 1 << i_bit];
1380 *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit];
1381
1382 *(texCoordsp++) = TEX00;
1383 *(texCoordsp++) = TEX01;
1384 *(texCoordsp++) = TEX10;
1385 *(texCoordsp++) = TEX11;
1386
1387 // Triangles for each side
1388 *indicesp++ = index_offset + 0;
1389 *indicesp++ = index_offset + 1;
1390 *indicesp++ = index_offset + 3;
1391
1392 *indicesp++ = index_offset + 0;
1393 *indicesp++ = index_offset + 3;
1394 *indicesp++ = index_offset + 2;
1395 }
1396
1397 const LLVector3 &look_at = gCamera->getAtAxis();
1398 LLVector3 right = look_at % LLVector3::z_axis;
1399 LLVector3 up = right % look_at;
1400 right.normVec();
1401 up.normVec();
1402
1403 const static F32 elevation_factor = 0.0f/sResolution;
1404 const F32 cos_max_angle = cosHorizon(elevation_factor);
1405 mSun.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_SUN, TRUE, mSun, cos_max_angle, up, right));
1406 mMoon.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_MOON, FALSE, mMoon, cos_max_angle, up, right));
1407
1408 const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f;
1409 // gWorldPointer->getWaterHeight() + 0.01f;
1410 const F32 camera_height = mCameraPosAgent.mV[2];
1411 const F32 height_above_water = camera_height - water_height;
1412
1413 BOOL sun = FALSE;
1414
1415 if (mSun.isVisible())
1416 {
1417 if (mMoon.isVisible())
1418 {
1419 sun = look_at * mSun.getDirection() > 0;
1420 }
1421 else
1422 {
1423 sun = TRUE;
1424 }
1425 }
1426
1427 if (height_above_water > 0)
1428 {
1429#if 1 //1.9.1
1430 BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0;
1431#else
1432 BOOL render_ref = !(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= LLDrawPoolWater::SHADER_LEVEL_RIPPLE);
1433#endif
1434 if (sun)
1435 {
1436 setDrawRefl(0);
1437 if (render_ref)
1438 {
1439 updateReflectionGeometry(drawable, height_above_water, mSun);
1440 }
1441 }
1442 else
1443 {
1444 setDrawRefl(1);
1445 if (render_ref)
1446 {
1447 updateReflectionGeometry(drawable, height_above_water, mMoon);
1448 }
1449 }
1450 }
1451 else
1452 {
1453 setDrawRefl(-1);
1454 }
1455
1456
1457 LLPipeline::sCompiles++;
1458 return TRUE;
1459}
1460
1461
1462BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, const BOOL is_sun,
1463 LLHeavenBody& hb, const F32 cos_max_angle,
1464 const LLVector3 &up, const LLVector3 &right)
1465{
1466 LLStrider<LLVector3> verticesp;
1467 LLStrider<LLVector3> normalsp;
1468 LLStrider<LLVector2> texCoordsp;
1469 U32 *indicesp;
1470 S32 index_offset;
1471 LLFace *facep;
1472
1473 LLVector3 to_dir = hb.getDirection();
1474 LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
1475
1476
1477 LLVector3 hb_right = to_dir % LLVector3::z_axis;
1478 LLVector3 hb_up = hb_right % to_dir;
1479 hb_right.normVec();
1480 hb_up.normVec();
1481
1482 //const static F32 cos_max_turn = sqrt(3.f) / 2; // 30 degrees
1483 //const F32 cos_turn_right = 1. / (llmax(cos_max_turn, hb_right * right));
1484 //const F32 cos_turn_up = 1. / llmax(cos_max_turn, hb_up * up);
1485
1486 const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
1487 F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
1488 F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
1489
1490 // Parameters for the water reflection
1491 hb.setU(HEAVENLY_BODY_FACTOR * horiz_enlargement * hb.getDiskRadius() * hb_right);
1492 hb.setV(HEAVENLY_BODY_FACTOR * vert_enlargement * hb.getDiskRadius() * hb_up);
1493 // End of parameters for the water reflection
1494
1495 const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU();
1496 const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV();
1497
1498 //const LLVector3 scaled_right = horiz_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_right;//right;
1499 //const LLVector3 scaled_up = vert_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_up;//up;
1500 LLVector3 v_clipped[4];
1501
1502 hb.corner(0) = draw_pos - scaled_right + scaled_up;
1503 hb.corner(1) = draw_pos - scaled_right - scaled_up;
1504 hb.corner(2) = draw_pos + scaled_right + scaled_up;
1505 hb.corner(3) = draw_pos + scaled_right - scaled_up;
1506
1507
1508 F32 t_left, t_right;
1509 if (!clip_quad_to_horizon(t_left, t_right, v_clipped, hb.corners(), cos_max_angle))
1510 {
1511 hb.setVisible(FALSE);
1512 return FALSE;
1513 }
1514 hb.setVisible(TRUE);
1515
1516 facep = mFace[f];
1517 facep->setPrimType(LLTriangles);
1518 facep->setSize(4, 6);
1519 index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1520 if (-1 == index_offset)
1521 {
1522 return TRUE;
1523 }
1524
1525 for (S32 vtx = 0; vtx < 4; ++vtx)
1526 {
1527 hb.corner(vtx) = v_clipped[vtx];
1528 *(verticesp++) = hb.corner(vtx) + mCameraPosAgent;
1529 }
1530
1531 *(texCoordsp++) = TEX01;
1532 *(texCoordsp++) = TEX00;
1533 //*(texCoordsp++) = (t_left > 0) ? LLVector2(0, t_left) : TEX00;
1534 *(texCoordsp++) = TEX11;
1535 *(texCoordsp++) = TEX10;
1536 //*(texCoordsp++) = (t_right > 0) ? LLVector2(1, t_right) : TEX10;
1537
1538 *indicesp++ = index_offset + 0;
1539 *indicesp++ = index_offset + 2;
1540 *indicesp++ = index_offset + 1;
1541
1542 *indicesp++ = index_offset + 1;
1543 *indicesp++ = index_offset + 2;
1544 *indicesp++ = index_offset + 3;
1545
1546 if (is_sun)
1547 {
1548 if ((t_left > 0) && (t_right > 0))
1549 {
1550 F32 t = (t_left + t_right) * 0.5f;
1551 mSun.setHorizonVisibility(0.5f * (1 + cos(t * F_PI)));
1552 }
1553 else
1554 {
1555 mSun.setHorizonVisibility();
1556 }
1557 updateSunHaloGeometry(drawable);
1558 }
1559
1560 return TRUE;
1561}
1562
1563
1564
1565
1566// Clips quads with top and bottom sides parallel to horizon.
1567
1568BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
1569 const LLVector3 v_corner[4], const F32 cos_max_angle)
1570{
1571 t_left = clip_side_to_horizon(v_corner[1], v_corner[0], cos_max_angle);
1572 t_right = clip_side_to_horizon(v_corner[3], v_corner[2], cos_max_angle);
1573
1574 if ((t_left >= 1) || (t_right >= 1))
1575 {
1576 return FALSE;
1577 }
1578
1579 //const BOOL left_clip = (t_left > 0);
1580 //const BOOL right_clip = (t_right > 0);
1581
1582 //if (!left_clip && !right_clip)
1583 {
1584 for (S32 vtx = 0; vtx < 4; ++vtx)
1585 {
1586 v_clipped[vtx] = v_corner[vtx];
1587 }
1588 }
1589/* else
1590 {
1591 v_clipped[0] = v_corner[0];
1592 v_clipped[1] = left_clip ? ((1 - t_left) * v_corner[1] + t_left * v_corner[0])
1593 : v_corner[1];
1594 v_clipped[2] = v_corner[2];
1595 v_clipped[3] = right_clip ? ((1 - t_right) * v_corner[3] + t_right * v_corner[2])
1596 : v_corner[3];
1597 }*/
1598
1599 return TRUE;
1600}
1601
1602
1603F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos_max_angle)
1604{
1605 const LLVector3 V = V1 - V0;
1606 const F32 k2 = 1.f/(cos_max_angle * cos_max_angle) - 1;
1607 const F32 A = V.mV[0] * V.mV[0] + V.mV[1] * V.mV[1] - k2 * V.mV[2] * V.mV[2];
1608 const F32 B = V0.mV[0] * V.mV[0] + V0.mV[1] * V.mV[1] - k2 * V0.mV[2] * V.mV[2];
1609 const F32 C = V0.mV[0] * V0.mV[0] + V0.mV[1] * V0.mV[1] - k2 * V0.mV[2] * V0.mV[2];
1610
1611 if (fabs(A) < 1e-7)
1612 {
1613 return -0.1f; // v0 is cone origin and v1 is on the surface of the cone.
1614 }
1615
1616 const F32 det = sqrt(B*B - A*C);
1617 const F32 t1 = (-B - det) / A;
1618 const F32 t2 = (-B + det) / A;
1619 const F32 z1 = V0.mV[2] + t1 * V.mV[2];
1620 const F32 z2 = V0.mV[2] + t2 * V.mV[2];
1621 if (z1 * cos_max_angle < 0)
1622 {
1623 return t2;
1624 }
1625 else if (z2 * cos_max_angle < 0)
1626 {
1627 return t1;
1628 }
1629 else if ((t1 < 0) || (t1 > 1))
1630 {
1631 return t2;
1632 }
1633 else
1634 {
1635 return t1;
1636 }
1637}
1638
1639
1640void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
1641{
1642 const LLVector3* v_corner = mSun.corners();
1643
1644 LLStrider<LLVector3> verticesp;
1645 LLStrider<LLVector3> normalsp;
1646 LLStrider<LLVector2> texCoordsp;
1647 U32 *indicesp;
1648 S32 index_offset;
1649 LLFace *face;
1650
1651 const LLVector3 right = 2 * (v_corner[2] - v_corner[0]);
1652 LLVector3 up = 2 * (v_corner[2] - v_corner[3]);
1653 up.normVec();
1654 F32 size = right.magVec();
1655 up = size * up;
1656 const LLVector3 draw_pos = 0.25 * (v_corner[0] + v_corner[1] + v_corner[2] + v_corner[3]);
1657
1658 LLVector3 v_glow_corner[4];
1659
1660 v_glow_corner[0] = draw_pos - right + up;
1661 v_glow_corner[1] = draw_pos - right - up;
1662 v_glow_corner[2] = draw_pos + right + up;
1663 v_glow_corner[3] = draw_pos + right - up;
1664
1665 face = mFace[FACE_BLOOM];
1666 face->setPrimType(LLTriangles);
1667 face->setSize(4, 6);
1668 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1669 if (-1 == index_offset)
1670 {
1671 return;
1672 }
1673
1674 for (S32 vtx = 0; vtx < 4; ++vtx)
1675 {
1676 *(verticesp++) = v_glow_corner[vtx] + mCameraPosAgent;
1677 }
1678
1679 *(texCoordsp++) = TEX01;
1680 *(texCoordsp++) = TEX00;
1681 *(texCoordsp++) = TEX11;
1682 *(texCoordsp++) = TEX10;
1683
1684 *indicesp++ = index_offset + 0;
1685 *indicesp++ = index_offset + 2;
1686 *indicesp++ = index_offset + 1;
1687
1688 *indicesp++ = index_offset + 1;
1689 *indicesp++ = index_offset + 2;
1690 *indicesp++ = index_offset + 3;
1691}
1692
1693
1694F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir)
1695{
1696 LLVector3 P = p;
1697 P.normVec();
1698
1699 const F32 cos_dir_angle = -P.mV[VZ];
1700 const F32 sin_dir_angle = sqrt(1 - cos_dir_angle * cos_dir_angle);
1701
1702 F32 cos_diff_angles = cos_dir_angle * cos_dir_from_top
1703 + sin_dir_angle * sin_dir_from_top;
1704
1705 F32 diff_angles;
1706 if (cos_diff_angles > (1 - 1e-7))
1707 diff_angles = 0;
1708 else
1709 diff_angles = acos(cos_diff_angles);
1710
1711 const F32 rel_diff_angles = diff_angles / diff_angl_dir;
1712 const F32 dt = 1 - rel_diff_angles;
1713
1714 return (dt < 0) ? 0 : dt;
1715}
1716
1717
1718F32 dtClip(const LLVector3& v0, const LLVector3& v1, F32 far_clip2)
1719{
1720 F32 dt_clip;
1721 const LLVector3 otrezok = v1 - v0;
1722 const F32 A = otrezok.magVecSquared();
1723 const F32 B = v0 * otrezok;
1724 const F32 C = v0.magVecSquared() - far_clip2;
1725 const F32 det = sqrt(B*B - A*C);
1726 dt_clip = (-B - det) / A;
1727 if ((dt_clip < 0) || (dt_clip > 1))
1728 dt_clip = (-B + det) / A;
1729 return dt_clip;
1730}
1731
1732
1733void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
1734 const LLHeavenBody& HB)
1735{
1736 const LLVector3 &look_at = gCamera->getAtAxis();
1737 // const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.001f;
1738 // gWorldPointer->getWaterHeight() + 0.001f;
1739
1740 LLVector3 to_dir = HB.getDirection();
1741 LLVector3 hb_pos = to_dir * (HORIZON_DIST - 10);
1742 LLVector3 to_dir_proj = to_dir;
1743 to_dir_proj.mV[VZ] = 0;
1744 to_dir_proj.normVec();
1745
1746 LLVector3 Right = to_dir % LLVector3::z_axis;
1747 LLVector3 Up = Right % to_dir;
1748 Right.normVec();
1749 Up.normVec();
1750
1751 // finding angle between look direction and sprite.
1752 LLVector3 look_at_right = look_at % LLVector3::z_axis;
1753 look_at_right.normVec();
1754
1755 const static F32 cos_horizon_angle = cosHorizon(0.0f/sResolution);
1756 //const static F32 horizon_angle = acos(cos_horizon_angle);
1757
1758 const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
1759 F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
1760 F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
1761
1762 F32 vert_size = vert_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
1763 Right *= /*cos_lookAt_toDir */ horiz_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
1764 Up *= vert_size;
1765
1766 LLVector3 v_corner[2];
1767 LLVector3 stretch_corner[2];
1768
1769 LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up;
1770 v_corner[1] = stretch_corner[1] = hb_pos - Right - Up;
1771
1772 F32 dt_hor, dt;
1773 dt_hor = clip_side_to_horizon(v_corner[1], v_corner[0], cos_horizon_angle);
1774
1775 LLVector2 TEX0t = TEX00;
1776 LLVector2 TEX1t = TEX10;
1777 LLVector3 lower_corner = v_corner[1];
1778
1779 if ((dt_hor > 0) && (dt_hor < 1))
1780 {
1781 TEX0t = LLVector2(0, dt_hor);
1782 TEX1t = LLVector2(1, dt_hor);
1783 lower_corner = (1 - dt_hor) * v_corner[1] + dt_hor * v_corner[0];
1784 }
1785 else
1786 dt_hor = llmax(0.0f, llmin(1.0f, dt_hor));
1787
1788 top_hb.normVec();
1789 const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]);
1790 const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view);
1791
1792 const S32 cols = 1;
1793 const S32 raws = lltrunc(16 * extension);
1794 S32 quads = cols * raws;
1795
1796 stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner);
1797 stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner);
1798
1799 dt = dt_hor;
1800
1801
1802 F32 cos_dir_from_top[2];
1803
1804 LLVector3 dir = stretch_corner[0];
1805 dir.normVec();
1806 cos_dir_from_top[0] = dir.mV[VZ];
1807
1808 dir = stretch_corner[1];
1809 dir.normVec();
1810 cos_dir_from_top[1] = dir.mV[VZ];
1811
1812 const F32 sin_dir_from_top = sqrt(1 - cos_dir_from_top[0] * cos_dir_from_top[0]);
1813 const F32 sin_dir_from_top2 = sqrt(1 - cos_dir_from_top[1] * cos_dir_from_top[1]);
1814 const F32 cos_diff_dir = cos_dir_from_top[0] * cos_dir_from_top[1]
1815 + sin_dir_from_top * sin_dir_from_top2;
1816 const F32 diff_angl_dir = acos(cos_diff_dir);
1817
1818 v_corner[0] = stretch_corner[0];
1819 v_corner[1] = lower_corner;
1820
1821
1822 LLVector2 TEX0tt = TEX01;
1823 LLVector2 TEX1tt = TEX11;
1824
1825 LLVector3 v_refl_corner[4];
1826 LLVector3 v_sprite_corner[4];
1827
1828 S32 vtx;
1829 for (vtx = 0; vtx < 2; ++vtx)
1830 {
1831 LLVector3 light_proj = v_corner[vtx];
1832 light_proj.normVec();
1833
1834 const F32 z = light_proj.mV[VZ];
1835 const F32 sin_angle = sqrt(1 - z * z);
1836 light_proj *= 1.f / sin_angle;
1837 light_proj.mV[VZ] = 0;
1838 const F32 to_refl_point = H * sin_angle / fabs(z);
1839
1840 v_refl_corner[vtx] = to_refl_point * light_proj;
1841 }
1842
1843
1844 for (vtx = 2; vtx < 4; ++vtx)
1845 {
1846 const LLVector3 to_dir_vec = (to_dir_proj * v_refl_corner[vtx-2]) * to_dir_proj;
1847 v_refl_corner[vtx] = v_refl_corner[vtx-2] + 2 * (to_dir_vec - v_refl_corner[vtx-2]);
1848 }
1849
1850 for (vtx = 0; vtx < 4; ++vtx)
1851 v_refl_corner[vtx].mV[VZ] -= H;
1852
1853 S32 side = 0;
1854 LLVector3 refl_corn_norm[2];
1855 refl_corn_norm[0] = v_refl_corner[1];
1856 refl_corn_norm[0].normVec();
1857 refl_corn_norm[1] = v_refl_corner[3];
1858 refl_corn_norm[1].normVec();
1859
1860 F32 cos_refl_look_at[2];
1861 cos_refl_look_at[0] = refl_corn_norm[0] * look_at;
1862 cos_refl_look_at[1] = refl_corn_norm[1] * look_at;
1863
1864 if (cos_refl_look_at[1] > cos_refl_look_at[0])
1865 {
1866 side = 2;
1867 }
1868
1869 //const F32 far_clip = (gCamera->getFar() - 0.01) / far_clip_factor;
1870 const F32 far_clip = 512;
1871 const F32 far_clip2 = far_clip*far_clip;
1872
1873 F32 dt_clip;
1874 F32 vtx_near2, vtx_far2;
1875
1876 if ((vtx_far2 = v_refl_corner[side].magVecSquared()) > far_clip2)
1877 {
1878 // whole thing is sprite: reflection is beyond far clip plane.
1879 dt_clip = 1.1f;
1880 quads = 1;
1881 }
1882 else if ((vtx_near2 = v_refl_corner[side+1].magVecSquared()) > far_clip2)
1883 {
1884 // part is reflection, the rest is sprite.
1885 dt_clip = dtClip(v_refl_corner[side + 1], v_refl_corner[side], far_clip2);
1886 const LLVector3 P = (1 - dt_clip) * v_refl_corner[side + 1] + dt_clip * v_refl_corner[side];
1887
1888 F32 dt_tex = dtReflection(P, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
1889
1890 dt = dt_tex;
1891 TEX0tt = LLVector2(0, dt);
1892 TEX1tt = LLVector2(1, dt);
1893 quads++;
1894 }
1895 else
1896 {
1897 // whole thing is correct reflection.
1898 dt_clip = -0.1f;
1899 }
1900
1901 LLStrider<LLVector3> verticesp;
1902 LLStrider<LLVector3> normalsp;
1903 LLStrider<LLVector2> texCoordsp;
1904 U32 *indicesp;
1905 S32 index_offset;
1906 LLFace *face = mFace[FACE_REFLECTION];
1907
1908 face->setPrimType(LLTriangles);
1909 face->setSize(quads * 4, quads * 6);
1910 index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1911 if (-1 == index_offset)
1912 {
1913 return;
1914 }
1915
1916 LLColor3 hb_col3 = HB.getInterpColor();
1917 hb_col3.clamp();
1918 const LLColor4 hb_col = LLColor4(hb_col3);
1919
1920 const F32 min_attenuation = 0.4f;
1921 const F32 max_attenuation = 0.7f;
1922 const F32 attenuation = min_attenuation
1923 + cos_angle_of_view * (max_attenuation - min_attenuation);
1924
1925 LLColor4 hb_refl_col = (1-attenuation) * hb_col + attenuation * mFogColor;
1926 face->setFaceColor(hb_refl_col);
1927
1928 LLVector3 v_far[2];
1929 v_far[0] = v_refl_corner[1];
1930 v_far[1] = v_refl_corner[3];
1931
1932 if(dt_clip > 0)
1933 {
1934 if (dt_clip >= 1)
1935 {
1936 for (S32 vtx = 0; vtx < 4; ++vtx)
1937 {
1938 F32 ratio = far_clip / v_refl_corner[vtx].magVec();
1939 *(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent;
1940 }
1941 const LLVector3 draw_pos = 0.25 *
1942 (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
1943 face->mCenterAgent = draw_pos;
1944 }
1945 else
1946 {
1947 F32 ratio = far_clip / v_refl_corner[1].magVec();
1948 v_sprite_corner[1] = v_refl_corner[1] * ratio;
1949
1950 ratio = far_clip / v_refl_corner[3].magVec();
1951 v_sprite_corner[3] = v_refl_corner[3] * ratio;
1952
1953 v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0];
1954 v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2];
1955 v_sprite_corner[0] = v_refl_corner[1];
1956 v_sprite_corner[2] = v_refl_corner[3];
1957
1958 for (S32 vtx = 0; vtx < 4; ++vtx)
1959 {
1960 *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent;
1961 }
1962
1963 const LLVector3 draw_pos = 0.25 *
1964 (v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]);
1965 face->mCenterAgent = draw_pos;
1966 }
1967
1968 *(texCoordsp++) = TEX0tt;
1969 *(texCoordsp++) = TEX0t;
1970 *(texCoordsp++) = TEX1tt;
1971 *(texCoordsp++) = TEX1t;
1972
1973 *indicesp++ = index_offset + 0;
1974 *indicesp++ = index_offset + 2;
1975 *indicesp++ = index_offset + 1;
1976
1977 *indicesp++ = index_offset + 1;
1978 *indicesp++ = index_offset + 2;
1979 *indicesp++ = index_offset + 3;
1980
1981 index_offset += 4;
1982 }
1983
1984 if (dt_clip < 1)
1985 {
1986 if (dt_clip <= 0)
1987 {
1988 const LLVector3 draw_pos = 0.25 *
1989 (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
1990 face->mCenterAgent = draw_pos;
1991 }
1992
1993 const F32 raws_inv = 1.f/raws;
1994 const F32 cols_inv = 1.f/cols;
1995 LLVector3 left = v_refl_corner[0] - v_refl_corner[1];
1996 LLVector3 right = v_refl_corner[2] - v_refl_corner[3];
1997 left *= raws_inv;
1998 right *= raws_inv;
1999
2000 F32 dt_raw = dt;
2001
2002 for (S32 raw = 0; raw < raws; ++raw)
2003 {
2004 F32 dt_v0 = raw * raws_inv;
2005 F32 dt_v1 = (raw + 1) * raws_inv;
2006 const LLVector3 BL = v_refl_corner[1] + (F32)raw * left;
2007 const LLVector3 BR = v_refl_corner[3] + (F32)raw * right;
2008 const LLVector3 EL = BL + left;
2009 const LLVector3 ER = BR + right;
2010 dt_v0 = dt_raw;
2011 dt_raw = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
2012 for (S32 col = 0; col < cols; ++col)
2013 {
2014 F32 dt_h0 = col * cols_inv;
2015 *(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent;
2016 *(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent;
2017 F32 dt_h1 = (col + 1) * cols_inv;
2018 *(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent;
2019 *(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent;
2020
2021 *(texCoordsp++) = LLVector2(dt_h0, dt_v1);
2022 *(texCoordsp++) = LLVector2(dt_h0, dt_v0);
2023 *(texCoordsp++) = LLVector2(dt_h1, dt_v1);
2024 *(texCoordsp++) = LLVector2(dt_h1, dt_v0);
2025
2026 *indicesp++ = index_offset + 0;
2027 *indicesp++ = index_offset + 2;
2028 *indicesp++ = index_offset + 1;
2029
2030 *indicesp++ = index_offset + 1;
2031 *indicesp++ = index_offset + 2;
2032 *indicesp++ = index_offset + 3;
2033
2034 index_offset += 4;
2035 }
2036 }
2037 }
2038}
2039
2040
2041
2042
2043void LLVOSky::updateFog(const F32 distance)
2044{
2045 if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG))
2046 {
2047 /*gGLSFog.addCap(GL_FOG, FALSE);
2048 gGLSPipeline.addCap(GL_FOG, FALSE);
2049 gGLSPipelineAlpha.addCap(GL_FOG, FALSE);
2050 gGLSPipelinePixieDust.addCap(GL_FOG, FALSE);
2051 gGLSPipelineSelection.addCap(GL_FOG, FALSE);
2052 gGLSPipelineAvatar.addCap(GL_FOG, FALSE);
2053 gGLSPipelineAvatarAlphaOnePass.addCap(GL_FOG, FALSE);
2054 gGLSPipelineAvatarAlphaPass1.addCap(GL_FOG, FALSE);
2055 gGLSPipelineAvatarAlphaPass2.addCap(GL_FOG, FALSE);
2056 gGLSPipelineAvatarAlphaPass3.addCap(GL_FOG, FALSE);*/
2057 glFogf(GL_FOG_DENSITY, 0);
2058 glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV);
2059 glFogf(GL_FOG_END, 1000000.f);
2060 return;
2061 }
2062 else
2063 {
2064 /*gGLSFog.addCap(GL_FOG, TRUE);
2065 gGLSPipeline.addCap(GL_FOG, TRUE);
2066 gGLSPipelineAlpha.addCap(GL_FOG, TRUE);
2067 gGLSPipelinePixieDust.addCap(GL_FOG, TRUE);
2068 gGLSPipelineSelection.addCap(GL_FOG, TRUE);
2069 if (!gGLManager.mIsATI)
2070 {
2071 gGLSPipelineAvatar.addCap(GL_FOG, TRUE);
2072 gGLSPipelineAvatarAlphaOnePass.addCap(GL_FOG, TRUE);
2073 gGLSPipelineAvatarAlphaPass1.addCap(GL_FOG, TRUE);
2074 gGLSPipelineAvatarAlphaPass2.addCap(GL_FOG, TRUE);
2075 gGLSPipelineAvatarAlphaPass3.addCap(GL_FOG, TRUE);
2076 }*/
2077 }
2078
2079 const BOOL hide_clip_plane = TRUE;
2080 LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f);
2081
2082 const F32 water_height = gAgent.getRegion()->getWaterHeight();
2083 // gWorldPointer->getWaterHeight();
2084 F32 camera_height = gAgent.getCameraPositionAgent().mV[2];
2085
2086 F32 near_clip_height = gCamera->getAtAxis().mV[VZ] * gCamera->getNear();
2087 camera_height += near_clip_height;
2088
2089 F32 fog_distance = 0.f;
2090 LLColor3 res_color[3];
2091
2092 LLColor3 sky_fog_color = LLColor3::white;
2093 LLColor3 render_fog_color = LLColor3::white;
2094
2095 LLColor3 transp;
2096 LLVector3 tosun = getToSunLast();
2097 const F32 tosun_z = tosun.mV[VZ];
2098 tosun.mV[VZ] = 0.f;
2099 tosun.normVec();
2100 LLVector3 perp_tosun;
2101 perp_tosun.mV[VX] = -tosun.mV[VY];
2102 perp_tosun.mV[VY] = tosun.mV[VX];
2103 LLVector3 tosun_45 = tosun + perp_tosun;
2104 tosun_45.normVec();
2105
2106 F32 delta = 0.06f;
2107 tosun.mV[VZ] = delta;
2108 perp_tosun.mV[VZ] = delta;
2109 tosun_45.mV[VZ] = delta;
2110 tosun.normVec();
2111 perp_tosun.normVec();
2112 tosun_45.normVec();
2113
2114 // Sky colors, just slightly above the horizon in the direction of the sun, perpendicular to the sun, and at a 45 degree angle to the sun.
2115 calcSkyColorInDir(res_color[0],transp, tosun);
2116 calcSkyColorInDir(res_color[1],transp, perp_tosun);
2117 calcSkyColorInDir(res_color[2],transp, tosun_45);
2118
2119 sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]);
2120
2121 F32 full_off = -0.25f;
2122 F32 full_on = 0.00f;
2123 F32 on = (tosun_z - full_off) / (full_on - full_off);
2124 on = llclamp(on, 0.01f, 1.f);
2125 sky_fog_color *= 0.5f * on;
2126
2127
2128 // We need to clamp these to non-zero, in order for the gamma correction to work. 0^y = ???
2129 S32 i;
2130 for (i = 0; i < 3; i++)
2131 {
2132 sky_fog_color.mV[i] = llmax(0.0001f, sky_fog_color.mV[i]);
2133 }
2134
2135 color_gamma_correct(sky_fog_color);
2136
2137 if (!(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) > LLDrawPool::SHADER_LEVEL_SCATTERING))
2138 {
2139 render_fog_color = sky_fog_color;
2140 }
2141
2142 if (camera_height > water_height)
2143 {
2144 fog_distance = mFogRatio * distance;
2145 LLColor4 fog(render_fog_color);
2146 glFogfv(GL_FOG_COLOR, fog.mV);
2147 }
2148 else
2149 {
2150 // Interpolate between sky fog and water fog...
2151 F32 depth = water_height - camera_height;
2152 F32 depth_frac = 1.f/(1.f + 200.f*depth);
2153 F32 color_frac = 1.f/(1.f + 0.5f* depth)* 0.2f;
2154 fog_distance = (mFogRatio * distance) * depth_frac + 30.f * (1.f-depth_frac);
2155 fog_distance = llmin(75.f, fog_distance);
2156
2157 F32 brightness = 1.f/(1.f + 0.05f*depth);
2158 F32 sun_brightness = getSunDiffuseColor().magVec() * 0.3f;
2159 brightness = llmin(1.f, brightness);
2160 brightness = llmin(brightness, sun_brightness);
2161 color_frac = llmin(0.7f, color_frac);
2162
2163 LLColor4 fogCol = brightness * (color_frac * render_fog_color + (1.f - color_frac) * LLColor4(0.f, 0.2f, 0.3f, 1.f));
2164 fogCol.setAlpha(1);
2165 glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
2166 }
2167
2168 mFogColor = sky_fog_color;
2169 mFogColor.setAlpha(1);
2170 LLGLSFog gls_fog;
2171
2172 F32 fog_density;
2173 if (hide_clip_plane)
2174 {
2175 // For now, set the density to extend to the cull distance.
2176 const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f)))
2177 fog_density = f_log/fog_distance;
2178 glFogi(GL_FOG_MODE, GL_EXP2);
2179 }
2180 else
2181 {
2182 const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f))
2183 fog_density = (f_log)/fog_distance;
2184 glFogi(GL_FOG_MODE, GL_EXP);
2185 }
2186
2187 glFogf(GL_FOG_END, fog_distance*2.2f);
2188
2189 glFogf(GL_FOG_DENSITY, fog_density);
2190
2191 glHint(GL_FOG_HINT, GL_NICEST);
2192 stop_glerror();
2193}
2194
2195// static
2196void LLHaze::initClass()
2197{
2198 sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel();
2199}
2200
2201
2202
2203// Functions used a lot.
2204
2205
2206F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
2207{
2208 F32 mv = color_max(col);
2209 if (0 == mv)
2210 {
2211 return 0;
2212 }
2213
2214 col *= 1.f / mv;
2215 color_pow(col, e);
2216 if (postmultiply)
2217 {
2218 col *= mv;
2219 }
2220 return mv;
2221}
2222
2223// Returns angle (RADIANs) between the horizontal projection of "v" and the x_axis.
2224// Range of output is 0.0f to 2pi //359.99999...f
2225// Returns 0.0f when "v" = +/- z_axis.
2226F32 azimuth(const LLVector3 &v)
2227{
2228 F32 azimuth = 0.0f;
2229 if (v.mV[VX] == 0.0f)
2230 {
2231 if (v.mV[VY] > 0.0f)
2232 {
2233 azimuth = F_PI * 0.5f;
2234 }
2235 else if (v.mV[VY] < 0.0f)
2236 {
2237 azimuth = F_PI * 1.5f;// 270.f;
2238 }
2239 }
2240 else
2241 {
2242 azimuth = (F32) atan(v.mV[VY] / v.mV[VX]);
2243 if (v.mV[VX] < 0.0f)
2244 {
2245 azimuth += F_PI;
2246 }
2247 else if (v.mV[VY] < 0.0f)
2248 {
2249 azimuth += F_PI * 2;
2250 }
2251 }
2252 return azimuth;
2253}
2254
2255
2256#if 0
2257// Not currently used
2258LLColor3 LLVOSky::calcGroundFog(LLColor3& transp, const LLVector3 &view_dir, F32 obj_dist) const
2259{
2260 LLColor3 col;
2261 calcGroundFog(col, transp, view_dir, obj_dist);
2262 col *= mBrightnessScaleGuess;
2263 return col;
2264}
2265#endif
2266
2267void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
2268{
2269 LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir;
2270 sun_direction.normVec();
2271 F32 dp = mSun.getDirection() * sun_direction;
2272 mSun.setDirection(sun_direction);
2273 mSun.setAngularVelocity(sun_ang_velocity);
2274 mMoon.setDirection(-sun_direction);
2275 if (dp < 0.995f) { //the sun jumped a great deal, update immediately
2276 updateHaze();
2277 mWeatherChange = FALSE;
2278 mForceUpdate = TRUE;
2279 }
2280 else if (mWeatherChange && (mSun.getDirection().mV[VZ] > -0.5) )
2281 {
2282 updateHaze();
2283 init();
2284 mWeatherChange = FALSE;
2285 }
2286 else if (mSun.getDirection().mV[VZ] < -0.5)
2287 {
2288 mWeatherChange = TRUE;
2289 }
2290}
2291
2292#define INV_WAVELENGTH_R_POW4 (1.f/0.2401f) // = 1/0.7^4
2293#define INV_WAVELENGTH_G_POW4 (1.f/0.0789f) // = 1/0.53^4
2294#define INV_WAVELENGTH_B_POW4 (1.f/0.03748f) // = 1/0.44^4
2295
2296// Dummy class for globals used below. Replace when KILLERSKY is merged in.
2297class LLKillerSky
2298{
2299public:
2300 static F32 sRaleighGroundDensity;
2301 static F32 sMieFactor;
2302 static F32 sNearFalloffFactor;
2303 static F32 sSkyContrib;
2304
2305 static void getRaleighCoefficients(float eye_sun_dp, float density, float *coefficients)
2306 {
2307 float dp = eye_sun_dp;
2308 float angle_dep = density*(1 + dp*dp);
2309 coefficients[0] = angle_dep * INV_WAVELENGTH_R_POW4;
2310 coefficients[1] = angle_dep * INV_WAVELENGTH_G_POW4;
2311 coefficients[2] = angle_dep * INV_WAVELENGTH_B_POW4;
2312 }
2313
2314 static void getMieCoefficients(float eye_sun_dp, float density, float *coefficient)
2315 {
2316 // TOTALLY ARBITRARY FUNCTION. Seems to work though
2317 // If anyone can replace this with some *actual* mie function, that'd be great
2318 float dp = eye_sun_dp;
2319 float dp_highpower = dp*dp;
2320 float angle_dep = density * (llclamp(dp_highpower*dp, 0.f, 1.f) + 0.4f);
2321 *coefficient = angle_dep;
2322 }
2323};
2324
2325F32 LLKillerSky::sRaleighGroundDensity = 0.013f;
2326F32 LLKillerSky::sMieFactor = 50;
2327F32 LLKillerSky::sNearFalloffFactor = 1.5f;
2328F32 LLKillerSky::sSkyContrib = 0.06f;
2329
2330void LLVOSky::generateScatterMap()
2331{
2332 float raleigh[3], mie;
2333
2334 mScatterMap = new LLImageGL(FALSE);
2335 mScatterMapRaw = new LLImageRaw(256, 256, 4);
2336 U8 *data = mScatterMapRaw->getData();
2337
2338 F32 light_brightness = gSky.getSunDirection().mV[VZ]+0.1f;
2339 LLColor4 light_color;
2340 LLColor4 sky_color;
2341 if (light_brightness > 0)
2342 {
2343 F32 interp = sqrtf(light_brightness);
2344 light_brightness = sqrt(sqrtf(interp));
2345 light_color = lerp(gSky.getSunDiffuseColor(), LLColor4(1,1,1,1), interp) * light_brightness;
2346 sky_color = lerp(LLColor4(0,0,0,0), LLColor4(0.4f, 0.6f, 1.f, 1.f), light_brightness)*LLKillerSky::sSkyContrib;
2347 }
2348 else
2349 {
2350 light_brightness = /*0.3f*/sqrt(-light_brightness);
2351 light_color = gSky.getMoonDiffuseColor() * light_brightness;
2352 sky_color = LLColor4(0,0,0,1);
2353 }
2354
2355 // x = distance [0..1024m]
2356 // y = dot product [-1,1]
2357 for (int y=0;y<256;y++)
2358 {
2359 // Accumulate outward
2360 float accum_r = 0, accum_g = 0, accum_b = 0;
2361
2362 float dp = (((float)y)/255.f)*1.95f - 0.975f;
2363 U8 *scanline = &data[y*256*4];
2364 for (int x=0;x<256;x++)
2365 {
2366 float dist = ((float)x+1)*4; // x -> 2048
2367
2368 float raleigh_density = LLKillerSky::sRaleighGroundDensity * 0.05f; // Arbitrary? Perhaps...
2369 float mie_density = raleigh_density*LLKillerSky::sMieFactor;
2370
2371 float extinction_factor = dist/LLKillerSky::sNearFalloffFactor;
2372
2373 LLKillerSky::getRaleighCoefficients(dp, raleigh_density, raleigh);
2374 LLKillerSky::getMieCoefficients(dp, mie_density, &mie);
2375
2376 float falloff_r = pow(llclamp(0.985f-raleigh[0],0.f,1.f), extinction_factor);
2377 float falloff_g = pow(llclamp(0.985f-raleigh[1],0.f,1.f), extinction_factor);
2378 float falloff_b = pow(llclamp(0.985f-raleigh[2],0.f,1.f), extinction_factor);
2379
2380 float light_r = light_color.mV[0] * (raleigh[0]+mie+sky_color.mV[0]) * falloff_r;
2381 float light_g = light_color.mV[1] * (raleigh[1]+mie+sky_color.mV[1]) * falloff_g;
2382 float light_b = light_color.mV[2] * (raleigh[2]+mie+sky_color.mV[2]) * falloff_b;
2383
2384 accum_r += light_r;
2385 accum_g += light_g;
2386 accum_b += light_b;
2387
2388 scanline[x*4] = (U8)llclamp(accum_r*255.f, 0.f, 255.f);
2389 scanline[x*4+1] = (U8)llclamp(accum_g*255.f, 0.f, 255.f);
2390 scanline[x*4+2] = (U8)llclamp(accum_b*255.f, 0.f, 255.f);
2391 float alpha = ((falloff_r+falloff_g+falloff_b)*0.33f);
2392 scanline[x*4+3] = (U8)llclamp(alpha*255.f, 0.f, 255.f); // Avg falloff
2393
2394 // Output color Co, Input color Ci, Map channels Mrgb, Ma:
2395 // Co = (Ci * Ma) + Mrgb
2396 }
2397 }
2398
2399 mScatterMap->createGLTexture(0, mScatterMapRaw);
2400 mScatterMap->bind(0);
2401 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2402 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2403}
2404
2405#if 0
2406// Not currently used
2407void LLVOSky::calcGroundFog(LLColor3& res, LLColor3& transp, const LLVector3 view_dir, F32 obj_dist) const
2408{
2409 const LLVector3& tosun = getToSunLast();//use_old_value ? sunDir() : toSunLast();
2410 res.setToBlack();
2411 transp.setToWhite();
2412 const F32 dist = obj_dist * mWorldScale;
2413
2414 //LLVector3 view_dir = gCamera->getAtAxis();
2415
2416 const F32 cos_dir = view_dir * tosun;
2417 LLVector3 dir = view_dir;
2418 LLVector3 virtual_P = mCameraPosAgent + dist * dir;
2419
2420 if (dir.mV[VZ] < 0)
2421 {
2422 dir = -dir;
2423 }
2424
2425 const F32 z_dir = dir.mV[2];
2426
2427 const F32 h = mCameraPosAgent.mV[2];
2428
2429 transp = color_div(mTransp.calcTransp(dir * calcUpVec(virtual_P), 0),
2430 mTransp.calcTransp(z_dir, h));
2431
2432 if (calcHitsEarth(mCameraPosAgent, tosun) > 0)
2433 {
2434 const F32 avg = llmin(1.f, 1.2f * color_avg(transp));
2435 transp = LLColor3(avg, avg, avg);
2436 return;
2437 }
2438
2439 LLColor3 haze_sca_opt_depth = mHaze.getSigSca();
2440 LLColor3 sun_transp;
2441 mTransp.calcTransp(tosun.mV[2], -0.1f, sun_transp);
2442
2443 res = calcAirPhaseFunc(cos_dir) * LLHaze::getAirScaSeaLevel();
2444 res += mHaze.calcPhase(cos_dir) * mHaze.getSigSca();
2445 res = mSun.getIntensity() * dist * sun_transp * res;
2446}
2447
2448#endif