summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl16
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterHazeV.glsl59
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/waterF.glsl3
-rw-r--r--indra/newview/lldrawpool.cpp8
-rw-r--r--indra/newview/lldrawpool.h5
-rw-r--r--indra/newview/lleventpoll.cpp22
-rw-r--r--indra/newview/llsettingsvo.cpp10
-rw-r--r--indra/newview/llviewercamera.cpp22
-rw-r--r--indra/newview/llviewershadermgr.cpp2
-rw-r--r--indra/newview/pipeline.cpp156
-rw-r--r--indra/newview/pipeline.h10
14 files changed, 255 insertions, 81 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 2798c59f1c..1de8b25a7d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -82,12 +82,12 @@ void main()
vec3 additive;
vec3 atten;
calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten);
-#endif
-
-#ifndef IS_HUD
color.rgb = srgb_to_linear(color.rgb);
+
+#ifdef IS_ALPHA
color.rgb = atmosFragLighting(color.rgb, additive, atten);
+#endif
vec4 fogged = applyWaterFogViewLinear(pos, vec4(color.rgb, final_alpha));
color.rgb = fogged.rgb;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl
index 7b77a2f5fb..e8f7d73f1f 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl
@@ -68,23 +68,21 @@ void main()
calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
vec3 sunlit_linear = srgb_to_linear(sunlit);
- vec3 amblit_linear = amblit;
-
+
+ // mask off atmospherics below water (when camera is under water)
bool do_atmospherics = false;
-
- // mask off atmospherics below water
- if (dot(pos.xyz, waterPlane.xyz) + waterPlane.w > 0.0)
+
+ if (dot(vec3(0), waterPlane.xyz) + waterPlane.w > 0.0 ||
+ dot(pos.xyz, waterPlane.xyz) + waterPlane.w > 0.0)
{
do_atmospherics = true;
}
+
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
- if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
- {
- }
- else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
+ if (depth >= 1.0)
{
//should only be true of WL sky, just port over base color value
discard;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl
index f63d70cbd7..025bcdaf3e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl
@@ -26,7 +26,7 @@
out vec4 frag_color;
// Inputs
-in vec2 vary_fragcoord;
+in vec4 vary_fragcoord;
uniform sampler2D normalMap;
@@ -37,20 +37,11 @@ vec4 getWaterFogView(vec3 pos);
void main()
{
- vec2 tc = vary_fragcoord.xy;
+ vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5;
float depth = getDepth(tc.xy);
vec4 pos = getPositionWithDepth(tc, depth);
vec4 norm = texture(normalMap, tc);
- if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
- {
- }
- else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
- {
- //should only be true of WL sky, just port over base color value
- discard;
- }
-
vec4 fogged = getWaterFogView(pos.xyz);
frag_color.rgb = max(fogged.rgb, vec3(0)); //output linear since local lights will be added to this shader's results
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeV.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeV.glsl
new file mode 100644
index 0000000000..16381a5d51
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeV.glsl
@@ -0,0 +1,59 @@
+/**
+ * @file class3/deferred/waterHazeV.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+in vec3 position;
+
+uniform vec2 screen_res;
+
+out vec4 vary_fragcoord;
+
+// forwards
+void setAtmosAttenuation(vec3 c);
+void setAdditiveColor(vec3 c);
+
+uniform vec4 waterPlane;
+
+uniform int above_water;
+
+uniform mat4 modelview_projection_matrix;
+
+void main()
+{
+ //transform vertex
+ vec4 pos = vec4(position.xyz, 1.0);
+
+ if (above_water > 0)
+ {
+ pos = modelview_projection_matrix*pos;
+ }
+
+ gl_Position = pos;
+
+ // appease OSX GLSL compiler/linker by touching all the varyings we said we would
+ setAtmosAttenuation(vec3(1));
+ setAdditiveColor(vec3(0));
+
+ vary_fragcoord = pos;
+}
diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
index 924f356f35..ddb1b79681 100644
--- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
@@ -77,5 +77,7 @@ void main()
vec4 fb = vec4(waterFogColorLinear, 0.0);
#endif
- frag_color = max(applyWaterFogViewLinearNoClip(vary_position, fb), vec4(0));
+ fb = applyWaterFogViewLinearNoClip(vary_position, fb);
+
+ frag_color = max(fb, vec4(0));
}
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
index 8bc5f3cc50..f53bc2e13e 100644
--- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -32,7 +32,6 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
#endif
vec3 scaleSoftClipFragLinear(vec3 l);
-vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
@@ -281,8 +280,6 @@ void main()
color = ((1.0 - f) * color) + fb.rgb;
- color = atmosFragLightingLinear(color, additive, atten);
-
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05);
frag_color = max(vec4(color, spec), vec4(0));
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index fca0f1c978..50210b06c4 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -320,6 +320,14 @@ void LLFacePool::addFaceReference(LLFace *facep)
}
}
+void LLFacePool::pushFaceGeometry()
+{
+ for (LLFace* const& face : mDrawFace)
+ {
+ face->renderIndexed();
+ }
+}
+
BOOL LLFacePool::verify() const
{
BOOL ok = TRUE;
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 5414dba6bf..4300670445 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -118,8 +118,8 @@ public:
virtual LLViewerTexture* getTexture() = 0;
virtual BOOL isFacePool() { return FALSE; }
virtual void resetDrawOrders() = 0;
+ virtual void pushFaceGeometry() {}
-protected:
S32 mShaderLevel;
S32 mId;
U32 mType; // Type of draw pool
@@ -429,6 +429,9 @@ public:
BOOL isFacePool() { return TRUE; }
+ // call drawIndexed on every draw face
+ void pushFaceGeometry();
+
friend class LLFace;
friend class LLPipeline;
public:
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 26782e53f0..670a780fdd 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -102,6 +102,7 @@ namespace Details
void LLEventPollImpl::handleMessage(const LLSD& content)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
std::string msg_name = content["message"];
LLSD message;
message["sender"] = mSenderIp;
@@ -149,6 +150,12 @@ namespace Details
mAdapter = httpAdapter;
+ LL::WorkQueue::ptr_t main_queue = nullptr;
+
+#if 1
+ main_queue = LL::WorkQueue::getInstance("mainloop");
+#endif
+
// continually poll for a server update until we've been flagged as
// finished
while (!mDone)
@@ -266,13 +273,26 @@ namespace Details
// was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << acknowledge << ")" << LL_ENDL;
+
LLSD::array_const_iterator i = events.beginArray();
LLSD::array_const_iterator end = events.endArray();
for (; i != end; ++i)
{
if (i->has("message"))
{
- handleMessage(*i);
+ if (main_queue)
+ { // shuttle to a sensible spot in the main thread instead
+ // of wherever this coroutine happens to be executing
+ const LLSD& msg = *i;
+ main_queue->post([this, msg]()
+ {
+ handleMessage(msg);
+ });
+ }
+ else
+ {
+ handleMessage(*i);
+ }
}
}
}
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 2f65f3dec3..7009fb98ab 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -63,6 +63,7 @@
#include <boost/algorithm/string/replace.hpp>
#include "llinventoryobserver.h"
#include "llinventorydefines.h"
+#include "llworld.h"
#include "lltrans.h"
@@ -989,6 +990,15 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force)
{
F32 water_height = env.getWaterHeight();
+ if (LLViewerCamera::instance().cameraUnderWater())
+ { // when the camera is under water, use the water height at the camera position
+ LLViewerRegion* region = LLWorld::instance().getRegionFromPosAgent(LLViewerCamera::instance().getOrigin());
+ if (region)
+ {
+ water_height = region->getWaterHeight();
+ }
+ }
+
//transform water plane to eye space
glh::vec3f norm(0.f, 0.f, 1.f);
glh::vec3f p(0.f, 0.f, water_height);
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index b926631ebe..4134e35f87 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -112,12 +112,16 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center, const LLVecto
mLastPointOfInterest = point_of_interest;
- LLViewerRegion *regp = gAgent.getRegion();
- F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f;
+ LLViewerRegion* regp = LLWorld::instance().getRegionFromPosAgent(getOrigin());
+ if (!regp)
+ {
+ regp = gAgent.getRegion();
+ }
+
+ F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f;
LLVector3 origin = center;
- if (LLEnvironment::instance().getCurrentWater()->getFogMod() != 1.f)
{
if (origin.mV[2] > water_height)
{
@@ -758,11 +762,19 @@ LLVector3 LLViewerCamera::roundToPixel(const LLVector3 &pos_agent)
BOOL LLViewerCamera::cameraUnderWater() const
{
- if(!gAgent.getRegion())
+ LLViewerRegion* regionp = LLWorld::instance().getRegionFromPosAgent(getOrigin());
+
+ if (!regionp)
+ {
+ regionp = gAgent.getRegion();
+ }
+
+ if(!regionp)
{
return FALSE ;
}
- return getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight();
+
+ return getOrigin().mV[VZ] < regionp->getWaterHeight();
}
BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 2c2ae022d7..3225299493 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -1804,7 +1804,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gHazeWaterProgram.mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED] > 2;
gHazeWaterProgram.clearPermutations();
- gHazeWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER));
+ gHazeWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterHazeV.glsl", GL_VERTEX_SHADER));
gHazeWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterHazeF.glsl", GL_FRAGMENT_SHADER));
gHazeWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 52afe16799..7b1e5a55d1 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3877,6 +3877,20 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
LLGLEnable cull(GL_CULL_FACE);
+ bool done_atmospherics = LLPipeline::sRenderingHUDs; //skip atmospherics on huds
+ bool done_water_haze = done_atmospherics;
+
+ // do atmospheric haze just before post water alpha
+ U32 atmospherics_pass = LLDrawPool::POOL_ALPHA_POST_WATER;
+
+ if (LLPipeline::sUnderWaterRender)
+ { // if under water, do atmospherics just before the water pass
+ atmospherics_pass = LLDrawPool::POOL_WATER;
+ }
+
+ // do water haze just before pre water alpha
+ U32 water_haze_pass = LLDrawPool::POOL_ALPHA_PRE_WATER;
+
calcNearbyLights(camera);
setupHWLights();
@@ -3896,6 +3910,18 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
cur_type = poolp->getType();
+ if (cur_type >= atmospherics_pass && !done_atmospherics)
+ { // do atmospherics against depth buffer before rendering alpha
+ doAtmospherics();
+ done_atmospherics = true;
+ }
+
+ if (cur_type >= water_haze_pass && !done_water_haze)
+ { // do water haze against depth buffer before rendering alpha
+ doWaterHaze();
+ done_water_haze = true;
+ }
+
pool_set_t::iterator iter2 = iter1;
if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
{
@@ -8153,52 +8179,6 @@ void LLPipeline::renderDeferredLighting()
}
}
-
-
- if (RenderDeferredAtmospheric)
- {
- LLGLEnable blend(GL_BLEND);
- gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_SOURCE_ALPHA);
- gGL.setColorMask(true, false);
-
- for (U32 i = 0; i < 2; ++i)
- {
- // apply haze
- LLGLSLShader &haze_shader = i == 0 ? gHazeProgram : gHazeWaterProgram;
-
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - haze");
- LL_PROFILE_GPU_ZONE("haze");
- bindDeferredShader(haze_shader);
-
- static LLCachedControl<F32> ssao_scale(gSavedSettings, "RenderSSAOIrradianceScale", 0.5f);
- static LLCachedControl<F32> ssao_max(gSavedSettings, "RenderSSAOIrradianceMax", 0.25f);
- static LLStaticHashedString ssao_scale_str("ssao_irradiance_scale");
- static LLStaticHashedString ssao_max_str("ssao_irradiance_max");
-
- haze_shader.uniform1f(ssao_scale_str, ssao_scale);
- haze_shader.uniform1f(ssao_max_str, ssao_max);
-
- LLEnvironment &environment = LLEnvironment::instance();
- haze_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- haze_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
-
- haze_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV);
-
- {
- LLGLDepthTest depth(GL_FALSE);
-
- // full screen blit
- mScreenTriangleVB->setBuffer();
- mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- }
-
- unbindDeferredShader(haze_shader);
- }
-
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-
-
gGL.setColorMask(true, true);
}
@@ -8254,6 +8234,90 @@ void LLPipeline::renderDeferredLighting()
gGL.setColorMask(true, true);
}
+void LLPipeline::doAtmospherics()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+
+ if (RenderDeferredAtmospheric)
+ {
+ LLGLEnable blend(GL_BLEND);
+ gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_SOURCE_ALPHA, LLRender::BF_ZERO, LLRender::BF_SOURCE_ALPHA);
+
+ gGL.setColorMask(true, true);
+
+ // apply haze
+ LLGLSLShader& haze_shader = gHazeProgram;
+
+ LL_PROFILE_GPU_ZONE("haze");
+ bindDeferredShader(haze_shader);
+
+ LLEnvironment& environment = LLEnvironment::instance();
+ haze_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
+ haze_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
+
+ haze_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV);
+
+ LLGLDepthTest depth(GL_FALSE);
+
+ // full screen blit
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+ unbindDeferredShader(haze_shader);
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+}
+
+void LLPipeline::doWaterHaze()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+
+ if (RenderDeferredAtmospheric)
+ {
+ LLGLEnable blend(GL_BLEND);
+ gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_SOURCE_ALPHA, LLRender::BF_ZERO, LLRender::BF_SOURCE_ALPHA);
+
+ gGL.setColorMask(true, true);
+
+ // apply haze
+ LLGLSLShader& haze_shader = gHazeWaterProgram;
+
+ LL_PROFILE_GPU_ZONE("haze");
+ bindDeferredShader(haze_shader);
+
+ haze_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV);
+
+ static LLStaticHashedString above_water_str("above_water");
+ haze_shader.uniform1i(above_water_str, sUnderWaterRender ? -1 : 1);
+
+ if (LLPipeline::sUnderWaterRender)
+ {
+ LLGLDepthTest depth(GL_FALSE);
+
+ // full screen blit
+ mScreenTriangleVB->setBuffer();
+ mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
+ else
+ {
+ //render water patches like LLDrawPoolWater does
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ mWaterPool->pushFaceGeometry();
+ }
+
+ unbindDeferredShader(haze_shader);
+
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+}
+
void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
{
//construct frustum
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 6e4c9c7a97..bbed7cad92 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -318,6 +318,16 @@ public:
void unbindReflectionProbes(LLGLSLShader& shader);
void renderDeferredLighting();
+
+ // apply atmospheric haze based on contents of color and depth buffer
+ // should be called just before rendering water when camera is under water
+ // and just before rendering alpha when camera is above water
+ void doAtmospherics();
+
+ // apply water haze based on contents of color and depth buffer
+ // should be called just before rendering pre-water alpha objects
+ void doWaterHaze();
+
void postDeferredGammaCorrect(LLRenderTarget* screen_target);
void generateSunShadow(LLCamera& camera);