diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl index 025bcdaf3e18bf4940d2fdb09568f23fc004b1b4..13619a82d30bcdff504e9f7aba30e7e707f9096a 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl @@ -35,10 +35,26 @@ float getDepth(vec2 pos_screen); vec4 getWaterFogView(vec3 pos); +uniform int above_water; + void main() { vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5; float depth = getDepth(tc.xy); + + if (above_water > 0) + { + // we want to depth test when the camera is above water, but some GPUs have a hard time + // with depth testing against render targets that are bound for sampling in the same shader + // so we do it manually here + + float cur_depth = vary_fragcoord.z/vary_fragcoord.w*0.5+0.5; + if (cur_depth > depth) + { + discard; + } + } + vec4 pos = getPositionWithDepth(tc, depth); vec4 norm = texture(normalMap, tc); diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index ddb1b7968111df9fcd38ba274fda220363d981ad..223e55eb69487d45edac47d99e7a27cfe92bed01 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -30,7 +30,6 @@ uniform sampler2D bumpMap; #ifdef TRANSPARENT_WATER uniform sampler2D screenTex; -uniform sampler2D screenDepth; #endif uniform vec4 fogCol; diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index b7292832f6fafcca3afbf8d2e2cf55e7c82c19a4..34281281536018c6c15371fded9a5d75bdb2a17d 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -76,7 +76,7 @@ uniform sampler2D bumpMap2; uniform float blend_factor; #ifdef TRANSPARENT_WATER uniform sampler2D screenTex; -uniform sampler2D screenDepth; +uniform sampler2D depthMap; #endif uniform sampler2D refTex; @@ -210,7 +210,7 @@ void main() #ifdef TRANSPARENT_WATER vec4 fb = texture(screenTex, distort2); - float depth = texture(screenDepth, distort2).r; + float depth = texture(depthMap, distort2).r; vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0)); if (refPos.z > pos.z-0.05) @@ -218,7 +218,7 @@ void main() //we sampled an above water sample, don't distort distort2 = distort; fb = texture(screenTex, distort2); - depth = texture(screenDepth, distort2).r; + depth = texture(depthMap, distort2).r; refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0)); } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 14f3142e1b55c3c942b02bf3996d12d862488e90..ca93815de7cf4dc983a4341cbefd22ab3f4ee022 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -206,7 +206,7 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) } } - gPipeline.bindDeferredShader(*shader); + gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis); //bind normal map S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); @@ -238,7 +238,6 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) // bind reflection texture from RenderTarget S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); - S32 screenDepth = shader->enableTexture(LLShaderMgr::WATER_SCREENDEPTH); F32 screenRes[] = { 1.f / gGLViewport[2], 1.f / gGLViewport[3] }; @@ -255,11 +254,6 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); } - if (screenDepth > -1) - { - gGL.getTexUnit(screenDepth)->bind(&gPipeline.mWaterDis, true); - } - if (mShaderLevel == 1) { fog_color.mV[VW] = log(fog_density) / log(2); @@ -342,7 +336,6 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) shader->disableTexture(LLShaderMgr::BUMP_MAP); shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); shader->disableTexture(LLShaderMgr::WATER_REFTEX); - shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); // clean up gPipeline.unbindDeferredShader(*shader); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f80a053e162042eba16864a38450270ebc918f8b..318fcb721577e15748ded2d054545e048ddd73af 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -875,10 +875,9 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mRT->deferredScreen.shareDepthBuffer(mRT->screen); - if (!is_aux_alloc && LLPipeline::sRenderTransparentWater) - { //water reflection texture - if (!mWaterDis.allocate(resX, resY, screenFormat, true)) return false; - } + //water reflection texture (always needed as scratch space whether or not transparent water is enabled) + mWaterDis.allocate(resX, resY, GL_RGBA16F, true); + //if (shadow_detail > 0 || ssao || gSavedSettings.getU32("RenderSharpenMethod") != ALRenderUtil::SHARPEN_NONE) { //only need mRT->deferredLight for shadows OR ssao OR sharpening @@ -7610,7 +7609,7 @@ void LLPipeline::bindDeferredShaderFast(LLGLSLShader& shader) } } -void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target) +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target, LLRenderTarget* depth_target) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; LLRenderTarget* deferred_target = &mRT->deferredScreen; @@ -7649,7 +7648,14 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage()); if (channel > -1) { - gGL.getTexUnit(channel)->bind(deferred_target, TRUE); + if (depth_target) + { + gGL.getTexUnit(channel)->bind(depth_target, TRUE); + } + else + { + gGL.getTexUnit(channel)->bind(deferred_target, TRUE); + } stop_glerror(); } @@ -8310,16 +8316,41 @@ void LLPipeline::doAtmospherics() if (RenderDeferredAtmospheric) { + { + // copy depth buffer for use in haze shader (use water displacement map as temp storage) + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + + LLRenderTarget& src = gPipeline.mRT->screen; + LLRenderTarget& depth_src = gPipeline.mRT->deferredScreen; + LLRenderTarget& dst = gPipeline.mWaterDis; + + mRT->screen.flush(); + dst.bindTarget(); + gCopyDepthProgram.bind(); + + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + + gGL.getTexUnit(diff_map)->bind(&src); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); + + gGL.setColorMask(false, false); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + dst.flush(); + mRT->screen.bindTarget(); + } + 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); + bindDeferredShader(haze_shader, nullptr, &mWaterDis); LLEnvironment& environment = LLEnvironment::instance(); haze_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); @@ -8345,6 +8376,32 @@ void LLPipeline::doWaterHaze() if (RenderDeferredAtmospheric) { + // copy depth buffer for use in haze shader (use water displacement map as temp storage) + { + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + + LLRenderTarget& src = gPipeline.mRT->screen; + LLRenderTarget& depth_src = gPipeline.mRT->deferredScreen; + LLRenderTarget& dst = gPipeline.mWaterDis; + + mRT->screen.flush(); + dst.bindTarget(); + gCopyDepthProgram.bind(); + + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + + gGL.getTexUnit(diff_map)->bind(&src); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); + + gGL.setColorMask(false, false); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + dst.flush(); + mRT->screen.bindTarget(); + } + LLGLEnable blend(GL_BLEND); gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_SOURCE_ALPHA, LLRender::BF_ZERO, LLRender::BF_SOURCE_ALPHA); @@ -8354,7 +8411,7 @@ void LLPipeline::doWaterHaze() LLGLSLShader& haze_shader = gHazeWaterProgram; LL_PROFILE_GPU_ZONE("haze"); - bindDeferredShader(haze_shader); + bindDeferredShader(haze_shader, nullptr, &mWaterDis); haze_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV); @@ -8372,7 +8429,7 @@ void LLPipeline::doWaterHaze() else { //render water patches like LLDrawPoolWater does - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); + LLGLDepthTest depth(GL_FALSE); LLGLDisable cull(GL_CULL_FACE); gGLLastMatrix = NULL; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index d20a833dea08387a77ef6e2c99b6e5fcc6b285d2..8507e5d5e6595626cc46ee252f7b8045a301f47a 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -285,7 +285,7 @@ class LLPipeline // if setup is true, wil lset texture compare mode function and filtering options void bindShadowMaps(LLGLSLShader& shader); void bindDeferredShaderFast(LLGLSLShader& shader); - void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr); + void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr, LLRenderTarget* depth_target = nullptr); void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); void unbindDeferredShader(LLGLSLShader& shader);