summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@lindenlab.com>2025-02-07 05:55:47 -0500
committerGitHub <noreply@github.com>2025-02-07 05:55:47 -0500
commit93a88e602545828c0298b20ff0375f191d1f6d9a (patch)
treecb098bfa5eeb4b0d784a9ed6aec3b5fe7f1a0245 /indra/newview
parent317cd6e66e65256eda6441c06fa32e55eee99fa3 (diff)
Water Exclusion Surfaces (#3517)
* #3455 Add support for water exclusion surfaces
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl43
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/waterF.glsl13
-rw-r--r--indra/newview/lldrawpool.cpp4
-rw-r--r--indra/newview/lldrawpool.h3
-rw-r--r--indra/newview/lldrawpoolwater.cpp48
-rw-r--r--indra/newview/lldrawpoolwater.h2
-rw-r--r--indra/newview/lldrawpoolwaterexclusion.cpp79
-rw-r--r--indra/newview/lldrawpoolwaterexclusion.h61
-rw-r--r--indra/newview/llviewershadermgr.cpp12
-rw-r--r--indra/newview/llviewershadermgr.h1
-rw-r--r--indra/newview/llviewertexturelist.cpp2
-rw-r--r--indra/newview/llvovolume.cpp12
-rw-r--r--indra/newview/pipeline.cpp60
-rw-r--r--indra/newview/pipeline.h6
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