diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llvosky.h |
Print done when done.
Diffstat (limited to 'indra/newview/llvosky.h')
-rw-r--r-- | indra/newview/llvosky.h | 907 |
1 files changed, 907 insertions, 0 deletions
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h new file mode 100644 index 0000000000..1c819ebcd8 --- /dev/null +++ b/indra/newview/llvosky.h @@ -0,0 +1,907 @@ +/** + * @file llvosky.h + * @brief LLVOSky class header file + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLVOSKY_H +#define LL_LLVOSKY_H + +#include "stdtypes.h" +#include "v3color.h" +#include "v4coloru.h" +#include "llviewerimage.h" +#include "llviewerobject.h" +#include "llframetimer.h" + + +////////////////////////////////// +// +// Lots of constants +// +// Will clean these up at some point... +// + +const F32 HORIZON_DIST = 1024.0f; +const F32 HEAVENLY_BODY_DIST = HORIZON_DIST - 10.f; +const F32 HEAVENLY_BODY_FACTOR = 0.1f; +const F32 HEAVENLY_BODY_SCALE = HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR; +const F32 EARTH_RADIUS = 6.4e6f; // exact radius = 6.37 x 10^6 m +const F32 ATM_EXP_FALLOFF = 0.000126f; +const F32 ATM_SEA_LEVEL_NDENS = 2.55e25f; +// Somewhat arbitrary: +const F32 ATM_HEIGHT = 100000.f; + +const F32 FIRST_STEP = 5000.f; +const F32 INV_FIRST_STEP = 1.f/FIRST_STEP; +const S32 NO_STEPS = 15; +const F32 INV_NO_STEPS = 1.f/NO_STEPS; + + +// constants used in calculation of scattering coeff of clear air +const F32 sigma = 0.035f; +const F32 fsigma = (6+3*sigma)/(6.f-7.f*sigma); +const F64 Ndens = 2.55e25; +const F64 Ndens2 = Ndens*Ndens; + +// !!! FIXME: This #define should be in llcommon somewhere... +#ifdef __GNUC__ +#define __forceinline inline __attribute__((always_inline)) +#endif + +__forceinline LLColor3 color_div(const LLColor3 &col1, const LLColor3 &col2) +{ + return LLColor3( + col1.mV[0] / col2.mV[0], + col1.mV[1] / col2.mV[1], + col1.mV[2] / col2.mV[2] ); +} + +LLColor3 color_norm(const LLColor3 &col); +LLVector3 move_vec (const LLVector3& v, F32 cos_max_angle); +BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4], + const LLVector3 v_corner[4], const F32 cos_max_angle); +F32 clip_side_to_horizon(const LLVector3& v0, const LLVector3& v1, const F32 cos_max_angle); + +inline F32 color_intens ( const LLColor3 &col ) +{ + return col.mV[0] + col.mV[1] + col.mV[2]; +} + +inline F32 color_max(const LLColor3 &col) +{ + return llmax(col.mV[0], col.mV[1], col.mV[2]); +} + +inline F32 color_max(const LLColor4 &col) +{ + return llmax(col.mV[0], col.mV[1], col.mV[2]); +} + + +inline F32 color_min(const LLColor3 &col) +{ + return llmin(col.mV[0], col.mV[1], col.mV[2]); +} + +inline LLColor3 color_norm_abs(const LLColor3 &col) +{ + const F32 m = color_max(col); + if (m > 1e-6) + { + return 1.f/m * col; + } + else return col; +} + + + +class LLFace; +class LLHaze; + + +class LLSkyTex +{ + friend class LLVOSky; +private: + static S32 sResolution; + static S32 sComponents; + LLPointer<LLImageGL> mImageGL[2]; + LLPointer<LLImageRaw> mImageRaw[2]; + LLColor3 *mSkyData; + LLVector3 *mSkyDirs; // Cache of sky direction vectors + static S32 sCurrent; + static F32 sInterpVal; + +public: + static F32 getInterpVal() { return sInterpVal; } + static void setInterpVal(const F32 v) { sInterpVal = v; } + static BOOL doInterpolate() { return sInterpVal > 0.001; } + + void bindTexture(BOOL curr = TRUE); + +protected: + LLSkyTex(); + void init(); + void cleanupGL(); + void restoreGL(); + + ~LLSkyTex(); + + + static S32 getResolution() { return sResolution; } + static S32 getCurrent() { return sCurrent; } + static S32 stepCurrent() { return (sCurrent = ++sCurrent % 2); } + static S32 getNext() { return ((sCurrent+1) % 2); } + static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); } + + void initEmpty(const S32 tex); + void create(F32 brightness_scale, const LLColor3& multiscatt); + + void setDir(const LLVector3 &dir, const S32 i, const S32 j) + { + S32 offset = i * sResolution + j; + mSkyDirs[offset] = dir; + } + + const LLVector3 &getDir(const S32 i, const S32 j) const + { + S32 offset = i * sResolution + j; + return mSkyDirs[offset]; + } + + void setPixel(const LLColor3 &col, const S32 i, const S32 j) + { + S32 offset = i * sResolution + j; + mSkyData[offset] = col; + } + + void setPixel(const LLColor4U &col, const S32 i, const S32 j) + { + S32 offset = (i * sResolution + j) * sComponents; + U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]); + *pix = col.mAll; + } + + LLColor4U getPixel(const S32 i, const S32 j) + { + LLColor4U col; + S32 offset = (i * sResolution + j) * sComponents; + U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]); + col.mAll = *pix; + return col; + } + + LLImageRaw* getImageRaw(BOOL curr=TRUE) { return mImageRaw[getWhich(curr)]; } + void createTexture(BOOL curr=TRUE); +}; + + +class LLHeavenBody +{ +protected: + LLVector3 mDirectionCached; // hack for events that shouldn't happen every frame + + LLColor3 mColor; + LLColor3 mColorCached; + F32 mIntensity; + LLVector3 mDirection; // direction of the local heavenly body + LLVector3 mAngularVelocity; // velocity of the local heavenly body + + F32 mDiskRadius; + BOOL mDraw; // FALSE - do not draw. + F32 mHorizonVisibility; // number [0, 1] due to how horizon + F32 mVisibility; // same but due to other objects being in frong. + BOOL mVisible; + static F32 sInterpVal; + LLVector3 mQuadCorner[4]; + LLVector3 mU; + LLVector3 mV; + LLVector3 mO; + +public: + LLHeavenBody(const F32 rad) : + mDirectionCached(LLVector3(0,0,0)), mDirection(LLVector3(0,0,0)), + mDiskRadius(rad), mDraw(FALSE), + mHorizonVisibility(1), mVisibility(1) + + { + mColor.setToBlack(); + mColorCached.setToBlack(); + } + ~LLHeavenBody() {} + + const LLVector3& getDirection() const { return mDirection; } + void setDirection(const LLVector3 &direction) { mDirection = direction; } + void setAngularVelocity(const LLVector3 &ang_vel) { mAngularVelocity = ang_vel; } + const LLVector3& getAngularVelocity() const { return mAngularVelocity; } + + const LLVector3& getDirectionCached() const { return mDirectionCached; } + void renewDirection() { mDirectionCached = mDirection; } + + const LLColor3& getColorCached() const { return mColorCached; } + void setColorCached(const LLColor3& c) { mColorCached = c; } + const LLColor3& getColor() const { return mColor; } + void setColor(const LLColor3& c) { mColor = c; } + + void renewColor() { mColorCached = mColor; } + + static F32 interpVal() { return sInterpVal; } + static void setInterpVal(const F32 v) { sInterpVal = v; } + + LLColor3 getInterpColor() const + { + return sInterpVal * mColor + (1 - sInterpVal) * mColorCached; + } + +// LLColor3 getDiffuseColor() const +// { +// LLColor3 dif = mColorCached; +// dif.clamp(); +// return 2 * dif; +// } + +// LLColor4 getAmbientColor(const LLColor3& scatt, F32 scale) const +// { +// const F32 min_val = 0.05f; +// LLColor4 col = LLColor4(scale * (0.8f * color_norm_abs(getDiffuseColor()) + 0.2f * scatt)); +// //F32 left = max(0, 1 - col.mV[0]); +// if (col.mV[0] >= 0.9) +// { +// col.mV[1] = llmax(col.mV[1], 2.f * min_val); +// col.mV[2] = llmax(col.mV[2], min_val); +// } +// col.setAlpha(1.f); +// return col; +// } + + const F32& getHorizonVisibility() const { return mHorizonVisibility; } + void setHorizonVisibility(const F32 c = 1) { mHorizonVisibility = c; } + const F32& getVisibility() const { return mVisibility; } + void setVisibility(const F32 c = 1) { mVisibility = c; } + const F32 getHaloBrighness() const + { + return llmax(0.f, llmin(0.9f, mHorizonVisibility)) * mVisibility; + } + BOOL isVisible() const { return mVisible; } + void setVisible(const BOOL v) { mVisible = v; } + + + const F32& getIntensity() const { return mIntensity; } + void setIntensity(const F32 c) { mIntensity = c; } + + void setDiskRadius(const F32 radius) { mDiskRadius = radius; } + F32 getDiskRadius() const { return mDiskRadius; } + + void setDraw(const BOOL draw) { mDraw = draw; } + BOOL getDraw() const { return mDraw; } + + const LLVector3& corner(const S32 n) const { return mQuadCorner[n]; } + LLVector3& corner(const S32 n) { return mQuadCorner[n]; } + const LLVector3* corners() const { return mQuadCorner; } + + const LLVector3& getU() const { return mU; } + const LLVector3& getV() const { return mV; } + void setU(const LLVector3& u) { mU = u; } + void setV(const LLVector3& v) { mV = v; } +}; + + +__forceinline LLColor3 refr_ind_calc(const LLColor3 &wave_length) +{ + LLColor3 refr_ind; + for (S32 i = 0; i < 3; ++i) + { + const F32 wl2 = wave_length.mV[i] * wave_length.mV[i] * 1e-6f; + refr_ind.mV[i] = 6.43e3f + ( 2.95e6f / ( 146.0f - 1.f/wl2 ) ) + ( 2.55e4f / ( 41.0f - 1.f/wl2 ) ); + refr_ind.mV[i] *= 1.0e-8f; + refr_ind.mV[i] += 1.f; + } + return refr_ind; +} + + +__forceinline LLColor3 calc_air_sca_sea_level() +{ + const static LLColor3 WAVE_LEN(675, 520, 445); + const static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN); + const static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1); + const static LLColor3 n4 = n21 * n21; + const static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f; + const static LLColor3 wl4 = wl2 * wl2; + const static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4; + const static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2); + return dens_div_N * color_div ( mult_const, wl4 ); +} + +const LLColor3 gAirScaSeaLevel = calc_air_sca_sea_level(); +const F32 AIR_SCA_INTENS = color_intens(gAirScaSeaLevel); +const F32 AIR_SCA_AVG = AIR_SCA_INTENS / 3; + +class LLHaze +{ +public: + LLHaze() : mG(0), mFalloff(1) {mSigSca.setToBlack();} + LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2) : + mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0) + { + mAbsCoef = color_intens(mSigSca) / AIR_SCA_INTENS; + } + + LLHaze(const F32 g, const F32 sca, const F32 fo = 2) : mG(g), + mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo) + { + mAbsCoef = 0.01f * sca / AIR_SCA_AVG; + } + + static void initClass(); + + + F32 getG() const { return mG; } + + void setG(const F32 g) + { + mG = g; + } + + const LLColor3& getSigSca() const // sea level + { + return mSigSca; + } + + void setSigSca(const LLColor3& s) + { + mSigSca = s; + mAbsCoef = 0.01f * color_intens(mSigSca) / AIR_SCA_INTENS; + } + + void setSigSca(const F32 s0, const F32 s1, const F32 s2) + { + mSigSca = AIR_SCA_AVG * LLColor3 (s0, s1, s2); + mAbsCoef = 0.01f * (s0 + s1 + s2) / 3; + } + + F32 getFalloff() const + { + return mFalloff; + } + + void setFalloff(const F32 fo) + { + mFalloff = fo; + } + + F32 getAbsCoef() const + { + return mAbsCoef; + } + + inline static F32 calcFalloff(const F32 h) + { + return (h <= 0) ? 1.0f : (F32)LL_FAST_EXP(-ATM_EXP_FALLOFF * h); + } + + inline LLColor3 calcSigSca(const F32 h) const + { + return calcFalloff(h * mFalloff) * mSigSca; + } + + inline void calcSigSca(const F32 h, LLColor3 &result) const + { + result = mSigSca; + result *= calcFalloff(h * mFalloff); + } + + LLColor3 calcSigExt(const F32 h) const + { + return calcFalloff(h * mFalloff) * (1 + mAbsCoef) * mSigSca; + } + + F32 calcPhase(const F32 cos_theta) const; + + static inline LLColor3 calcAirSca(const F32 h); + static inline void calcAirSca(const F32 h, LLColor3 &result); + static LLColor3 calcAirScaSeaLevel() { return gAirScaSeaLevel; } + static const LLColor3 &getAirScaSeaLevel() { return sAirScaSeaLevel; } +public: + static LLColor3 sAirScaSeaLevel; + +protected: + F32 mG; + LLColor3 mSigSca; + F32 mFalloff; // 1 - slow, >1 - faster + F32 mAbsCoef; +}; + +class LLTranspMap +{ +public: + LLTranspMap() : mElevation(0), mMaxAngle(0), mStep(5), mHaze(NULL), mT(NULL) {} + ~LLTranspMap() + { + delete[] mT; + mT = NULL; + } + + void init(const F32 elev, const F32 step, const F32 h, const LLHaze* const haze); + + F32 calcHeight(const LLVector3& pos) const + { + return pos.magVec() - EARTH_RADIUS ; + } + + BOOL hasHaze() const + { + return mHaze != NULL; + } + + LLColor3 calcSigExt(const F32 h) const + { + return LLHaze::calcAirSca(h) + (hasHaze() ? mHaze->calcSigExt(h) : LLColor3(0, 0, 0)); + } + + inline void calcAirTransp(const F32 cos_angle, LLColor3 &result) const; + LLColor3 calcAirTranspDir(const F32 elevation, const LLVector3 &dir) const; + LLColor3 getHorizonAirTransp () const { return mT[mMapSize-1]; } + F32 hitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const; + +protected: + F32 mAtmHeight; + F32 mElevation; + F32 mMaxAngle; + F32 mCosMaxAngle; + F32 mStep; + F32 mStepInv; + S32 mMapSize; + const LLHaze *mHaze; + LLColor3 *mT; // transparency values in all directions + //starting with mAngleBelowHorz at mElevation +}; + +class LLTranspMapSet +{ +protected: + F32 *mHeights; + LLTranspMap *mTransp; + S32 mSize; + F32 mMediaHeight; + const LLHaze *mHaze; + S32 lerp(F32& dt, S32& indx, const F32 h) const; +public: + LLTranspMapSet() : mHeights(NULL), mTransp(NULL), mHaze(NULL) {} + ~LLTranspMapSet(); + + void init (S32 size, F32 first_step, F32 media_height, const LLHaze* const haze); + S32 getSize() const { return mSize; } + F32 getMediaHeight() const { return mMediaHeight; } + const LLTranspMap& getLastTransp() const { return mTransp[mSize-1]; } + F32 getLastHeight() const { return mHeights[mSize-1]; } + const LLTranspMap& getMap(const S32 n) const { return mTransp[n]; } + F32 getHeight(const S32 n) const { return mHeights[n]; } + BOOL isReady() const { return mTransp != NULL; } + + inline LLColor3 calcTransp(const F32 cos_angle, const F32 h) const; + inline void calcTransp(const F32 cos_angle, const F32 h, LLColor3 &result) const; +}; + +class LLCubeMap; + + +class LLVOSky : public LLViewerObject +{ +public: + enum + { + FACE_SIDE0, + FACE_SIDE1, + FACE_SIDE2, + FACE_SIDE3, + FACE_SIDE4, + FACE_SIDE5, + FACE_SUN, // was 6 + FACE_MOON, // was 7 + FACE_BLOOM, // was 8 + FACE_REFLECTION, // was 10 + FACE_COUNT + }; + + LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + virtual ~LLVOSky(); + + // Initialize/delete data that's only inited once per class. + static void initClass(); + void init(); + void initCubeMap(); + void initEmpty(); + BOOL isReady() const { return mTransp.isReady(); } + const LLTranspMapSet& getTransp() const { return mTransp; } + + void cleanupGL(); + void restoreGL(); + + /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + BOOL updateSky(); + + // Graphical stuff for objects - maybe broken out into render class + // later? + /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + + void initSkyTextureDirs(const S32 side, const S32 tile); + void createSkyTexture(const S32 side, const S32 tile); + + void updateBrightestDir(); + void calcBrightnessScaleAndColors(); + + LLColor3 calcSkyColorInDir(const LLVector3& dir); + void calcSkyColorInDir(LLColor3& res, LLColor3& transp, + const LLVector3& dir) const; + LLColor4 calcInScatter(LLColor4& transp, const LLVector3 &point, F32 exag) const; + void calcInScatter( LLColor3& res, LLColor3& transp, + const LLVector3& P, F32 exag) const; + + // Not currently used. + //LLColor3 calcGroundFog(LLColor3& transp, const LLVector3 &view_dir, F32 obj_dist) const; + //void calcGroundFog(LLColor3& res, LLColor3& transp, const LLVector3 view_dir, F32 dist) const; + + LLColor3 calcRadianceAtPoint(const LLVector3& pos) const + { + const F32 cos_angle = calcUpVec(pos) * getToSunLast(); + LLColor3 tr; + mTransp.calcTransp(cos_angle, calcHeight(pos), tr); + return mBrightnessScaleGuess * mSun.getIntensity() * tr; + } + + const LLHeavenBody& getSun() const { return mSun; } + const LLHeavenBody& getMoon() const { return mMoon; } + + const LLVector3& getToSunLast() const { return mSun.getDirectionCached(); } + const LLVector3& getToSun() const { return mSun.getDirection(); } + const LLVector3& getToMoon() const { return mMoon.getDirection(); } + const LLVector3& getToMoonLast() const { return mMoon.getDirectionCached(); } + BOOL isSunUp() const { return mSun.getDirectionCached().mV[2] > -0.05f; } + void calculateColors(); + + LLColor3 getSunDiffuseColor() const { return mSunDiffuse; } + LLColor3 getMoonDiffuseColor() const { return mMoonDiffuse; } + LLColor4 getSunAmbientColor() const { return mSunAmbient; } + LLColor4 getMoonAmbientColor() const { return mMoonAmbient; } + const LLColor4& getTotalAmbientColor() const { return mTotalAmbient; } + LLColor4 getFogColor() const { return mFogColor; } + + LLVector3 calcUpVec(const LLVector3 &pos) const + { + LLVector3 v = pos - mEarthCenter; + v.normVec(); + return v; + } + + F32 calcHeight(const LLVector3& pos) const + { + return dist_vec(pos, mEarthCenter) - EARTH_RADIUS; + } + + // Phase function for atmospheric scattering. + // co = cos ( theta ) + F32 calcAirPhaseFunc(const F32 co) const + { + return (0.75f * (1.f + co*co)); + } + + + BOOL isSameFace(S32 idx, const LLFace* face) const { return mFace[idx] == face; } + + void initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity) + { + LLVector3 sun_direction = (sun_dir.magVec() == 0) ? LLVector3::x_axis : sun_dir; + sun_direction.normVec(); + mSun.setDirection(sun_direction); + mSun.renewDirection(); + mSun.setAngularVelocity(sun_ang_velocity); + mMoon.setDirection(-mSun.getDirection()); + mMoon.renewDirection(); + mLastLightingDirection = mSun.getDirection(); + + if ( !isReady() ) + { + init(); + LLSkyTex::stepCurrent(); + } + } + + void setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity); + + void updateHaze(); + + BOOL updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 side, const BOOL is_sun, + LLHeavenBody& hb, const F32 sin_max_angle, + const LLVector3 &up, const LLVector3 &right); + + LLVector3 toHorizon(const LLVector3& dir, F32 delta = 0) const + { + return move_vec(dir, cosHorizon(delta)); + } + F32 cosHorizon(const F32 delta = 0) const + { + const F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mCameraPosAgent.mV[2]); + return delta - (F32)sqrt(1.f - sin_angle * sin_angle); + } + + void updateSunHaloGeometry(LLDrawable *drawable); + void updateReflectionGeometry(LLDrawable *drawable, F32 H, const LLHeavenBody& HB); + + + const LLHaze& getHaze() const { return mHaze; } + LLHaze& getHaze() { return mHaze; } + F32 getHazeConcentration() const { return mHazeConcentration; } + void setHaze(const LLHaze& h) { mHaze = h; } + F32 getWorldScale() const { return mWorldScale; } + void setWorldScale(const F32 s) { mWorldScale = s; } + void updateFog(const F32 distance); + void setFogRatio(const F32 fog_ratio) { mFogRatio = fog_ratio; } + LLColor4U getFadeColor() const { return mFadeColor; } + F32 getFogRatio() const { return mFogRatio; } + void setCloudDensity(F32 cloud_density) { mCloudDensity = cloud_density; } + void setWind ( const LLVector3& wind ) { mWind = wind.magVec(); } + + const LLVector3 &getCameraPosAgent() const { return mCameraPosAgent; } + LLVector3 getEarthCenter() const { return mEarthCenter; } + + LLCubeMap *getCubeMap() const { return mCubeMap; } + S32 getDrawRefl() const { return mDrawRefl; } + void setDrawRefl(const S32 r) { mDrawRefl = r; } + BOOL isReflFace(const LLFace* face) const { return face == mFace[FACE_REFLECTION]; } + LLFace* getReflFace() const { return mFace[FACE_REFLECTION]; } + + F32 calcHitsEarth(const LLVector3& orig, const LLVector3& dir) const; + F32 calcHitsAtmEdge(const LLVector3& orig, const LLVector3& dir) const; + LLViewerImage* getSunTex() const { return mSunTexturep; } + LLViewerImage* getMoonTex() const { return mMoonTexturep; } + LLViewerImage* getBloomTex() const { return mBloomTexturep; } + + void generateScatterMap(); + LLImageGL* getScatterMap() { return mScatterMap; } + +public: + static F32 sNighttimeBrightness; // [0,2] default = 1.0 + +protected: + LLPointer<LLViewerImage> mSunTexturep; + LLPointer<LLViewerImage> mMoonTexturep; + LLPointer<LLViewerImage> mBloomTexturep; + + static S32 sResolution; + static S32 sTileResX; + static S32 sTileResY; + LLSkyTex mSkyTex[6]; + LLHeavenBody mSun; + LLHeavenBody mMoon; + LLVector3 mSunDefaultPosition; + LLVector3 mSunAngVel; + F32 mAtmHeight; + LLVector3 mEarthCenter; + LLVector3 mCameraPosAgent; + F32 mBrightnessScale; + LLColor3 mBrightestPoint; + F32 mBrightnessScaleNew; + LLColor3 mBrightestPointNew; + F32 mBrightnessScaleGuess; + LLColor3 mBrightestPointGuess; + LLTranspMapSet mTransp; + LLHaze mHaze; + F32 mHazeConcentration; + BOOL mWeatherChange; + F32 mCloudDensity; + F32 mWind; + LLFace *mFace[FACE_COUNT]; + + BOOL mInitialized; + BOOL mForceUpdate; //flag to force instantaneous update of cubemap + LLVector3 mLastLightingDirection; + LLColor3 mLastTotalAmbient; + F32 mAmbientScale; + LLColor3 mNightColorShift; + F32 sInterpVal; + + LLColor4 mFogColor; + F32 mFogRatio; + F32 mWorldScale; + + LLColor4 mSunAmbient; + LLColor4 mMoonAmbient; + LLColor4 mTotalAmbient; + LLColor3 mSunDiffuse; + LLColor3 mMoonDiffuse; + LLColor4U mFadeColor; // Color to fade in from + + LLCubeMap *mCubeMap; // Cube map for the sky + S32 mDrawRefl; + + LLFrameTimer mUpdateTimer; + + LLPointer<LLImageGL> mScatterMap; + LLPointer<LLImageRaw> mScatterMapRaw; +}; + +// Utility functions +F32 azimuth(const LLVector3 &v); +F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE); + + +/* Proportion of light that is scattered into 'path' from 'in' over distance dt. */ +/* assumes that vectors 'path' and 'in' are normalized. Scattering coef / 2pi */ + +inline LLColor3 LLHaze::calcAirSca(const F32 h) +{ + static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel(); + return calcFalloff(h) * air_sca_sea_level; +} + +inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result) +{ + static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel(); + result = air_sca_sea_level; + result *= calcFalloff(h); +} + +// Given cos of the angle between direction of interest and zenith, +// compute transparency by interpolation of known values. +inline void LLTranspMap::calcAirTransp(const F32 cos_angle, LLColor3 &result) const +{ + if (cos_angle > 1.f) + { + result = mT[0]; + return; + } + if (cos_angle < mCosMaxAngle - 0.1f) + { + result.setVec(0.f, 0.f, 0.f); + return; + } + if (cos_angle < mCosMaxAngle) + { + result = mT[mMapSize-1]; + return; + } + + + const F32 relative = (1 - cos_angle)*mStepInv; + const S32 index = llfloor(relative); + const F32 dt = relative - index; + + if (index >= (mMapSize-1)) + { + result = mT[0]; + return; + } +// result = mT[index]; +// LLColor3 res2(mT[index+1]); +// result *= 1 - dt; +// res2 *= dt; +// result += res2; + + const LLColor3& color1 = mT[index]; + const LLColor3& color2 = mT[index + 1]; + + const F32 x1 = color1.mV[VX]; + const F32 x2 = color2.mV[VX]; + result.mV[VX] = x1 - dt * (x1 - x2); + + const F32 y1 = color1.mV[VY]; + const F32 y2 = color2.mV[VY]; + result.mV[VY] = y1 - dt * (y1 - y2); + + const F32 z1 = color1.mV[VZ]; + const F32 z2 = color2.mV[VZ]; + result.mV[VZ] = z1 - dt * (z1 - z2); +} + + + +// Returns the translucency of the atmosphere along the ray in the sky. +// dir is assumed to be normalized +inline void LLTranspMapSet::calcTransp(const F32 cos_angle, const F32 h, LLColor3 &result) const +{ + S32 indx = 0; + F32 dt = 0.f; + const S32 status = lerp(dt, indx, h); + + if (status < 0) + { + mTransp[0].calcAirTransp(cos_angle, result); + return; + } + if (status > 0) + { + mTransp[NO_STEPS].calcAirTransp(cos_angle, result); + return; + } + + mTransp[indx].calcAirTransp(cos_angle, result); + result *= 1 - dt; + + LLColor3 transp_above; + + mTransp[indx + 1].calcAirTransp(cos_angle, transp_above); + transp_above *= dt; + result += transp_above; +} + + +inline LLColor3 LLTranspMapSet::calcTransp(const F32 cos_angle, const F32 h) const +{ + LLColor3 result; + S32 indx = 0; + F32 dt = 0; + const S32 status = lerp(dt, indx, h); + + if (status < 0) + { + mTransp[0].calcAirTransp(cos_angle, result); + return result; + } + if (status > 0) + { + mTransp[NO_STEPS].calcAirTransp(cos_angle, result); + return result; + } + + mTransp[indx].calcAirTransp(cos_angle, result); + result *= 1 - dt; + + LLColor3 transp_above; + + mTransp[indx + 1].calcAirTransp(cos_angle, transp_above); + transp_above *= dt; + result += transp_above; + return result; +} + + +// Returns -1 if height < 0; +1 if height > max height; 0 if within range +inline S32 LLTranspMapSet::lerp(F32& dt, S32& indx, const F32 h) const +{ + static S32 last_indx = 0; + + if (h < 0) + { + return -1; + } + if (h > getLastHeight()) + { + return 1; + } + + if (h < mHeights[last_indx]) + { + indx = last_indx-1; + while (mHeights[indx] > h) + { + indx--; + } + last_indx = indx; + } + else if (h > mHeights[last_indx+1]) + { + indx = last_indx+1; + while (mHeights[indx+1] < h) + { + indx++; + } + last_indx = indx; + } + else + { + indx = last_indx; + } + + const F32 h_below = mHeights[indx]; + const F32 h_above = mHeights[indx+1]; + dt = (h - h_below) / (h_above - h_below); + return 0; +} + +#endif |