PageRenderTime 257ms CodeModel.GetById 12ms app.highlight 222ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llvosky.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2287 lines | 1726 code | 405 blank | 156 comment | 182 complexity | 21e683142957bd34200da12e121ccd81 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llvosky.cpp
   3 * @brief LLVOSky class implementation
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llvosky.h"
  30
  31#include "imageids.h"
  32#include "llfeaturemanager.h"
  33#include "llviewercontrol.h"
  34#include "llframetimer.h"
  35#include "timing.h"
  36
  37#include "llagent.h"
  38#include "llagentcamera.h"
  39#include "lldrawable.h"
  40#include "llface.h"
  41#include "llcubemap.h"
  42#include "lldrawpoolsky.h"
  43#include "lldrawpoolwater.h"
  44#include "llglheaders.h"
  45#include "llsky.h"
  46#include "llviewercamera.h"
  47#include "llviewertexturelist.h"
  48#include "llviewerobjectlist.h"
  49#include "llviewerregion.h"
  50#include "llworld.h"
  51#include "pipeline.h"
  52#include "lldrawpoolwlsky.h"
  53#include "llwlparammanager.h"
  54#include "llwaterparammanager.h"
  55
  56#undef min
  57#undef max
  58
  59static const S32 NUM_TILES_X = 8;
  60static const S32 NUM_TILES_Y = 4;
  61static const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
  62
  63// Heavenly body constants
  64static const F32 SUN_DISK_RADIUS	= 0.5f;
  65static const F32 MOON_DISK_RADIUS	= SUN_DISK_RADIUS * 0.9f;
  66static const F32 SUN_INTENSITY = 1e5;
  67static const F32 SUN_DISK_INTENSITY = 24.f;
  68
  69
  70// Texture coordinates:
  71static const LLVector2 TEX00 = LLVector2(0.f, 0.f);
  72static const LLVector2 TEX01 = LLVector2(0.f, 1.f);
  73static const LLVector2 TEX10 = LLVector2(1.f, 0.f);
  74static const LLVector2 TEX11 = LLVector2(1.f, 1.f);
  75
  76// Exported globals
  77LLUUID gSunTextureID = IMG_SUN;
  78LLUUID gMoonTextureID = IMG_MOON;
  79
  80class LLFastLn
  81{
  82public:
  83	LLFastLn() 
  84	{
  85		mTable[0] = 0;
  86		for( S32 i = 1; i < 257; i++ )
  87		{
  88			mTable[i] = log((F32)i);
  89		}
  90	}
  91
  92	F32 ln( F32 x )
  93	{
  94		const F32 OO_255 = 0.003921568627450980392156862745098f;
  95		const F32 LN_255 = 5.5412635451584261462455391880218f;
  96
  97		if( x < OO_255 )
  98		{
  99			return log(x);
 100		}
 101		else
 102		if( x < 1 )
 103		{
 104			x *= 255.f;
 105			S32 index = llfloor(x);
 106			F32 t = x - index;
 107			F32 low = mTable[index];
 108			F32 high = mTable[index + 1];
 109			return low + t * (high - low) - LN_255;
 110		}
 111		else
 112		if( x <= 255 )
 113		{
 114			S32 index = llfloor(x);
 115			F32 t = x - index;
 116			F32 low = mTable[index];
 117			F32 high = mTable[index + 1];
 118			return low + t * (high - low);
 119		}
 120		else
 121		{
 122			return log( x );
 123		}
 124	}
 125
 126	F32 pow( F32 x, F32 y )
 127	{
 128		return (F32)LL_FAST_EXP(y * ln(x));
 129	}
 130
 131
 132private:
 133	F32 mTable[257]; // index 0 is unused
 134};
 135
 136static LLFastLn gFastLn;
 137
 138
 139// Functions used a lot.
 140
 141inline F32 LLHaze::calcPhase(const F32 cos_theta) const
 142{
 143	const F32 g2 = mG * mG;
 144	const F32 den = 1 + g2 - 2 * mG * cos_theta;
 145	return (1 - g2) * gFastLn.pow(den, -1.5);
 146}
 147
 148inline void color_pow(LLColor3 &col, const F32 e)
 149{
 150	col.mV[0] = gFastLn.pow(col.mV[0], e);
 151	col.mV[1] = gFastLn.pow(col.mV[1], e);
 152	col.mV[2] = gFastLn.pow(col.mV[2], e);
 153}
 154
 155inline LLColor3 color_norm(const LLColor3 &col)
 156{
 157	const F32 m = color_max(col);
 158	if (m > 1.f)
 159	{
 160		return 1.f/m * col;
 161	}
 162	else return col;
 163}
 164
 165inline void color_gamma_correct(LLColor3 &col)
 166{
 167	const F32 gamma_inv = 1.f/1.2f;
 168	if (col.mV[0] != 0.f)
 169	{
 170		col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv);
 171	}
 172	if (col.mV[1] != 0.f)
 173	{
 174		col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv);
 175	}
 176	if (col.mV[2] != 0.f)
 177	{
 178		col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv);
 179	}
 180}
 181
 182static LLColor3 calc_air_sca_sea_level()
 183{
 184	static LLColor3 WAVE_LEN(675, 520, 445);
 185	static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
 186	static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
 187	static LLColor3 n4 = n21 * n21;
 188	static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
 189	static LLColor3 wl4 = wl2 * wl2;
 190	static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
 191	static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
 192	return dens_div_N * color_div ( mult_const, wl4 );
 193}
 194
 195// static constants.
 196LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level();
 197F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel);	
 198F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f;
 199
 200
 201/***************************************
 202		SkyTex
 203***************************************/
 204
 205S32 LLSkyTex::sComponents = 4;
 206S32 LLSkyTex::sResolution = 64;
 207F32 LLSkyTex::sInterpVal = 0.f;
 208S32 LLSkyTex::sCurrent = 0;
 209
 210
 211LLSkyTex::LLSkyTex() :
 212	mSkyData(NULL),
 213	mSkyDirs(NULL)
 214{
 215}
 216
 217void LLSkyTex::init()
 218{
 219	mSkyData = new LLColor4[sResolution * sResolution];
 220	mSkyDirs = new LLVector3[sResolution * sResolution];
 221
 222	for (S32 i = 0; i < 2; ++i)
 223	{
 224		mTexture[i] = LLViewerTextureManager::getLocalTexture(FALSE);
 225		mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
 226		mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents);
 227		
 228		initEmpty(i);
 229	}
 230}
 231
 232void LLSkyTex::cleanupGL()
 233{
 234	mTexture[0] = NULL;
 235	mTexture[1] = NULL;
 236}
 237
 238void LLSkyTex::restoreGL()
 239{
 240	for (S32 i = 0; i < 2; i++)
 241	{
 242		mTexture[i] = LLViewerTextureManager::getLocalTexture(FALSE);
 243		mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
 244	}
 245}
 246
 247LLSkyTex::~LLSkyTex()
 248{
 249	delete[] mSkyData;
 250	mSkyData = NULL;
 251
 252	delete[] mSkyDirs;
 253	mSkyDirs = NULL;
 254}
 255
 256
 257void LLSkyTex::initEmpty(const S32 tex)
 258{
 259	U8* data = mImageRaw[tex]->getData();
 260	for (S32 i = 0; i < sResolution; ++i)
 261	{
 262		for (S32 j = 0; j < sResolution; ++j)
 263		{
 264			const S32 basic_offset = (i * sResolution + j);
 265			S32 offset = basic_offset * sComponents;
 266			data[offset] = 0;
 267			data[offset+1] = 0;
 268			data[offset+2] = 0;
 269			data[offset+3] = 255;
 270
 271			mSkyData[basic_offset].setToBlack();
 272		}
 273	}
 274
 275	createGLImage(tex);
 276}
 277
 278void LLSkyTex::create(const F32 brightness)
 279{
 280	/// Brightness ignored for now.
 281	U8* data = mImageRaw[sCurrent]->getData();
 282	for (S32 i = 0; i < sResolution; ++i)
 283	{
 284		for (S32 j = 0; j < sResolution; ++j)
 285		{
 286			const S32 basic_offset = (i * sResolution + j);
 287			S32 offset = basic_offset * sComponents;
 288			U32* pix = (U32*)(data + offset);
 289			LLColor4U temp = LLColor4U(mSkyData[basic_offset]);
 290			*pix = temp.mAll;
 291		}
 292	}
 293	createGLImage(sCurrent);
 294}
 295
 296
 297
 298
 299void LLSkyTex::createGLImage(S32 which)
 300{	
 301	mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL);
 302	mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP);
 303}
 304
 305void LLSkyTex::bindTexture(BOOL curr)
 306{
 307	gGL.getTexUnit(0)->bind(mTexture[getWhich(curr)], true);
 308}
 309
 310/***************************************
 311		Sky
 312***************************************/
 313
 314F32	LLHeavenBody::sInterpVal = 0;
 315
 316S32 LLVOSky::sResolution = LLSkyTex::getResolution();
 317S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X;
 318S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y;
 319
 320LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 321:	LLStaticViewerObject(id, pcode, regionp, TRUE),
 322	mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS),
 323	mBrightnessScale(1.f),
 324	mBrightnessScaleNew(0.f),
 325	mBrightnessScaleGuess(1.f),
 326	mWeatherChange(FALSE),
 327	mCloudDensity(0.2f),
 328	mWind(0.f),
 329	mForceUpdate(FALSE),
 330	mWorldScale(1.f),
 331	mBumpSunDir(0.f, 0.f, 1.f)
 332{
 333	bool error = false;
 334	
 335	/// WL PARAMS
 336	dome_radius = 1.f;
 337	dome_offset_ratio = 0.f;
 338	sunlight_color = LLColor3();
 339	ambient = LLColor3();
 340	gamma = 1.f;
 341	lightnorm = LLVector4();
 342	blue_density = LLColor3();
 343	blue_horizon = LLColor3();
 344	haze_density = 0.f;
 345	haze_horizon = LLColor3();
 346	density_multiplier = 0.f;
 347	max_y = 0.f;
 348	glow = LLColor3();
 349	cloud_shadow = 0.f;
 350	cloud_color = LLColor3();
 351	cloud_scale = 0.f;
 352	cloud_pos_density1 = LLColor3();
 353	cloud_pos_density2 = LLColor3();
 354
 355	mInitialized = FALSE;
 356	mbCanSelect = FALSE;
 357	mUpdateTimer.reset();
 358
 359	for (S32 i = 0; i < 6; i++)
 360	{
 361		mSkyTex[i].init();
 362		mShinyTex[i].init();
 363	}
 364	for (S32 i=0; i<FACE_COUNT; i++)
 365	{
 366		mFace[i] = NULL;
 367	}
 368	
 369	mCameraPosAgent = gAgentCamera.getCameraPositionAgent();
 370	mAtmHeight = ATM_HEIGHT;
 371	mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
 372
 373	mSunDefaultPosition = LLVector3(LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error));
 374	if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition"))
 375	{
 376		initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0));
 377	}
 378	mAmbientScale = gSavedSettings.getF32("SkyAmbientScale");
 379	mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift");
 380	mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f;
 381	mFogColor.mV[VALPHA] = 0.0f;
 382	mFogRatio = 1.2f;
 383
 384	mSun.setIntensity(SUN_INTENSITY);
 385	mMoon.setIntensity(0.1f * SUN_INTENSITY);
 386
 387	mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
 388	mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 389	mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
 390	mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 391	mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
 392	mBloomTexturep->setNoDelete() ;
 393	mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 394
 395	mHeavenlyBodyUpdated = FALSE ;
 396
 397	mDrawRefl = 0;
 398	mHazeConcentration = 0.f;
 399	mInterpVal = 0.f;
 400}
 401
 402
 403LLVOSky::~LLVOSky()
 404{
 405	// Don't delete images - it'll get deleted by gTextureList on shutdown
 406	// This needs to be done for each texture
 407
 408	mCubeMap = NULL;
 409}
 410
 411void LLVOSky::init()
 412{
 413   	const F32 haze_int = color_intens(mHaze.calcSigSca(0));
 414	mHazeConcentration = haze_int /
 415		(color_intens(LLHaze::calcAirSca(0)) + haze_int);
 416
 417	calcAtmospherics();
 418
 419	// Initialize the cached normalized direction vectors
 420	for (S32 side = 0; side < 6; ++side)
 421	{
 422		for (S32 tile = 0; tile < NUM_TILES; ++tile)
 423		{
 424			initSkyTextureDirs(side, tile);
 425			createSkyTexture(side, tile);
 426		}
 427	}
 428
 429	for (S32 i = 0; i < 6; ++i)
 430	{
 431		mSkyTex[i].create(1.0f);
 432		mShinyTex[i].create(1.0f);
 433	}
 434
 435	initCubeMap();
 436	mInitialized = true;
 437
 438	mHeavenlyBodyUpdated = FALSE ;
 439}
 440
 441void LLVOSky::initCubeMap() 
 442{
 443	std::vector<LLPointer<LLImageRaw> > images;
 444	for (S32 side = 0; side < 6; side++)
 445	{
 446		images.push_back(mShinyTex[side].getImageRaw());
 447	}
 448	if (mCubeMap)
 449	{
 450		mCubeMap->init(images);
 451	}
 452	else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
 453	{
 454		mCubeMap = new LLCubeMap();
 455		mCubeMap->init(images);
 456	}
 457	gGL.getTexUnit(0)->disable();
 458}
 459
 460
 461void LLVOSky::cleanupGL()
 462{
 463	S32 i;
 464	for (i = 0; i < 6; i++)
 465	{
 466		mSkyTex[i].cleanupGL();
 467	}
 468	if (getCubeMap())
 469	{
 470		getCubeMap()->destroyGL();
 471	}
 472}
 473
 474void LLVOSky::restoreGL()
 475{
 476	S32 i;
 477	for (i = 0; i < 6; i++)
 478	{
 479		mSkyTex[i].restoreGL();
 480	}
 481	mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
 482	mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 483	mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
 484	mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 485	mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
 486	mBloomTexturep->setNoDelete() ;
 487	mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 488
 489	calcAtmospherics();	
 490
 491	if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap
 492	    && LLCubeMap::sUseCubeMaps)
 493	{
 494		LLCubeMap* cube_map = getCubeMap();
 495
 496		std::vector<LLPointer<LLImageRaw> > images;
 497		for (S32 side = 0; side < 6; side++)
 498		{
 499			images.push_back(mShinyTex[side].getImageRaw());
 500		}
 501
 502		if(cube_map)
 503		{
 504			cube_map->init(images);
 505			mForceUpdate = TRUE;
 506		}
 507	}
 508
 509	if (mDrawable)
 510	{
 511		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 512	}
 513
 514}
 515
 516void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile)
 517{
 518	S32 tile_x = tile % NUM_TILES_X;
 519	S32 tile_y = tile / NUM_TILES_X;
 520
 521	S32 tile_x_pos = tile_x * sTileResX;
 522	S32 tile_y_pos = tile_y * sTileResY;
 523
 524	F32 coeff[3] = {0, 0, 0};
 525	const S32 curr_coef = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
 526	const S32 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
 527	const S32 x_coef = (curr_coef + 1) % 3;
 528	const S32 y_coef = (x_coef + 1) % 3;
 529
 530	coeff[curr_coef] = (F32)side_dir;
 531
 532	F32 inv_res = 1.f/sResolution;
 533	S32 x, y;
 534	for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
 535	{
 536		for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
 537		{
 538			coeff[x_coef] = F32((x<<1) + 1) * inv_res - 1.f;
 539			coeff[y_coef] = F32((y<<1) + 1) * inv_res - 1.f;
 540			LLVector3 dir(coeff[0], coeff[1], coeff[2]);
 541			dir.normalize();
 542			mSkyTex[side].setDir(dir, x, y);
 543			mShinyTex[side].setDir(dir, x, y);
 544		}
 545	}
 546}
 547
 548void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
 549{
 550	S32 tile_x = tile % NUM_TILES_X;
 551	S32 tile_y = tile / NUM_TILES_X;
 552
 553	S32 tile_x_pos = tile_x * sTileResX;
 554	S32 tile_y_pos = tile_y * sTileResY;
 555
 556	S32 x, y;
 557	for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
 558	{
 559		for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
 560		{
 561			mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y);
 562			mShinyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y), true), x, y);
 563		}
 564	}
 565}
 566
 567static inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
 568{
 569	return LLColor3(left.mV[0]/right.mV[0],
 570					 left.mV[1]/right.mV[1],
 571					 left.mV[2]/right.mV[2]);
 572}
 573
 574
 575static inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
 576{
 577	return LLColor3(left.mV[0]*right.mV[0],
 578					 left.mV[1]*right.mV[1],
 579					 left.mV[2]*right.mV[2]);
 580}
 581
 582
 583static inline LLColor3 componentExp(LLColor3 const &v)
 584{
 585	return LLColor3(exp(v.mV[0]),
 586					 exp(v.mV[1]),
 587					 exp(v.mV[2]));
 588}
 589
 590static inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
 591{
 592	return LLColor3(pow(v.mV[0], exponent),
 593					pow(v.mV[1], exponent),
 594					pow(v.mV[2], exponent));
 595}
 596
 597static inline LLColor3 componentSaturate(LLColor3 const &v)
 598{
 599	return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
 600					 std::max(std::min(v.mV[1], 1.f), 0.f),
 601					 std::max(std::min(v.mV[2], 1.f), 0.f));
 602}
 603
 604
 605static inline LLColor3 componentSqrt(LLColor3 const &v)
 606{
 607	return LLColor3(sqrt(v.mV[0]),
 608					 sqrt(v.mV[1]),
 609					 sqrt(v.mV[2]));
 610}
 611
 612static inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
 613{
 614	left.mV[0] *= right.mV[0];
 615	left.mV[1] *= right.mV[1];
 616	left.mV[2] *= right.mV[2];
 617}
 618
 619static inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
 620{
 621	return (left + ((right - left) * amount));
 622}
 623
 624static inline F32 texture2D(LLPointer<LLImageRaw> const & tex, LLVector2 const & uv)
 625{
 626	U16 w = tex->getWidth();
 627	U16 h = tex->getHeight();
 628
 629	U16 r = U16(uv[0] * w) % w;
 630	U16 c = U16(uv[1] * h) % h;
 631
 632	U8 const * imageBuffer = tex->getData();
 633
 634	U8 sample = imageBuffer[r * w + c];
 635
 636	return sample / 255.f;
 637}
 638
 639static inline LLColor3 smear(F32 val)
 640{
 641	return LLColor3(val, val, val);
 642}
 643
 644void LLVOSky::initAtmospherics(void)
 645{	
 646	bool error;
 647	
 648	// uniform parameters for convenience
 649	dome_radius = LLWLParamManager::getInstance()->getDomeRadius();
 650	dome_offset_ratio = LLWLParamManager::getInstance()->getDomeOffset();
 651	sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error));
 652	ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error));
 653	//lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error);
 654	gamma = LLWLParamManager::getInstance()->mCurParams.getVector("gamma", error)[0];
 655	blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error));
 656	blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error));
 657	haze_density = LLWLParamManager::getInstance()->mCurParams.getVector("haze_density", error)[0];
 658	haze_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("haze_horizon", error));
 659	density_multiplier = LLWLParamManager::getInstance()->mCurParams.getVector("density_multiplier", error)[0];
 660	max_y = LLWLParamManager::getInstance()->mCurParams.getVector("max_y", error)[0];
 661	glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error));
 662	cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_shadow", error)[0];
 663	cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error));
 664	cloud_scale = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_scale", error)[0];
 665	cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error));
 666	cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error));
 667
 668	// light norm is different.  We need the sun's direction, not the light direction
 669	// which could be from the moon.  And we need to clamp it
 670	// just like for the gpu
 671	LLVector3 sunDir = gSky.getSunDirection();
 672
 673	// CFR_TO_OGL
 674	lightnorm = LLVector4(sunDir.mV[1], sunDir.mV[2], sunDir.mV[0], 0);
 675	unclamped_lightnorm = lightnorm;
 676	if(lightnorm.mV[1] < -0.1f)
 677	{
 678		lightnorm.mV[1] = -0.1f;
 679	}
 680	
 681}
 682
 683LLColor4 LLVOSky::calcSkyColorInDir(const LLVector3 &dir, bool isShiny)
 684{
 685	F32 saturation = 0.3f;
 686	if (dir.mV[VZ] < -0.02f)
 687	{
 688		LLColor4 col = LLColor4(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.22f),0.f);
 689		if (isShiny)
 690		{
 691			LLColor3 desat_fog = LLColor3(mFogColor);
 692			F32 brightness = desat_fog.brightness();
 693			// So that shiny somewhat shows up at night.
 694			if (brightness < 0.15f)
 695			{
 696				brightness = 0.15f;
 697				desat_fog = smear(0.15f);
 698			}
 699			LLColor3 greyscale = smear(brightness);
 700			desat_fog = desat_fog * saturation + greyscale * (1.0f - saturation);
 701			if (!gPipeline.canUseWindLightShaders())
 702			{
 703				col = LLColor4(desat_fog, 0.f);
 704			}
 705			else 
 706			{
 707				col = LLColor4(desat_fog * 0.5f, 0.f);
 708			}
 709		}
 710		float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]);
 711		x *= x;
 712		col.mV[0] *= x*x;
 713		col.mV[1] *= powf(x, 2.5f);
 714		col.mV[2] *= x*x*x;
 715		return col;
 716	}
 717
 718	// undo OGL_TO_CFR_ROTATION and negate vertical direction.
 719	LLVector3 Pn = LLVector3(-dir[1] , -dir[2], -dir[0]);
 720
 721	LLColor3 vary_HazeColor(0,0,0);
 722	LLColor3 vary_CloudColorSun(0,0,0);
 723	LLColor3 vary_CloudColorAmbient(0,0,0);
 724	F32 vary_CloudDensity(0);
 725	LLVector2 vary_HorizontalProjection[2];
 726	vary_HorizontalProjection[0] = LLVector2(0,0);
 727	vary_HorizontalProjection[1] = LLVector2(0,0);
 728
 729	calcSkyColorWLVert(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient,
 730						vary_CloudDensity, vary_HorizontalProjection);
 731	
 732	LLColor3 sky_color =  calcSkyColorWLFrag(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient, 
 733								vary_CloudDensity, vary_HorizontalProjection);
 734	if (isShiny)
 735	{
 736		F32 brightness = sky_color.brightness();
 737		LLColor3 greyscale = smear(brightness);
 738		sky_color = sky_color * saturation + greyscale * (1.0f - saturation);
 739		sky_color *= (0.5f + 0.5f * brightness);
 740	}
 741	return LLColor4(sky_color, 0.0f);
 742}
 743
 744// turn on floating point precision
 745// in vs2003 for this function.  Otherwise
 746// sky is aliased looking 7:10 - 8:50
 747#if LL_MSVC && __MSVC_VER__ < 8
 748#pragma optimize("p", on)
 749#endif
 750
 751void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, 
 752							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
 753							LLVector2 vary_HorizontalProjection[2])
 754{
 755	// project the direction ray onto the sky dome.
 756	F32 phi = acos(Pn[1]);
 757	F32 sinA = sin(F_PI - phi);
 758	if (fabsf(sinA) < 0.01f)
 759	{ //avoid division by zero
 760		sinA = 0.01f;
 761	}
 762
 763	F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA;
 764
 765	Pn *= Plen;
 766
 767	vary_HorizontalProjection[0] = LLVector2(Pn[0], Pn[2]);
 768	vary_HorizontalProjection[0] /= - 2.f * Plen;
 769
 770	// Set altitude
 771	if (Pn[1] > 0.f)
 772	{
 773		Pn *= (max_y / Pn[1]);
 774	}
 775	else
 776	{
 777		Pn *= (-32000.f / Pn[1]);
 778	}
 779
 780	Plen = Pn.length();
 781	Pn /= Plen;
 782
 783	// Initialize temp variables
 784	LLColor3 sunlight = sunlight_color;
 785
 786	// Sunlight attenuation effect (hue and brightness) due to atmosphere
 787	// this is used later for sunlight modulation at various altitudes
 788	LLColor3 light_atten =
 789		(blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
 790
 791	// Calculate relative weights
 792	LLColor3 temp2(0.f, 0.f, 0.f);
 793	LLColor3 temp1 = blue_density + smear(haze_density);
 794	LLColor3 blue_weight = componentDiv(blue_density, temp1);
 795	LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
 796
 797	// Compute sunlight from P & lightnorm (for long rays like sky)
 798	temp2.mV[1] = llmax(F_APPROXIMATELY_ZERO, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] );
 799
 800	temp2.mV[1] = 1.f / temp2.mV[1];
 801	componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
 802
 803	// Distance
 804	temp2.mV[2] = Plen * density_multiplier;
 805
 806	// Transparency (-> temp1)
 807	temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
 808
 809
 810	// Compute haze glow
 811	temp2.mV[0] = Pn * LLVector3(lightnorm);
 812
 813	temp2.mV[0] = 1.f - temp2.mV[0];
 814		// temp2.x is 0 at the sun and increases away from sun
 815	temp2.mV[0] = llmax(temp2.mV[0], .001f);	
 816		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
 817	temp2.mV[0] *= glow.mV[0];
 818		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
 819	temp2.mV[0] = pow(temp2.mV[0], glow.mV[2]);
 820		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
 821
 822	// Add "minimum anti-solar illumination"
 823	temp2.mV[0] += .25f;
 824
 825
 826	// Haze color above cloud
 827	vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient)
 828				+ componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + ambient)
 829			 );	
 830
 831	// Increase ambient when there are more clouds
 832	LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f;
 833
 834	// Dim sunlight by cloud shadow percentage
 835	sunlight *= (1.f - cloud_shadow);
 836
 837	// Haze color below cloud
 838	LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
 839				+ componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + tmpAmbient)
 840			 );	
 841
 842	// Final atmosphere additive
 843	componentMultBy(vary_HazeColor, LLColor3::white - temp1);
 844
 845	sunlight = sunlight_color;
 846	temp2.mV[1] = llmax(0.f, lightnorm[1] * 2.f);
 847	temp2.mV[1] = 1.f / temp2.mV[1];
 848	componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
 849
 850	// Attenuate cloud color by atmosphere
 851	temp1 = componentSqrt(temp1);	//less atmos opacity (more transparency) below clouds
 852
 853	// At horizon, blend high altitude sky color towards the darker color below the clouds
 854	vary_HazeColor +=
 855		componentMult(additiveColorBelowCloud - vary_HazeColor, LLColor3::white - componentSqrt(temp1));
 856		
 857	if (Pn[1] < 0.f)
 858	{
 859		// Eric's original: 
 860		// LLColor3 dark_brown(0.143f, 0.129f, 0.114f);
 861		LLColor3 dark_brown(0.082f, 0.076f, 0.066f);
 862		LLColor3 brown(0.430f, 0.386f, 0.322f);
 863		LLColor3 sky_lighting = sunlight + ambient;
 864		F32 haze_brightness = vary_HazeColor.brightness();
 865
 866		if (Pn[1] < -0.05f)
 867		{
 868			vary_HazeColor = colorMix(dark_brown, brown, -Pn[1] * 0.9f) * sky_lighting * haze_brightness;
 869		}
 870		
 871		if (Pn[1] > -0.1f)
 872		{
 873			vary_HazeColor = colorMix(LLColor3::white * haze_brightness, vary_HazeColor, fabs((Pn[1] + 0.05f) * -20.f));
 874		}
 875	}
 876}
 877
 878#if LL_MSVC && __MSVC_VER__ < 8
 879#pragma optimize("p", off)
 880#endif
 881
 882LLColor3 LLVOSky::calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, 
 883							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
 884							LLVector2 vary_HorizontalProjection[2])
 885{
 886	LLColor3 res;
 887
 888	LLColor3 color0 = vary_HazeColor;
 889	
 890	if (!gPipeline.canUseWindLightShaders())
 891	{
 892		LLColor3 color1 = color0 * 2.0f;
 893		color1 = smear(1.f) - componentSaturate(color1);
 894		componentPow(color1, gamma);
 895		res = smear(1.f) - color1;
 896	} 
 897	else 
 898	{
 899		res = color0;
 900	}
 901
 902#	ifndef LL_RELEASE_FOR_DOWNLOAD
 903
 904	LLColor3 color2 = 2.f * color0;
 905
 906	LLColor3 color3 = LLColor3(1.f, 1.f, 1.f) - componentSaturate(color2);
 907	componentPow(color3, gamma);
 908	color3 = LLColor3(1.f, 1.f, 1.f) - color3;
 909
 910	static enum {
 911		OUT_DEFAULT		= 0,
 912		OUT_SKY_BLUE	= 1,
 913		OUT_RED			= 2,
 914		OUT_PN			= 3,
 915		OUT_HAZE		= 4,
 916	} debugOut = OUT_DEFAULT;
 917
 918	switch(debugOut) 
 919	{
 920		case OUT_DEFAULT:
 921			break;
 922		case OUT_SKY_BLUE:
 923			res = LLColor3(0.4f, 0.4f, 0.9f);
 924			break;
 925		case OUT_RED:
 926			res = LLColor3(1.f, 0.f, 0.f);
 927			break;
 928		case OUT_PN:
 929			res = LLColor3(Pn[0], Pn[1], Pn[2]);
 930			break;
 931		case OUT_HAZE:
 932			res = vary_HazeColor;
 933			break;
 934	}
 935#	endif // LL_RELEASE_FOR_DOWNLOAD
 936	return res;
 937}
 938
 939LLColor3 LLVOSky::createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
 940{
 941	return componentMult(diffuse, sundiffuse) * 4.0f +
 942			componentMult(ambient, sundiffuse) * 2.0f + sunambient;
 943}
 944
 945LLColor3 LLVOSky::createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
 946{
 947	return (componentMult(ambient, sundiffuse) + sunambient) * 0.8f;
 948}
 949
 950
 951void LLVOSky::calcAtmospherics(void)
 952{
 953	initAtmospherics();
 954
 955	LLColor3 vary_HazeColor;
 956	LLColor3 vary_SunlightColor;
 957	LLColor3 vary_AmbientColor;
 958	{
 959		// Initialize temp variables
 960		LLColor3 sunlight = sunlight_color;
 961
 962		// Sunlight attenuation effect (hue and brightness) due to atmosphere
 963		// this is used later for sunlight modulation at various altitudes
 964		LLColor3 light_atten =
 965			(blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
 966
 967		// Calculate relative weights
 968		LLColor3 temp2(0.f, 0.f, 0.f);
 969		LLColor3 temp1 = blue_density + smear(haze_density);
 970		LLColor3 blue_weight = componentDiv(blue_density, temp1);
 971		LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
 972
 973		// Compute sunlight from P & lightnorm (for long rays like sky)
 974		/// USE only lightnorm.
 975		// temp2[1] = llmax(0.f, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] );
 976		
 977		// and vary_sunlight will work properly with moon light
 978		F32 lighty = unclamped_lightnorm[1];
 979		if(lighty < LLSky::NIGHTTIME_ELEVATION_COS)
 980		{
 981			lighty = -lighty;
 982		}
 983
 984		temp2.mV[1] = llmax(0.f, lighty);
 985		if(temp2.mV[1] > 0.f)
 986		{
 987			temp2.mV[1] = 1.f / temp2.mV[1];
 988		}
 989		componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
 990
 991		// Distance
 992		temp2.mV[2] = density_multiplier;
 993
 994		// Transparency (-> temp1)
 995		temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
 996
 997		// vary_AtmosAttenuation = temp1; 
 998
 999		//increase ambient when there are more clouds
1000		LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5f;
1001
1002		//haze color
1003		vary_HazeColor =
1004			(blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient)	
1005			+ componentMult(haze_horizon.mV[0] * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient)
1006				 );	
1007
1008		//brightness of surface both sunlight and ambient
1009		vary_SunlightColor = componentMult(sunlight, temp1) * 1.f;
1010		vary_SunlightColor.clamp();
1011		vary_SunlightColor = smear(1.0f) - vary_SunlightColor;
1012		vary_SunlightColor = componentPow(vary_SunlightColor, gamma);
1013		vary_SunlightColor = smear(1.0f) - vary_SunlightColor;
1014		vary_AmbientColor = componentMult(tmpAmbient, temp1) * 0.5;
1015		vary_AmbientColor.clamp();
1016		vary_AmbientColor = smear(1.0f) - vary_AmbientColor;
1017		vary_AmbientColor = componentPow(vary_AmbientColor, gamma);
1018		vary_AmbientColor = smear(1.0f) - vary_AmbientColor;
1019
1020		componentMultBy(vary_HazeColor, LLColor3(1.f, 1.f, 1.f) - temp1);
1021
1022	}
1023
1024	mSun.setColor(vary_SunlightColor);
1025	mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f));
1026
1027	mSun.renewDirection();
1028	mSun.renewColor();
1029	mMoon.renewDirection();
1030	mMoon.renewColor();
1031
1032	float dp = getToSunLast() * LLVector3(0,0,1.f);
1033	if (dp < 0)
1034	{
1035		dp = 0;
1036	}
1037
1038	// Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
1039	// between sunlight and point lights in windlight to normalize point lights.
1040	F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
1041	LLWLParamManager::getInstance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
1042
1043	mSunDiffuse = vary_SunlightColor;
1044	mSunAmbient = vary_AmbientColor;
1045	mMoonDiffuse = vary_SunlightColor;
1046	mMoonAmbient = vary_AmbientColor;
1047
1048	mTotalAmbient = vary_AmbientColor;
1049	mTotalAmbient.setAlpha(1);
1050	
1051	mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f;
1052	mFadeColor.setAlpha(0);
1053}
1054
1055BOOL LLVOSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
1056{
1057	return TRUE;
1058}
1059
1060BOOL LLVOSky::updateSky()
1061{
1062	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
1063	{
1064		return TRUE;
1065	}
1066	
1067	if (mDead)
1068	{
1069		// It's dead.  Don't update it.
1070		return TRUE;
1071	}
1072	if (gGLManager.mIsDisabled)
1073	{
1074		return TRUE;
1075	}
1076
1077	static S32 next_frame = 0;
1078	const S32 total_no_tiles = 6 * NUM_TILES;
1079	const S32 cycle_frame_no = total_no_tiles + 1;
1080
1081	if (mUpdateTimer.getElapsedTimeF32() > 0.001f)
1082	{
1083		mUpdateTimer.reset();
1084		const S32 frame = next_frame;
1085
1086		++next_frame;
1087		next_frame = next_frame % cycle_frame_no;
1088
1089		mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no;
1090		// sInterpVal = (F32)next_frame / cycle_frame_no;
1091		LLSkyTex::setInterpVal( mInterpVal );
1092		LLHeavenBody::setInterpVal( mInterpVal );
1093		calcAtmospherics();
1094
1095		if (mForceUpdate || total_no_tiles == frame)
1096		{
1097			LLSkyTex::stepCurrent();
1098			
1099			const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f);
1100			const static F32 COLOR_CHANGE_THRESHOLD = 0.01f;
1101
1102			LLVector3 direction = mSun.getDirection();
1103			direction.normalize();
1104			const F32 dot_lighting = direction * mLastLightingDirection;
1105
1106			LLColor3 delta_color;
1107			delta_color.setVec(mLastTotalAmbient.mV[0] - mTotalAmbient.mV[0],
1108							   mLastTotalAmbient.mV[1] - mTotalAmbient.mV[1],
1109							   mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]);
1110
1111			if ( mForceUpdate 
1112				 || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
1113				 || (delta_color.length() > COLOR_CHANGE_THRESHOLD)
1114				 || !mInitialized)
1115				&& !direction.isExactlyZero()))
1116			{
1117				mLastLightingDirection = direction;
1118				mLastTotalAmbient = mTotalAmbient;
1119				mInitialized = TRUE;
1120
1121				if (mCubeMap)
1122				{
1123                    if (mForceUpdate)
1124					{
1125						updateFog(LLViewerCamera::getInstance()->getFar());
1126						for (int side = 0; side < 6; side++) 
1127						{
1128							for (int tile = 0; tile < NUM_TILES; tile++) 
1129							{
1130								createSkyTexture(side, tile);
1131							}
1132						}
1133
1134						calcAtmospherics();
1135
1136						for (int side = 0; side < 6; side++) 
1137						{
1138							LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE);
1139							LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE);
1140							raw2->copy(raw1);
1141							mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE));
1142
1143							raw1 = mShinyTex[side].getImageRaw(TRUE);
1144							raw2 = mShinyTex[side].getImageRaw(FALSE);
1145							raw2->copy(raw1);
1146							mShinyTex[side].createGLImage(mShinyTex[side].getWhich(FALSE));
1147						}
1148						next_frame = 0;	
1149					}
1150				}
1151			}
1152
1153			/// *TODO really, sky texture and env map should be shared on a single texture
1154			/// I'll let Brad take this at some point
1155
1156			// update the sky texture
1157			for (S32 i = 0; i < 6; ++i)
1158			{
1159				mSkyTex[i].create(1.0f);
1160				mShinyTex[i].create(1.0f);
1161			}
1162			
1163			// update the environment map
1164			if (mCubeMap)
1165			{
1166				std::vector<LLPointer<LLImageRaw> > images;
1167				images.reserve(6);
1168				for (S32 side = 0; side < 6; side++)
1169				{
1170					images.push_back(mShinyTex[side].getImageRaw(TRUE));
1171				}
1172				mCubeMap->init(images);
1173				gGL.getTexUnit(0)->disable();
1174			}
1175
1176			gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
1177			// *TODO: decide whether we need to update the stars vertex buffer in LLVOWLSky -Brad.
1178			//gPipeline.markRebuild(gSky.mVOWLSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
1179
1180			mForceUpdate = FALSE;
1181		}
1182		else
1183		{
1184			const S32 side = frame / NUM_TILES;
1185			const S32 tile = frame % NUM_TILES;
1186			createSkyTexture(side, tile);
1187		}
1188	}
1189
1190	if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
1191	{
1192		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
1193	}
1194	return TRUE;
1195}
1196
1197void LLVOSky::updateTextures()
1198{
1199	if (mSunTexturep)
1200	{
1201		mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
1202		mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
1203		mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
1204	}
1205}
1206
1207LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
1208{
1209	pipeline->allocDrawable(this);
1210	mDrawable->setLit(FALSE);
1211
1212	LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
1213	poolp->setSkyTex(mSkyTex);
1214	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
1215	
1216	for (S32 i = 0; i < 6; ++i)
1217	{
1218		mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
1219	}
1220
1221	mFace[FACE_SUN] = mDrawable->addFace(poolp, mSunTexturep);
1222	mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
1223	mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
1224
1225	return mDrawable;
1226}
1227
1228//by bao
1229//fake vertex buffer updating
1230//to guarantee at least updating one VBO buffer every frame
1231//to walk around the bug caused by ATI card --> DEV-3855
1232//
1233void LLVOSky::createDummyVertexBuffer()
1234{
1235	if(!mFace[FACE_DUMMY])
1236	{
1237		LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
1238		mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL);
1239	}
1240
1241	if(!mFace[FACE_DUMMY]->getVertexBuffer())
1242	{
1243		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
1244		buff->allocateBuffer(1, 1, TRUE);
1245		mFace[FACE_DUMMY]->setVertexBuffer(buff);
1246	}
1247}
1248
1249static LLFastTimer::DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update");
1250
1251void LLVOSky::updateDummyVertexBuffer()
1252{	
1253	if(!LLVertexBuffer::sEnableVBOs)
1254		return ;
1255
1256	if(mHeavenlyBodyUpdated)
1257	{
1258		mHeavenlyBodyUpdated = FALSE ;
1259		return ;
1260	}
1261
1262	LLFastTimer t(FTM_RENDER_FAKE_VBO_UPDATE) ;
1263
1264	if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer())
1265		createDummyVertexBuffer() ;
1266
1267	LLStrider<LLVector3> vertices ;
1268	mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices,  0);
1269	*vertices = mCameraPosAgent ;
1270	mFace[FACE_DUMMY]->getVertexBuffer()->flush();
1271}
1272//----------------------------------
1273//end of fake vertex buffer updating
1274//----------------------------------
1275static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry");
1276
1277BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
1278{
1279	LLFastTimer ftm(FTM_GEO_SKY);
1280	if (mFace[FACE_REFLECTION] == NULL)
1281	{
1282		LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
1283		if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0)
1284		{
1285			mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
1286		}
1287	}
1288
1289	mCameraPosAgent = drawable->getPositionAgent();
1290	mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
1291	mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
1292
1293	LLVector3 v_agent[8];
1294	for (S32 i = 0; i < 8; ++i)
1295	{
1296		F32 x_sgn = (i&1) ? 1.f : -1.f;
1297		F32 y_sgn = (i&2) ? 1.f : -1.f;
1298		F32 z_sgn = (i&4) ? 1.f : -1.f;
1299		v_agent[i] = HORIZON_DIST * SKY_BOX_MULT * LLVector3(x_sgn, y_sgn, z_sgn);
1300	}
1301
1302	LLStrider<LLVector3> verticesp;
1303	LLStrider<LLVector3> normalsp;
1304	LLStrider<LLVector2> texCoordsp;
1305	LLStrider<U16> indicesp;
1306	U16 index_offset;
1307	LLFace *face;	
1308
1309	for (S32 side = 0; side < 6; ++side)
1310	{
1311		face = mFace[FACE_SIDE0 + side]; 
1312
1313		if (!face->getVertexBuffer())
1314		{
1315			face->setSize(4, 6);
1316			face->setGeomIndex(0);
1317			face->setIndicesIndex(0);
1318			LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
1319			buff->allocateBuffer(4, 6, TRUE);
1320			face->setVertexBuffer(buff);
1321
1322			index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1323			
1324			S32 vtx = 0;
1325			S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X
1326			S32 side_dir = side & 1;  // even - 0, odd - 1
1327			S32 i_bit = (curr_bit + 2) % 3;
1328			S32 j_bit = (i_bit + 2) % 3;
1329
1330			LLVector3 axis;
1331			axis.mV[curr_bit] = 1;
1332			face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST;
1333
1334			vtx = side_dir << curr_bit;
1335			*(verticesp++)  = v_agent[vtx];
1336			*(verticesp++)  = v_agent[vtx | 1 << j_bit];
1337			*(verticesp++)  = v_agent[vtx | 1 << i_bit];
1338			*(verticesp++)  = v_agent[vtx | 1 << i_bit | 1 << j_bit];
1339
1340			*(texCoordsp++) = TEX00;
1341			*(texCoordsp++) = TEX01;
1342			*(texCoordsp++) = TEX10;
1343			*(texCoordsp++) = TEX11;
1344
1345			// Triangles for each side
1346			*indicesp++ = index_offset + 0;
1347			*indicesp++ = index_offset + 1;
1348			*indicesp++ = index_offset + 3;
1349
1350			*indicesp++ = index_offset + 0;
1351			*indicesp++ = index_offset + 3;
1352			*indicesp++ = index_offset + 2;
1353
1354			buff->flush();
1355		}
1356	}
1357
1358	const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis();
1359	LLVector3 right = look_at % LLVector3::z_axis;
1360	LLVector3 up = right % look_at;
1361	right.normalize();
1362	up.normalize();
1363
1364	const static F32 elevation_factor = 0.0f/sResolution;
1365	const F32 cos_max_angle = cosHorizon(elevation_factor);
1366	mSun.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_SUN, TRUE, mSun, cos_max_angle, up, right));
1367	mMoon.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_MOON, FALSE, mMoon, cos_max_angle, up, right));
1368
1369	const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f;
1370		// LLWorld::getInstance()->getWaterHeight() + 0.01f;
1371	const F32 camera_height = mCameraPosAgent.mV[2];
1372	const F32 height_above_water = camera_height - water_height;
1373
1374	BOOL sun_flag = FALSE;
1375
1376	if (mSun.isVisible())
1377	{
1378		if (mMoon.isVisible())
1379		{
1380			sun_flag = look_at * mSun.getDirection() > 0;
1381		}
1382		else
1383		{
1384			sun_flag = TRUE;
1385		}
1386	}
1387	
1388	if (height_above_water > 0)
1389	{
1390		BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0;
1391
1392		if (sun_flag)
1393		{
1394			setDrawRefl(0);
1395			if (render_ref)
1396			{
1397				updateReflectionGeometry(drawable, height_above_water, mSun);
1398			}
1399		}
1400		else
1401		{
1402			setDrawRefl(1);
1403			if (render_ref)
1404			{
1405				updateReflectionGeometry(drawable, height_above_water, mMoon);
1406			}
1407		}
1408	}
1409	else
1410	{
1411		setDrawRefl(-1);
1412	}
1413
1414	LLPipeline::sCompiles++;
1415	return TRUE;
1416}
1417
1418BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, const BOOL is_sun,
1419										 LLHeavenBody& hb, const F32 cos_max_angle,
1420										 const LLVector3 &up, const LLVector3 &right)
1421{
1422	mHeavenlyBodyUpdated = TRUE ;
1423
1424	LLStrider<LLVector3> verticesp;
1425	LLStrider<LLVector3> normalsp;
1426	LLStrider<LLVector2> texCoordsp;
1427	LLStrider<U16> indicesp;
1428	S32 index_offset;
1429	LLFace *facep;
1430
1431	LLVector3 to_dir = hb.getDirection();
1432
1433	if (!is_sun)
1434	{
1435		to_dir.mV[2] = llmax(to_dir.mV[2]+0.1f, 0.1f);
1436	}
1437	LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
1438
1439
1440	LLVector3 hb_right = to_dir % LLVector3::z_axis;
1441	LLVector3 hb_up = hb_right % to_dir;
1442	hb_right.normalize();
1443	hb_up.normalize();
1444
1445	//const static F32 cos_max_turn = sqrt(3.f) / 2; // 30 degrees
1446	//const F32 cos_turn_right = 1. / (llmax(cos_max_turn, hb_right * right));
1447	//const F32 cos_turn_up = 1. / llmax(cos_max_turn, hb_up * up);
1448
1449	const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
1450	F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
1451	F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
1452
1453	// Parameters for the water reflection
1454	hb.setU(HEAVENLY_BODY_FACTOR * horiz_enlargement * hb.getDiskRadius() * hb_right);
1455	hb.setV(HEAVENLY_BODY_FACTOR * vert_enlargement * hb.getDiskRadius() * hb_up);
1456	// End of parameters for the water reflection
1457
1458	const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU();
1459	const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV();
1460
1461	//const LLVector3 scaled_right = horiz_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_right;//right;
1462	//const LLVector3 scaled_up = vert_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_up;//up;
1463	LLVector3 v_clipped[4];
1464
1465	hb.corner(0) = draw_pos - scaled_right + scaled_up;
1466	hb.corner(1) = draw_pos - scaled_right - scaled_up;
1467	hb.corner(2) = draw_pos + scaled_right + scaled_up;
1468	hb.corner(3) = draw_pos + scaled_right - scaled_up;
1469
1470
1471	F32 t_left, t_right;
1472	if (!clip_quad_to_horizon(t_left, t_right, v_clipped, hb.corners(), cos_max_angle))
1473	{
1474		hb.setVisible(FALSE);
1475		return FALSE;
1476	}
1477	hb.setVisible(TRUE);
1478
1479	facep = mFace[f]; 
1480
1481	if (!facep->getVertexBuffer())
1482	{
1483		facep->setSize(4, 6);	
1484		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
1485		buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE);
1486		facep->setGeomIndex(0);
1487		facep->setIndicesIndex(0);
1488		facep->setVertexBuffer(buff);
1489	}
1490
1491	llassert(facep->getVertexBuffer()->getNumIndices() == 6);
1492
1493	index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1494
1495	if (-1 == index_offset)
1496	{
1497		return TRUE;
1498	}
1499
1500	for (S32 vtx = 0; vtx < 4; ++vtx)
1501	{
1502		hb.corner(vtx) = v_clipped[vtx];
1503		*(verticesp++)  = hb.corner(vtx) + mCameraPosAgent;
1504	}
1505
1506	*(texCoordsp++) = TEX01;
1507	*(texCoordsp++) = TEX00;
1508	*(texCoordsp++) = TEX11;
1509	*(texCoordsp++) = TEX10;
1510
1511	*indicesp++ = index_offset + 0;
1512	*indicesp++ = index_offset + 2;
1513	*indicesp++ = index_offset + 1;
1514
1515	*indicesp++ = index_offset + 1;
1516	*indicesp++ = index_offset + 2;
1517	*indicesp++ = index_offset + 3;
1518
1519	facep->getVertexBuffer()->flush();
1520
1521	if (is_sun)
1522	{
1523		if ((t_left > 0) && (t_right > 0))
1524		{
1525			F32 t = (t_left + t_right) * 0.5f;
1526			mSun.setHorizonVisibility(0.5f * (1 + cos(t * F_PI)));
1527		}
1528		else
1529		{
1530			mSun.setHorizonVisibility();
1531		}
1532		updateSunHaloGeometry(drawable);
1533	}
1534
1535	return TRUE;
1536}
1537
1538
1539
1540
1541// Clips quads with top and bottom sides parallel to horizon.
1542
1543BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
1544						  const LLVector3 v_corner[4], const F32 cos_max_angle)
1545{
1546	t_left = clip_side_to_horizon(v_corner[1], v_corner[0], cos_max_angle);
1547	t_right = clip_side_to_horizon(v_corner[3], v_corner[2], cos_max_angle);
1548
1549	if ((t_left >= 1) || (t_right >= 1))
1550	{
1551		return FALSE;
1552	}
1553
1554	//const BOOL left_clip = (t_left > 0);
1555	//const BOOL right_clip = (t_right > 0);
1556
1557	//if (!left_clip && !right_clip)
1558	{
1559		for (S32 vtx = 0; vtx < 4; ++vtx)
1560		{
1561			v_clipped[vtx]  = v_corner[vtx];
1562		}
1563	}
1564/*	else
1565	{
1566		v_clipped[0] = v_corner[0];
1567		v_clipped[1] = left_clip ? ((1 - t_left) * v_corner[1] + t_left * v_corner[0])
1568									: v_corner[1];
1569		v_clipped[2] = v_corner[2];
1570		v_clipped[3] = right_clip ? ((1 - t_right) * v_corner[3] + t_right * v_corner[2])
1571									: v_corner[3];
1572	}*/
1573
1574	return TRUE;
1575}
1576
1577
1578F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos_max_angle)
1579{
1580	const LLVector3 V = V1 - V0;
1581	const F32 k2 = 1.f/(cos_max_angle * cos_max_angle) - 1;
1582	const F32 A = V.mV[0] * V.mV[0] + V.mV[1] * V.mV[1] - k2 * V.mV[2] * V.mV[2];
1583	const F32 B = V0.mV[0] * V.mV[0] + V0.mV[1] * V.mV[1] - k2 * V0.mV[2] * V.mV[2];
1584	const F32 C = V0.mV[0] * V0.mV[0] + V0.mV[1] * V0.mV[1] - k2 * V0.mV[2] * V0.mV[2];
1585
1586	if (fabs(A) < 1e-7)
1587	{
1588		return -0.1f;	// v0 is cone origin and v1 is on the surface of the cone.
1589	}
1590
1591	const F32 det = sqrt(B*B - A*C);
1592	const F32 t1 = (-B - det) / A;
1593	const F32 t2 = (-B + det) / A;
1594	const F32 z1 = V0.mV[2] + t1 * V.mV[2];
1595	const F32 z2 = V0.mV[2] + t2 * V.mV[2];
1596	if (z1 * cos_max_angle < 0)
1597	{
1598		return t2;
1599	}
1600	else if (z2 * cos_max_angle < 0)
1601	{
1602		return t1;
1603	}
1604	else if ((t1 < 0) || (t1 > 1))
1605	{
1606		return t2;
1607	}
1608	else
1609	{
1610		return t1;
1611	}
1612}
1613
1614
1615void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
1616{
1617#if 0
1618	const LLVector3* v_corner = mSun.corners();
1619
1620	LLStrider<LLVector3> verticesp;
1621	LLStrider<LLVector3> normalsp;
1622	LLStrider<LLVector2> texCoordsp;
1623	LLStrider<U16> indicesp;
1624	S32 index_offset;
1625	LLFace *face;
1626
1627	const LLVector3 right = 2 * (v_corner[2] - v_corner[0]);
1628	LLVector3 up = 2 * (v_corner[2] - v_corner[3]);
1629	up.normalize();
1630	F32 size = right.length();
1631	up = size * up;
1632	const LLVector3 draw_pos = 0.25 * (v_corner[0] + v_corner[1] + v_corner[2] + v_corner[3]);
1633	
1634	LLVector3 v_glow_corner[4];
1635
1636	v_glow_corner[0] = draw_pos - right + up;
1637	v_glow_corner[1] = draw_pos - right - up;
1638	v_glow_corner[2] = draw_pos + right + up;
1639	v_glow_corner[3] = draw_pos + right - up;
1640
1641	face = mFace[FACE_BLOOM]; 
1642
1643	if (face->mVertexBuffer.isNull())
1644	{
1645		face->setSize(4, 6);
1646		face->setGeomIndex(0);
1647		face->setIndicesIndex(0);
1648		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
1649		face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
1650	}
1651
1652	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
1653	if (-1 == index_offset)
1654	{
1655		return;
1656	}
1657
1658	for (S32 vtx = 0; vtx < 4; ++vtx)
1659	{
1660		*(verticesp++)  = v_glow_corner[vtx] + mCameraPosAgent;
1661	}
1662
1663	*(texCoordsp++) = TEX01;
1664	*(texCoordsp++) = TEX00;
1665	*(texCoordsp++) = TEX11;
1666	*(texCoordsp++) = TEX10;
1667
1668	*indicesp++ = index_offset + 0;
1669	*indicesp++ = index_offset + 2;
1670	*indicesp++ = index_offset + 1;
1671
1672	*indicesp++ = index_offset + 1;
1673	*indicesp++ = index_offset + 2;
1674	*indicesp++ = index_offset + 3;
1675#endif
1676}
1677
1678
1679F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir)
1680{
1681	LLVector3 P = p;
1682	P.normalize();
1683
1684	const F32 cos_dir_angle = -P.mV[VZ];
1685	const F32 sin_dir_angle = sqrt(1 - cos_dir_angle * cos_dir_angle);
1686
1687	F32 cos_diff_angles = cos_dir_angle * cos_dir_from_top
1688									+ sin_dir_angle * sin_dir_from_top;
1689
1690	F32 diff_angles;
1691	if (cos_diff_angles > (1 - 1e-7))
1692		diff_angles = 0;
1693	else
1694		diff_angles = acos(cos_diff_angles);
1695
1696	const F32 rel_diff_angles = diff_angles / diff_angl_dir;
1697	const F32 dt = 1 - rel_diff_angles;
1698
1699	return (dt < 0) ? 0 : dt;
1700}
1701
1702
1703F32 dtClip(const LLVector3& v0, const LLVector3& v1, F32 far_clip2)
1704{
1705	F32 dt_clip;
1706	const LLVector3 otrezok = v1 - v0;
1707	const F32 A = otrezok.lengthSquared();
1708	const F32 B = v0 * otrezok;
1709	const F32 C = v0.lengthSquared() - far_clip2;
1710	const F32 det = sqrt(B*B - A*C);
1711	dt_clip = (-B - det) / A;
1712	if ((dt_clip < 0) || (dt_clip > 1))
1713		dt_clip = (-B + det) / A;
1714	return dt_clip;
1715}
1716
1717
1718void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
1719										 const LLHeavenBody& HB)
1720{
1721	const LLVector3 &look_at = LLViewerCamera::getInstance()->getAtAxis();
1722	// const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.001f;
1723	// LLWorld::getInstance()->getWaterHeight() + 0.001f;
1724
1725	LLVector3 to_dir = HB.getDirection();
1726	LLVector3 hb_pos = to_dir * (HORIZON_DIST - 10);
1727	LLVector3 to_dir_proj = to_dir;
1728	to_dir_proj.mV[VZ] = 0;
1729	to_dir_proj.normalize();
1730
1731	LLVector3 Right = to_dir % LLVector3::z_axis;
1732	LLVector3 Up = Right % to_dir;
1733	Right.normalize();
1734	Up.normalize();
1735
1736	// finding angle between  look direction and sprite.
1737	LLVector3 look_at_right = look_at % LLVector3::z_axis;
1738	look_at_right.normalize();
1739
1740	const static F32 cos_horizon_angle = cosHorizon(0.0f/sResolution);
1741	//const static F32 horizon_angle = acos(cos_horizon_angle);
1742
1743	const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
1744	F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
1745	F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
1746
1747	F32 vert_size = vert_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
1748	Right *= /*cos_lookAt_toDir */ horiz_enlargement * HEAVENLY_BODY_SCALE * HB.getDiskRadius();
1749	Up *= vert_size;
1750
1751	LLVector3 v_corner[2];
1752	LLVector3 stretch_corner[2];
1753
1754	LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up;
1755	v_corner[1] = stretch_corner[1] = hb_pos - Right - Up;
1756
1757	F32 dt_hor, dt;
1758	dt_hor = clip_side_to_horizon(v_corner[1], v_corner[0], cos_horizon_angle);
1759
1760	LLVector2 TEX0t = TEX00;
1761	LLVector2 TEX1t = TEX10;
1762	LLVector3 lower_corner = v_corner[1];
1763
1764	if ((dt_hor > 0) && (dt_hor < 1))
1765	{
1766		TEX0t = LLVector2(0, dt_hor);
1767		TEX1t = LLVector2(1, dt_hor);
1768		lower_corner = (1 - dt_hor) * v_corner[1] + dt_hor * v_corner[0];
1769	}
1770	else
1771		dt_hor = llmax(0.0f, llmin(1.0f, dt_hor));
1772
1773	top_hb.normalize();
1774	const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]);
1775	const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view);
1776
1777	const S32 cols = 1;
1778	const S32 raws = lltrunc(16 * extension);
1779	S32 quads = cols * raws;
1780
1781	stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner);
1782	stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner);
1783
1784	dt = dt_hor;
1785
1786
1787	F32 cos_dir_from_top[2];
1788
1789	LLVector3 dir = stretch_corner[0];
1790	dir.normalize();
1791	cos_dir_from_top[0] = dir.mV[VZ];
1792
1793	dir = stretch_corner[1];
1794	dir.normalize();
1795	cos_dir_from_top[1] = dir.mV[VZ];
1796
1797	const F32 sin_dir_from_top = sqrt(1 - cos_dir_from_top[0] * cos_dir_from_top[0]);
1798	const F32 sin_dir_from_top2 = sqrt(1 - cos_dir_from_top[1] * cos_dir_from_top[1]);
1799	const F32 cos_diff_dir = cos_dir_from_top[0] * cos_dir_from_top[1]
1800							+ sin_dir_from_top * sin_dir_from_top2;
1801	const F32 diff_angl_dir = acos(cos_diff_dir);
1802
1803	v_corner[0] = stretch_corner[0];
1804	v_corner[1] = lower_corner;
1805
1806
1807	LLVector2 TEX0tt = TEX01;
1808	LLVector2 TEX1tt = TEX11;
1809
1810	LLVector3 v_refl_corner[4];
1811	LLVector3 v_sprite_corner[4];
1812
1813	S32 vtx;
1814	for (vtx = 0; vtx < 2; ++vtx)
1815	{
1816		LLVector3 light_proj = v_corner[vtx];
1817		light_proj.normalize();
1818
1819		const F32 z = light_proj.mV[VZ];
1820		const F32 sin_angle = sqrt(1 - z * z);
1821		light_proj *= 1.f / sin_angle;
1822		light_proj.mV[VZ] = 0;
1823		const F32 to_refl_point = H * sin_angle / fabs(z);
1824
1825		v_refl_corner[vtx] = to_refl_point * light_proj;
1826	}
1827
1828
1829	for (vtx = 2; vtx < 4; ++vtx)
1830	{
1831		const LLVector3 to_dir_vec = (to_dir_proj * v_refl_corner[vtx-2]) * to_dir_proj;
1832		v_refl_corner[vtx] = v_refl_corner[vtx-2] + 2 * (to_dir_vec - v_refl_corner[vtx-2]);
1833	}
1834
1835	for (vtx = 0; vtx < 4; ++vtx)
1836		v_refl_corner[vtx].mV[VZ] -= H;
1837
1838	S32 side = 0;
1839	LLVector3 refl_corn_norm[2];
1840	refl_corn_norm[0] = v_refl_corner[1];
1841	refl_corn_norm[0].normalize();
1842	refl_corn_norm[1] = v_refl_corner[3];
1843	refl_corn_norm[1].normalize();
1844
1845	F32 cos_refl_look_at[2];
1846	cos_refl_look_at[0] = refl_corn_norm[0] * look_at;
1847	cos_refl_look_at[1] = refl_corn_norm[1] * look_at;
1848
1849	if (cos_refl_look_at[1] > cos_refl_look_at[0])
1850	{
1851		side = 2;
1852	}
1853
1854	//const F32 far_clip = (LLViewerCamera::getInstance()->getFar() - 0.01) / far_clip_factor;
1855	const F32 far_clip = 512;
1856	const F32 far_clip2 = far_clip*far_clip;
1857
1858	F32 dt_clip;
1859	F32 vtx_near2, vtx_far2;
1860
1861	if ((vtx_far2 = v_refl_corner[side]

Large files files are truncated, but you can click here to view the full file