diff options
author | Jonathan "Geenz" Goodman <geenz@lindenlab.com> | 2025-02-07 05:55:47 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-07 05:55:47 -0500 |
commit | 93a88e602545828c0298b20ff0375f191d1f6d9a (patch) | |
tree | cb098bfa5eeb4b0d784a9ed6aec3b5fe7f1a0245 /indra/newview | |
parent | 317cd6e66e65256eda6441c06fa32e55eee99fa3 (diff) |
Water Exclusion Surfaces (#3517)
* #3455 Add support for water exclusion surfaces
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl | 57 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl | 43 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl | 14 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl | 8 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class3/environment/waterF.glsl | 13 | ||||
-rw-r--r-- | indra/newview/lldrawpool.cpp | 4 | ||||
-rw-r--r-- | indra/newview/lldrawpool.h | 3 | ||||
-rw-r--r-- | indra/newview/lldrawpoolwater.cpp | 48 | ||||
-rw-r--r-- | indra/newview/lldrawpoolwater.h | 2 | ||||
-rw-r--r-- | indra/newview/lldrawpoolwaterexclusion.cpp | 79 | ||||
-rw-r--r-- | indra/newview/lldrawpoolwaterexclusion.h | 61 | ||||
-rw-r--r-- | indra/newview/llviewershadermgr.cpp | 12 | ||||
-rw-r--r-- | indra/newview/llviewershadermgr.h | 1 | ||||
-rw-r--r-- | indra/newview/llviewertexturelist.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 12 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 60 | ||||
-rw-r--r-- | indra/newview/pipeline.h | 6 |
18 files changed, 396 insertions, 31 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5bcfddfe25..d2736c7c12 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -156,6 +156,7 @@ set(viewer_SOURCE_FILES lldrawpooltree.cpp lldrawpoolwater.cpp lldrawpoolwlsky.cpp + lldrawpoolwaterexclusion.cpp lldynamictexture.cpp llemote.cpp llenvironment.cpp @@ -823,6 +824,7 @@ set(viewer_HEADER_FILES lldrawpooltree.h lldrawpoolwater.h lldrawpoolwlsky.h + lldrawpoolwaterexclusion.h lldynamictexture.h llemote.h llenvironment.h diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl new file mode 100644 index 0000000000..dea76da5a5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl @@ -0,0 +1,57 @@ +/** + * @file simpleColorF.glsl + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, 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$ + */ + +out vec4 frag_color; + +in vec4 vertex_color; +in vec4 vertex_position; + +uniform vec4 waterPlane; +uniform float waterSign; + +void waterClip(vec3 pos) +{ + // TODO: make this less branchy + if (waterSign > 0) + { + if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < 0.0) + { + discard; + } + } + else + { + if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) > 0.0) + { + discard; + } + } +} + +void main() +{ + + frag_color = vertex_color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl new file mode 100644 index 0000000000..4564e56313 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl @@ -0,0 +1,43 @@ +/** + * @file simpleNoAtmosV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, 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$ + */ + +uniform mat4 modelview_matrix; +uniform mat4 modelview_projection_matrix; + +uniform vec4 color; + +in vec3 position; + +out vec4 vertex_color; +out vec4 vertex_position; + +void main() +{ + //transform vertex + vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); + vertex_position = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = vertex_position; + vertex_color = color; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl index ee49b4baae..091c25d15e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl @@ -35,13 +35,25 @@ vec4 getWaterFogView(vec3 pos); uniform int above_water; +uniform sampler2D exclusionTex; + void main() { vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5; float depth = getDepth(tc.xy); + float mask = texture(exclusionTex, tc.xy).r; if (above_water > 0) { + // Just discard if we're in the exclusion mask. + // The previous invisiprim hack we're replacing would also crank up water fog desntiy. + // But doing that makes exclusion surfaces very slow as we'd need to render even more into the mask. + // - Geenz 2025-02-06 + if (mask < 1) + { + discard; + } + // 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 @@ -51,12 +63,14 @@ void main() { discard; } + } vec4 pos = getPositionWithDepth(tc, depth); vec4 fogged = getWaterFogView(pos.xyz); fogged.a = max(pow(fogged.a, 1.7), 0); + frag_color = max(fogged, vec4(0)); //output linear since local lights will be added to this shader's results } diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index 1c02dc764d..fa410e9f11 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -26,6 +26,7 @@ out vec4 frag_color; uniform sampler2D bumpMap; +uniform sampler2D exclusionTex; #ifdef TRANSPARENT_WATER uniform sampler2D screenTex; @@ -59,6 +60,9 @@ void mirrorClip(vec3 position); void main() { mirrorClip(vary_position); + vec2 screen_tc = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + float water_mask = texture(exclusionTex, screen_tc).r; + vec4 color; //get detail normals @@ -68,8 +72,8 @@ void main() vec3 wavef = normalize(wave1+wave2+wave3); //figure out distortion vector (ripply) - vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - distort = distort+wavef.xy*refScale; + vec2 distort = screen_tc; + distort = mix(distort, distort+wavef.xy*refScale, water_mask); #ifdef TRANSPARENT_WATER vec4 fb = texture(screenTex, distort); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index f8aa684433..7027e3796e 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -88,7 +88,7 @@ uniform sampler2D screenTex; uniform sampler2D depthMap; #endif -uniform sampler2D refTex; +uniform sampler2D exclusionTex; uniform float sunAngle; uniform float sunAngle2; @@ -252,6 +252,8 @@ void main() float shadow = 1.0f; + float water_mask = texture(exclusionTex, distort).r; + #ifdef HAS_SUN_SHADOW shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, distort); #endif @@ -266,9 +268,8 @@ void main() vec3 refPos = getPositionWithNDC(vec3(distort*2.0-vec2(1.0), depth*2.0-1.0)); // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". - fade = max(0,min(1, (pos.z - refPos.z) / 10)); + fade = max(0,min(1, (pos.z - refPos.z) / 10)) * water_mask; distort2 = mix(distort, distort2, min(1, fade * 10)); - depth = texture(depthMap, distort2).r; refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0)); @@ -282,6 +283,9 @@ void main() #else vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0)); + + if (water_mask < 1) + discard; #endif float metallic = 1.0; @@ -333,6 +337,7 @@ void main() color = mix(fb.rgb, color, fade); float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05); - frag_color = min(vec4(1),max(vec4(color.rgb, spec), vec4(0))); + + frag_color = min(vec4(1),max(vec4(color.rgb, spec * water_mask), vec4(0))); } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 7bd5206453..e60b3eb5dc 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -42,6 +42,7 @@ #include "lldrawpooltree.h" #include "lldrawpoolterrain.h" #include "lldrawpoolwater.h" +#include "lldrawpoolwaterexclusion.h" #include "llface.h" #include "llviewerobjectlist.h" // For debug listing. #include "pipeline.h" @@ -119,6 +120,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0) case POOL_GLTF_PBR_ALPHA_MASK: poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK); break; + case POOL_WATEREXCLUSION: + poolp = new LLDrawPoolWaterExclusion(); + break; default: LL_ERRS() << "Unknown draw pool type!" << LL_ENDL; return NULL; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index bc412214c7..1c8864a9df 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -55,6 +55,7 @@ public: // based on fill rate and likelihood to occlude future passes (faster, large occluders first). // POOL_SKY = 1, + POOL_WATEREXCLUSION, POOL_WL_SKY, POOL_SIMPLE, POOL_FULLBRIGHT, @@ -140,7 +141,7 @@ public: PASS_GRASS, PASS_FULLBRIGHT, PASS_FULLBRIGHT_RIGGED, - PASS_INVISIBLE, + PASS_INVISIBLE, // Formerly, invisiprims. Now, water exclusion surfaces. PASS_INVISIBLE_RIGGED, PASS_INVISI_SHINY, PASS_INVISI_SHINY_RIGGED, diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 53d6e528b6..c27f5ef486 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -236,6 +236,8 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) gGL.getTexUnit(bumpTex2)->bind(tex_b); } + shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask); + // bind reflection texture from RenderTarget S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); @@ -307,30 +309,11 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) LLGLDisable cullface(GL_CULL_FACE); - LLVOWater* water = nullptr; - for (LLFace* const& face : mDrawFace) - { - if (!face) continue; - water = static_cast<LLVOWater*>(face->getViewerObject()); - if (!water) continue; - - if ((bool)edge == (bool)water->getIsEdgePatch()) - { - face->renderIndexed(); - - // Note non-void water being drawn, updates required - if (!edge) // SL-16461 remove !LLPipeline::sUseOcclusion check - { - sNeedsReflectionUpdate = true; - sNeedsDistortionUpdate = true; - } - } - } + pushWaterPlanes(edge); shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); shader->disableTexture(LLShaderMgr::BUMP_MAP); - shader->disableTexture(LLShaderMgr::WATER_REFTEX); // clean up gPipeline.unbindDeferredShader(*shader); @@ -345,6 +328,31 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) gGL.setColorMask(true, false); } +void LLDrawPoolWater::pushWaterPlanes(int pass) +{ + LLVOWater* water = nullptr; + for (LLFace* const& face : mDrawFace) + { + if (!face) + continue; + water = static_cast<LLVOWater*>(face->getViewerObject()); + if (!water) + continue; + + if ((bool)pass == (bool)water->getIsEdgePatch()) + { + face->renderIndexed(); + + // Note non-void water being drawn, updates required + if (!pass) // SL-16461 remove !LLPipeline::sUseOcclusion check + { + sNeedsReflectionUpdate = true; + sNeedsDistortionUpdate = true; + } + } + } +} + LLViewerTexture *LLDrawPoolWater::getDebugTexture() { return LLViewerTextureManager::getFetchedTexture(IMG_SMOKE); diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index f64477a059..7fc9b68bcf 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -74,6 +74,8 @@ public: void setOpaqueTexture(const LLUUID& opaqueTextureId); void setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId); + void pushWaterPlanes(int pass); + protected: void renderOpaqueLegacyWater(); }; diff --git a/indra/newview/lldrawpoolwaterexclusion.cpp b/indra/newview/lldrawpoolwaterexclusion.cpp new file mode 100644 index 0000000000..d796bf39bf --- /dev/null +++ b/indra/newview/lldrawpoolwaterexclusion.cpp @@ -0,0 +1,79 @@ +/** + * @file lldrawpool.cpp + * @brief LLDrawPoolMaterials class implementation + * @author Jonathan "Geenz" Goodman + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lldrawpoolwaterexclusion.h" +#include "llviewershadermgr.h" +#include "pipeline.h" +#include "llglcommonfunc.h" +#include "llvoavatar.h" +#include "lldrawpoolwater.h" + +LLDrawPoolWaterExclusion::LLDrawPoolWaterExclusion() : LLRenderPass(LLDrawPool::POOL_WATEREXCLUSION) +{ + LL_INFOS("DPInvisible") << "Creating water exclusion draw pool" << LL_ENDL; +} + + +void LLDrawPoolWaterExclusion::render(S32 pass) +{ // render invisiprims + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; // LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE); + + if (gPipeline.shadersLoaded()) + { + gDrawColorProgram.bind(); + } + + + LLGLDepthTest depth(GL_TRUE); + gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 1, 1, 1, 1); + + LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER); + if (pwaterpool) + { + // Just treat our water planes as double sided for the purposes of generating the exclusion mask. + LLGLDisable cullface(GL_CULL_FACE); + pwaterpool->pushWaterPlanes(0); + + // Take care of the edge water tiles. + pwaterpool->pushWaterPlanes(1); + } + + gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 0, 0, 0, 1); + + static LLStaticHashedString waterSign("waterSign"); + gDrawColorProgram.uniform1f(waterSign, 1.f); + + pushBatches(LLRenderPass::PASS_INVISIBLE, false, false); + + + if (gPipeline.shadersLoaded()) + { + gDrawColorProgram.unbind(); + } +} diff --git a/indra/newview/lldrawpoolwaterexclusion.h b/indra/newview/lldrawpoolwaterexclusion.h new file mode 100644 index 0000000000..e95721a443 --- /dev/null +++ b/indra/newview/lldrawpoolwaterexclusion.h @@ -0,0 +1,61 @@ +/** + * @file lldrawpoolwaterexclusion.h + * @brief LLDrawPoolWaterExclusion class definition + * @author Jonathan "Geenz" Goodman + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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$ + */ + +#ifndef LL_LLDRAWPOOLWATEREXCLUSION_H +#define LL_LLDRAWPOOLWATEREXCLUSION_H + +#include "v4coloru.h" +#include "v2math.h" +#include "v3math.h" +#include "llvertexbuffer.h" +#include "lldrawpool.h" + +class LLViewerTexture; +class LLDrawInfo; +class LLGLSLShader; + +class LLDrawPoolWaterExclusion : public LLRenderPass +{ +public: + LLDrawPoolWaterExclusion(); + + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + virtual void prerender() {} + + virtual void render(S32 pass = 0); + virtual void beginRenderPass(S32 pass) {} + virtual void endRenderPass(S32 pass) {} + virtual S32 getNumPasses() { return 1; } +}; + +#endif // LL_LLDRAWPOOLWATEREXCLUSION_H diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 2619bbbfcb..ac4519e593 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -101,6 +101,7 @@ LLGLSLShader gReflectionProbeDisplayProgram; LLGLSLShader gCopyProgram; LLGLSLShader gCopyDepthProgram; LLGLSLShader gPBRTerrainBakeProgram; +LLGLSLShader gDrawColorProgram; //object shaders LLGLSLShader gObjectPreviewProgram; @@ -3355,6 +3356,17 @@ bool LLViewerShaderMgr::loadShadersInterface() success = gCopyDepthProgram.createShader(); } + if (success) + { + gDrawColorProgram.mName = "Draw Color Shader"; + gDrawColorProgram.mShaderFiles.clear(); + gDrawColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoAtmosV.glsl", GL_VERTEX_SHADER)); + gDrawColorProgram.mShaderFiles.push_back(make_pair("objects/simpleColorF.glsl", GL_FRAGMENT_SHADER)); + gDrawColorProgram.clearPermutations(); + gDrawColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gDrawColorProgram.createShader(); + } + if (gSavedSettings.getBOOL("LocalTerrainPaintEnabled")) { if (success) diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index b08796025a..6326de9a6b 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -175,6 +175,7 @@ extern LLGLSLShader gReflectionProbeDisplayProgram; extern LLGLSLShader gCopyProgram; extern LLGLSLShader gCopyDepthProgram; extern LLGLSLShader gPBRTerrainBakeProgram; +extern LLGLSLShader gDrawColorProgram; //output tex0[tc0] - tex1[tc1] extern LLGLSLShader gTwoTextureCompareProgram; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7f38642623..0c186c0ed2 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -266,7 +266,7 @@ void LLViewerTextureList::doPrefetchImages() S32 pixel_area = imagesd["area"]; S32 texture_type = imagesd["type"]; - if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) + if((LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type)) { LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); if (image) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4dba930ed5..4e8932f912 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -6732,8 +6732,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + if (!facep->getViewerObject()->isAttachment() && !facep->getViewerObject()->isRiggedMesh()) + { + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } } else if (!hud_group) { //deferred rendering @@ -6769,7 +6772,10 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + if (!facep->getViewerObject()->isAttachment() && !facep->getViewerObject()->isRiggedMesh()) + { + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } } else if (fullbright || bake_sunlight) { //fullbright diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f91b054dd7..18dd694246 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -431,6 +431,7 @@ void LLPipeline::init() stop_glerror(); //create render pass pools + getPool(LLDrawPool::POOL_WATEREXCLUSION); getPool(LLDrawPool::POOL_ALPHA_PRE_WATER); getPool(LLDrawPool::POOL_ALPHA_POST_WATER); getPool(LLDrawPool::POOL_SIMPLE); @@ -673,6 +674,8 @@ void LLPipeline::cleanup() // don't delete wl sky pool it was handled above in the for loop //delete mWLSkyPool; mWLSkyPool = NULL; + delete mWaterExclusionPool; + mWaterExclusionPool = nullptr; releaseGLBuffers(); @@ -907,6 +910,15 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) mPostMap.allocate(resX, resY, screenFormat); + // The water exclusion mask needs its own depth buffer so we can take care of the problem of multiple water planes. + // Should we ever make water not just a plane, it also aids with that as well as the water planes will be rendered into the mask. + // Why do we do this? Because it saves us some janky logic in the exclusion shader when we generate the mask. + // Regardless, this should always only be an R8 texture unless we choose to start having multiple kinds of exclusion that 8 bits can't handle. + // - Geenz 2025-02-06 + bool success = mWaterExclusionMask.allocate(resX, resY, GL_R8, true); + + assert(success); + // used to scale down textures // See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown mDownResMap.allocate(1024, 1024, GL_RGBA); @@ -1166,6 +1178,8 @@ void LLPipeline::releaseGLBuffers() mSceneMap.release(); + mWaterExclusionMask.release(); + mPostMap.release(); mFXAAMap.release(); @@ -1676,6 +1690,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) poolp = mPBRAlphaMaskPool; break; + case LLDrawPool::POOL_WATEREXCLUSION: + poolp = mWaterExclusionPool; + break; + default: llassert(0); LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; @@ -4068,6 +4086,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) } } +// Render all of our geometry that's required after our deferred pass. +// This is gonna be stuff like alpha, water, etc. void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; @@ -4084,6 +4104,10 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) bool done_atmospherics = LLPipeline::sRenderingHUDs; //skip atmospherics on huds bool done_water_haze = done_atmospherics; + bool done_water_exclusion = false; + + // do water exclusion just before water pass. + U32 water_exclusion_pass = LLDrawPool::POOL_WATEREXCLUSION; // do atmospheric haze just before post water alpha U32 atmospherics_pass = LLDrawPool::POOL_ALPHA_POST_WATER; @@ -4122,6 +4146,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) cur_type = poolp->getType(); + if (cur_type >= water_exclusion_pass && !done_water_exclusion) + { // do water exclusion against depth buffer before rendering alpha + doWaterExclusionMask(); + done_water_exclusion = true; + } + if (cur_type >= atmospherics_pass && !done_atmospherics) { // do atmospherics against depth buffer before rendering alpha doAtmospherics(); @@ -5201,6 +5231,17 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; + case LLDrawPool::POOL_WATEREXCLUSION: + if (mWaterExclusionPool) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water Exclusion Pool" << LL_ENDL; + } + else + { + mWaterExclusionPool = new_poolp; + } + break; default: llassert(0); @@ -5323,6 +5364,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mPBRAlphaMaskPool = NULL; break; + case LLDrawPool::POOL_WATEREXCLUSION: + llassert(poolp == mWaterExclusionPool); + mWaterExclusionPool = nullptr; + break; + default: llassert(0); LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; @@ -8824,6 +8870,7 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_WATEREXCLUSION, END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); @@ -8962,6 +9009,8 @@ void LLPipeline::doWaterHaze() static LLStaticHashedString above_water_str("above_water"); haze_shader.uniform1i(above_water_str, sUnderWaterRender ? -1 : 1); + haze_shader.bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &mWaterExclusionMask); + if (LLPipeline::sUnderWaterRender) { LLGLDepthTest depth(GL_FALSE); @@ -8992,6 +9041,17 @@ void LLPipeline::doWaterHaze() } } +void LLPipeline::doWaterExclusionMask() +{ + mWaterExclusionMask.bindTarget(); + glClearColor(1, 1, 1, 1); + mWaterExclusionMask.clear(); + mWaterExclusionPool->render(); + + mWaterExclusionMask.flush(); + glClearColor(0, 0, 0, 0); +} + void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) { //construct frustum diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5c9b95ef4a..315e38ed8c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -337,6 +337,9 @@ public: // should be called just before rendering pre-water alpha objects void doWaterHaze(); + // Generate the water exclusion surface mask. + void doWaterExclusionMask(); + void postDeferredGammaCorrect(LLRenderTarget* screen_target); void generateSunShadow(LLCamera& camera); @@ -500,6 +503,7 @@ public: RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_CONTROL_AV = LLDrawPool::POOL_CONTROL_AV, // Animesh RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, + RENDER_TYPE_WATEREXCLUSION = LLDrawPool::POOL_WATEREXCLUSION, RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, RENDER_TYPE_GLTF_PBR = LLDrawPool::POOL_GLTF_PBR, @@ -714,6 +718,7 @@ public: LLRenderTarget mSpotShadow[2]; LLRenderTarget mPbrBrdfLut; + LLRenderTarget mWaterExclusionMask; // copy of the color/depth buffer just before gamma correction // for use by SSR @@ -953,6 +958,7 @@ protected: LLDrawPool* mWLSkyPool = nullptr; LLDrawPool* mPBROpaquePool = nullptr; LLDrawPool* mPBRAlphaMaskPool = nullptr; + LLDrawPool* mWaterExclusionPool = nullptr; // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar |