summaryrefslogtreecommitdiff
path: root/indra/newview/app_settings/shaders/class3
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-06-11 13:38:43 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-06-11 13:38:43 +0200
commitd9789bfaf230e301873bd700f6f360d306dc2486 (patch)
tree4b2dd2680905ca9821e2b11b36aa63dfe7af4f84 /indra/newview/app_settings/shaders/class3
parent9f6b8484dfb7dfa981d8a8ac3693d3f68e32bc12 (diff)
parenta73773bc1abdac6bc3beea36fd4ba58eba686e13 (diff)
Merge branch 'main' of https://github.com/secondlife/viewer into DRTVWR-600-maint-A
# Conflicts: # indra/llappearance/llavatarappearance.h # indra/llimage/llimage.cpp # indra/llmath/llvolume.cpp # indra/llmath/llvolume.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llrendertarget.cpp # indra/llrender/llshadermgr.cpp # indra/newview/lldynamictexture.cpp # indra/newview/llenvironment.cpp # indra/newview/llfetchedgltfmaterial.cpp # indra/newview/llfloaterimagepreview.cpp # indra/newview/llfloaterimagepreview.h # indra/newview/llfloaterregioninfo.cpp # indra/newview/llfloaterregioninfo.h # indra/newview/llmaniprotate.cpp # indra/newview/llmaniptranslate.cpp # indra/newview/llpanelvolume.cpp # indra/newview/llselectmgr.cpp # indra/newview/llselectmgr.h # indra/newview/llsurface.cpp # indra/newview/llsurface.h # indra/newview/llsurfacepatch.cpp # indra/newview/lltexturectrl.cpp # indra/newview/lltexturectrl.h # indra/newview/lltinygltfhelper.cpp # indra/newview/llviewertexture.cpp # indra/newview/llviewerwindow.cpp # indra/newview/llviewerwindow.h # indra/newview/llvlcomposition.cpp # indra/newview/llvlcomposition.h # indra/newview/llvocache.cpp # indra/newview/llvovolume.cpp # indra/newview/pipeline.cpp
Diffstat (limited to 'indra/newview/app_settings/shaders/class3')
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/materialF.glsl30
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl206
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl39
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl50
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/waterF.glsl3
12 files changed, 240 insertions, 168 deletions
diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
index 22408387b1..03dc3d7113 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
@@ -53,8 +53,11 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
+void mirrorClip(vec3 pos);
+
void main()
{
+ mirrorClip(vary_position);
#ifdef HAS_DIFFUSE_LOOKUP
vec4 color = diffuseLookup(vary_texcoord0.xy);
#else
diff --git a/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl
index 7f75b16cf0..4af57e3b80 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl
@@ -33,7 +33,7 @@ uniform vec3 moon_dir;
uniform int sun_up_factor;
in vec2 vary_fragcoord;
-vec3 getNorm(vec2 pos_screen);
+vec4 getNorm(vec2 pos_screen);
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
@@ -53,8 +53,7 @@ void main()
vec2 tc = vary_fragcoord.xy;
float depth = getDepth(tc.xy);
vec4 pos = getPositionWithDepth(tc, depth);
- vec4 norm = texture(normalMap, tc);
- norm.xyz = getNorm(tc);
+ vec4 norm = getNorm(tc);
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
vec3 color = vec3(0);
@@ -68,16 +67,16 @@ void main()
calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
vec3 sunlit_linear = srgb_to_linear(sunlit);
-
+
// mask off atmospherics below water (when camera is under water)
bool do_atmospherics = false;
-
+
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);
@@ -102,5 +101,5 @@ void main()
}
frag_color = max(vec4(color.rgb, alpha), vec4(0)); //output linear since local lights will be added to this shader's results
-
+
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
index 20f063fe3e..d3e19cf4a8 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -45,6 +45,13 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float
vec3 srgb_to_linear(vec3 cs);
vec3 linear_to_srgb(vec3 cs);
+uniform mat4 modelview_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 vary_position;
+
+void mirrorClip(vec3 pos);
+
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
out vec4 frag_color;
@@ -66,12 +73,12 @@ uniform vec4 morphFactor;
uniform vec3 camPosLocal;
uniform mat3 env_mat;
+uniform float is_mirror;
+
uniform vec3 sun_dir;
uniform vec3 moon_dir;
in vec2 vary_fragcoord;
-in vec3 vary_position;
-
uniform mat4 proj_mat;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -209,8 +216,6 @@ in vec3 vary_normal;
in vec4 vertex_color;
in vec2 vary_texcoord0;
-vec2 encode_normal(vec3 n);
-
// get the transformed normal and apply glossiness component from normal map
vec3 getNormal(inout float glossiness)
{
@@ -285,12 +290,12 @@ float getShadow(vec3 pos, vec3 norm)
void main()
{
+ mirrorClip(vary_position);
waterClip();
// diffcol == diffuse map combined with vertex color
vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy);
diffcol.rgb *= vertex_color.rgb;
-
alphaMask(diffcol.a);
// spec == specular map combined with specular color
@@ -299,8 +304,6 @@ void main()
float glossiness = specular_color.a;
vec3 norm = getNormal(glossiness);
- vec2 abnormal = encode_normal(norm.xyz);
-
float emissive = getEmissive(diffcol);
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
@@ -407,10 +410,15 @@ void main()
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
- frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials
- frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent.
- frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
- frag_data[3] = vec4(0);
+
+ float flag = GBUFFER_FLAG_HAS_ATMOS;
+
+ frag_data[0] = max(vec4(diffcol.rgb, emissive), vec4(0)); // gbuffer is sRGB for legacy materials
+ frag_data[1] = max(vec4(spec.rgb, glossiness), vec4(0)); // XYZ = Specular color. W = Specular exponent.
+ frag_data[2] = vec4(norm, flag); // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
+ frag_data[3] = vec4(env, 0, 0, 0);
+
#endif
}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
index 31aca8a745..edfd6cbced 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
@@ -48,7 +48,7 @@ in vec4 vary_fragcoord;
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
vec4 getPosition(vec2 pos_screen);
-vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec4 getNorm(vec2 screenpos);
vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 c);
@@ -56,8 +56,8 @@ vec3 srgb_to_linear(vec3 c);
// Util
vec3 hue_to_rgb(float hue);
-vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
- float perceptualRoughness,
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
@@ -74,9 +74,8 @@ void main()
discard;
}
- float envIntensity; // not used for this shader
- vec3 n;
- vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+ vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG()
+ vec3 n = norm.xyz;
vec4 spec = texture(specularRect, tc);
vec3 diffuse = texture(diffuseRect, tc).rgb;
@@ -92,7 +91,7 @@ void main()
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
-
+
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
index c27310cf89..60be9f4407 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
@@ -1,28 +1,28 @@
-/**
+/**
* @file class3\deferred\pointLightF.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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$
*/
-
+
/*[EXTRA_CODE_HERE]*/
out vec4 frag_color;
@@ -52,15 +52,15 @@ uniform vec4 viewport;
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
-vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec4 getNorm(vec2 screenpos);
vec4 getPosition(vec2 pos_screen);
vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 c);
float getDepth(vec2 tc);
-vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
- float perceptualRoughness,
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
@@ -72,9 +72,8 @@ void main()
vec2 tc = getScreenCoord(vary_fragcoord);
vec3 pos = getPosition(tc).xyz;
- float envIntensity;
- vec3 n;
- vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+ vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG()
+ vec3 n = norm.xyz;
vec3 diffuse = texture(diffuseRect, tc).rgb;
vec4 spec = texture(specularRect, tc);
@@ -94,13 +93,13 @@ void main()
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
- vec3 colorEmissive = texture(emissiveRect, tc).rgb;
+ vec3 colorEmissive = texture(emissiveRect, tc).rgb;
vec3 orm = spec.rgb;
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
-
+
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
@@ -137,7 +136,7 @@ void main()
final_color += lit*scol*color.rgb*spec.rgb;
}
}
-
+
if (dot(final_color, final_color) <= 0.0)
{
discard;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index ae81a4b472..90c84cc428 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n,
uniform samplerCubeArray reflectionProbes;
uniform samplerCubeArray irradianceProbes;
+
uniform sampler2D sceneMap;
uniform int cube_snapshot;
uniform float max_probe_lod;
@@ -47,14 +48,16 @@ layout (std140) uniform ReflectionProbes
/// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation
// box[3][0..2] - plane thickness
mat4 refBox[MAX_REFMAP_COUNT];
+ mat4 heroBox;
// list of bounding spheres for reflection probes sorted by distance to camera (closest first)
vec4 refSphere[MAX_REFMAP_COUNT];
- // extra parameters
+ // extra parameters
// x - irradiance scale
// y - radiance scale
// z - fade in
// w - znear
vec4 refParams[MAX_REFMAP_COUNT];
+ vec4 heroSphere;
// index of cube map in reflectionProbes for a corresponding reflection probe
// e.g. cube map channel of refSphere[2] is stored in refIndex[2]
// refIndex.x - cubemap channel in reflectionProbes
@@ -70,6 +73,10 @@ layout (std140) uniform ReflectionProbes
// number of reflection probes present in refSphere
int refmapCount;
+
+ int heroShape;
+ int heroMipCount;
+ int heroProbeCount;
};
// Inputs
@@ -95,7 +102,7 @@ bool shouldSampleProbe(int i, vec3 pos)
if (refIndex[i].w < 0)
{
vec4 v = refBox[i] * vec4(pos, 1.0);
- if (abs(v.x) > 1 ||
+ if (abs(v.x) > 1 ||
abs(v.y) > 1 ||
abs(v.z) > 1)
{
@@ -222,7 +229,7 @@ void preProbeSample(vec3 pos)
}
}
count++;
-
+
++neighborIdx;
}
@@ -244,56 +251,56 @@ void preProbeSample(vec3 pos)
// original reference implementation:
/*
-bool intersect(const Ray &ray) const
-{
- float t0, t1; // solutions for t if the ray intersects
-#if 0
+bool intersect(const Ray &ray) const
+{
+ float t0, t1; // solutions for t if the ray intersects
+#if 0
// geometric solution
- Vec3f L = center - orig;
- float tca = L.dotProduct(dir);
+ Vec3f L = center - orig;
+ float tca = L.dotProduct(dir);
// if (tca < 0) return false;
- float d2 = L.dotProduct(L) - tca * tca;
- if (d2 > radius2) return false;
- float thc = sqrt(radius2 - d2);
- t0 = tca - thc;
- t1 = tca + thc;
-#else
+ float d2 = L.dotProduct(L) - tca * tca;
+ if (d2 > radius2) return false;
+ float thc = sqrt(radius2 - d2);
+ t0 = tca - thc;
+ t1 = tca + thc;
+#else
// analytic solution
- Vec3f L = orig - center;
- float a = dir.dotProduct(dir);
- float b = 2 * dir.dotProduct(L);
- float c = L.dotProduct(L) - radius2;
- if (!solveQuadratic(a, b, c, t0, t1)) return false;
-#endif
- if (t0 > t1) std::swap(t0, t1);
-
- if (t0 < 0) {
- t0 = t1; // if t0 is negative, let's use t1 instead
- if (t0 < 0) return false; // both t0 and t1 are negative
- }
-
- t = t0;
-
- return true;
+ Vec3f L = orig - center;
+ float a = dir.dotProduct(dir);
+ float b = 2 * dir.dotProduct(L);
+ float c = L.dotProduct(L) - radius2;
+ if (!solveQuadratic(a, b, c, t0, t1)) return false;
+#endif
+ if (t0 > t1) std::swap(t0, t1);
+
+ if (t0 < 0) {
+ t0 = t1; // if t0 is negative, let's use t1 instead
+ if (t0 < 0) return false; // both t0 and t1 are negative
+ }
+
+ t = t0;
+
+ return true;
} */
// adapted -- assume that origin is inside sphere, return intersection of ray with edge of sphere
vec3 sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2)
-{
- float t0, t1; // solutions for t if the ray intersects
+{
+ float t0, t1; // solutions for t if the ray intersects
- vec3 L = center - origin;
+ vec3 L = center - origin;
float tca = dot(L,dir);
- float d2 = dot(L,L) - tca * tca;
-
- float thc = sqrt(radius2 - d2);
- t0 = tca - thc;
- t1 = tca + thc;
+ float d2 = dot(L,L) - tca * tca;
+ float thc = sqrt(radius2 - d2);
+ t0 = tca - thc;
+ t1 = tca + thc;
+
vec3 v = origin + dir * t1;
- return v;
-}
+ return v;
+}
void swap(inout float a, inout float b)
{
@@ -305,17 +312,17 @@ void swap(inout float a, inout float b)
// debug implementation, make no assumptions about origin
void sphereIntersectDebug(vec3 origin, vec3 dir, vec3 center, float radius2, float depth, inout vec4 col)
{
- float t[2]; // solutions for t if the ray intersects
+ float t[2]; // solutions for t if the ray intersects
// geometric solution
- vec3 L = center - origin;
+ vec3 L = center - origin;
float tca = dot(L, dir);
// if (tca < 0) return false;
- float d2 = dot(L, L) - tca * tca;
- if (d2 > radius2) return;
- float thc = sqrt(radius2 - d2);
- t[0] = tca - thc;
- t[1] = tca + thc;
+ float d2 = dot(L, L) - tca * tca;
+ if (d2 > radius2) return;
+ float thc = sqrt(radius2 - d2);
+ t[0] = tca - thc;
+ t[1] = tca + thc;
for (int i = 0; i < 2; ++i)
{
@@ -365,11 +372,11 @@ return texCUBE(envMap, ReflDirectionWS);
// i - probe index in refBox/refSphere
// d - distance to nearest wall in clip space
// scale - scale of box, default 1.0
-vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale)
+vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d, float scale)
{
// Intersection with OBB convert to unit box space
// Transform in local unit parallax cube space (scaled and rotated)
- mat4 clipToLocal = refBox[i];
+ mat4 clipToLocal = i;
vec3 RayLS = mat3(clipToLocal) * dir;
vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
@@ -388,7 +395,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale)
return IntersectPositionCS;
}
-vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d)
+vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d)
{
return boxIntersect(origin, dir, i, d, 1.0);
}
@@ -404,8 +411,8 @@ void debugBoxCol(vec3 ro, vec3 rd, float t, vec3 p, inout vec4 col)
bool behind = dot(v,v) > dot(pos,pos);
float w = 0.25;
-
- if (behind)
+
+ if (behind)
{
w *= 0.5;
w /= (length(v)-length(pos))*0.5+1.0;
@@ -419,7 +426,7 @@ void debugBoxCol(vec3 ro, vec3 rd, float t, vec3 p, inout vec4 col)
// cribbed from https://iquilezles.org/articles/intersectors/
// axis aligned box centered at the origin, with size boxSize
-void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col)
+void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col)
{
vec3 rd = normalize(p-ro);
@@ -443,10 +450,10 @@ void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col)
}
-void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
+void boxIntersectDebug(vec3 origin, vec3 pos, mat4 i, inout vec4 col)
{
- mat4 clipToLocal = refBox[i];
-
+ mat4 clipToLocal = i;
+
// transform into unit cube space
origin = (clipToLocal * vec4(origin, 1.0)).xyz;
pos = (clipToLocal * vec4(pos, 1.0)).xyz;
@@ -462,16 +469,16 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
// r - radius of probe influence volume
// i - index of probe in refSphere
// dw - distance weight
-float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw)
+float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, vec4 i, out float dw)
{
- float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
+ float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz - origin;
float d2 = max(length(delta), 0.001);
float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001);
float w = 1.0 / d2;
- w *= refParams[i].z;
+ w *= i.z;
dw = w * atten * max(r, 1.0)*4;
@@ -488,7 +495,7 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw
// lod - which mip to sample (lower is higher res, sharper reflections)
// c - center of probe
// r2 - radius of probe squared
-// i - index of probe
+// i - index of probe
vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, int i)
{
// parallax adjustment
@@ -497,7 +504,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
if (refIndex[i].w < 0)
{ // box probe
float d = 0;
- v = boxIntersect(pos, dir, i, d);
+ v = boxIntersect(pos, dir, refBox[i], d);
w = max(d, 0.001);
}
@@ -507,18 +514,18 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
float rr = r * r;
- v = sphereIntersect(pos, dir, c,
+ v = sphereIntersect(pos, dir, c,
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr);
- w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw);
+ w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw);
}
v -= c;
vec3 d = normalize(v);
v = env_mat * v;
-
+
vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y;
return ret.rgb;
@@ -529,7 +536,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
// dir - pixel normal
// w - weight of sample (distance and angular attenuation)
// dw - weight of sample (distance only)
-// i - index of probe
+// i - index of probe
vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int i, vec3 amblit)
{
// parallax adjustment
@@ -537,7 +544,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int
if (refIndex[i].w < 0)
{
float d = 0.0;
- v = boxIntersect(pos, dir, i, d, 3.0);
+ v = boxIntersect(pos, dir, refBox[i], d, 3.0);
w = max(d, 0.001);
}
else
@@ -547,16 +554,16 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int
// pad sphere for manual probe extending into automatic probe space
float rr = r * r;
- v = sphereIntersect(pos, dir, c,
+ v = sphereIntersect(pos, dir, c,
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr);
- w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw);
+ w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw);
}
v -= c;
v = env_mat * v;
-
+
vec3 col = textureLod(irradianceProbes, vec4(v.xyz, refIndex[i].x), 0).rgb * refParams[i].x;
col = mix(amblit, col, min(refParams[i].x, 1.0));
@@ -618,7 +625,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
col[1] *= 1.0/wsum[1];
col[0] = vec3(0);
}
-
+
return col[1]+col[0];
}
@@ -647,7 +654,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
{
continue;
}
-
+
{
float w = 0;
float dw = 0;
@@ -677,10 +684,53 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
col[1] *= 1.0/wsum[1];
col[0] = vec3(0);
}
-
+
return col[1]+col[0];
}
+#if defined(HERO_PROBES)
+
+uniform vec4 clipPlane;
+uniform samplerCubeArray heroProbes;
+
+void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
+{
+ float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w;
+ float w = 0;
+ float dw = 0;
+ float falloffMult = 10;
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+ if (heroShape < 1)
+ {
+ float d = 0;
+ boxIntersect(pos, norm, heroBox, d, 1.0);
+
+ w = max(d, 0);
+ }
+ else
+ {
+ float r = heroSphere.w;
+
+ w = sphereWeight(pos, refnormpersp, heroSphere.xyz, r, vec4(1), dw);
+ }
+
+ clipDist = clipDist * 0.95 + 0.05;
+ clipDist = clamp(clipDist * falloffMult, 0, 1);
+ w = clamp(w * falloffMult * clipDist, 0, 1);
+ w = mix(0, w, clamp(glossiness - 0.75, 0, 1) * 4); // We only generate a quarter of the mips for the hero probes. Linearly interpolate between normal probes and hero probes based upon glossiness.
+ glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w);
+}
+
+#else
+
+void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
+{
+}
+
+#endif
+
+
+
void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit)
{
@@ -712,6 +762,8 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
glossenv = mix(glossenv, ssr.rgb, ssr.a);
}
#endif
+
+ tapHeroProbe(glossenv, pos, norm, glossiness);
}
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
@@ -747,7 +799,7 @@ void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
{
if (refIndex[i].w < 0)
{
- boxIntersectDebug(origin, pos, i, col);
+ boxIntersectDebug(origin, pos, refBox[i], col);
}
else
{
@@ -799,8 +851,9 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
{
float lod = (1.0-glossiness)*reflection_lods;
glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
+
}
-
+
if (envIntensity > 0.0)
{
legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0);
@@ -826,6 +879,9 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
}
#endif
+ tapHeroProbe(glossenv, pos, norm, glossiness);
+ tapHeroProbe(legacyenv, pos, norm, 1.0);
+
glossenv = clamp(glossenv, vec3(0), vec3(10));
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl
index 63fa4ecc55..deb276ef9d 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl
@@ -40,36 +40,33 @@ uniform sampler2D specularRect;
uniform sampler2D diffuseRect;
uniform sampler2D diffuseMap;
-vec3 getNorm(vec2 screenpos);
+vec4 getNorm(vec2 screenpos);
float getDepth(vec2 pos_screen);
float linearDepth(float d, float znear, float zfar);
float linearDepth01(float d, float znear, float zfar);
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
vec4 getPosition(vec2 pos_screen);
-vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
float random (vec2 uv);
float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source, float glossiness);
-void main()
+void main()
{
vec2 tc = vary_fragcoord.xy;
float depth = linearDepth01(getDepth(tc), zNear, zFar);
- float envIntensity;
- vec3 n;
- vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+ vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG()
vec3 pos = getPositionWithDepth(tc, getDepth(tc)).xyz;
vec4 spec = texture(specularRect, tc);
vec2 hitpixel;
-
+
vec4 diffuse = texture(diffuseRect, tc);
vec3 specCol = spec.rgb;
vec4 fcol = texture(diffuseMap, tc);
- if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 orm = specCol.rgb;
float perceptualRoughness = orm.g;
@@ -84,7 +81,7 @@ void main()
vec4 collectedColor = vec4(0);
- float w = tapScreenSpaceReflection(4, tc, pos, n, collectedColor, diffuseMap, 0);
+ float w = tapScreenSpaceReflection(4, tc, pos, norm.xyz, collectedColor, diffuseMap, 0);
collectedColor.rgb *= specCol.rgb;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 47b5934b84..96c32734e4 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -50,6 +50,7 @@ uniform float ssao_irradiance_max;
#endif
// Inputs
+uniform vec4 clipPlane;
uniform mat3 env_mat;
uniform mat3 ssao_effect_mat;
uniform vec3 sun_dir;
@@ -60,7 +61,7 @@ in vec2 vary_fragcoord;
uniform mat4 inv_proj;
uniform vec2 screen_res;
-vec3 getNorm(vec2 pos_screen);
+vec4 getNorm(vec2 pos_screen);
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
@@ -104,8 +105,8 @@ vec3 pbrBaseLight(vec3 diffuseColor,
vec3 additive,
vec3 atten);
-vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
- float perceptualRoughness,
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
@@ -127,13 +128,13 @@ void main()
vec2 tc = vary_fragcoord.xy;
float depth = getDepth(tc.xy);
vec4 pos = getPositionWithDepth(tc, depth);
- vec4 norm = texture(normalMap, tc);
- float envIntensity = norm.z;
- norm.xyz = getNorm(tc);
+ vec4 norm = getNorm(tc);
+ vec3 colorEmissive = texture(emissiveRect, tc).rgb;
+ float envIntensity = colorEmissive.r;
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
vec4 baseColor = texture(diffuseRect, tc);
- vec4 spec = texture(specularRect, vary_fragcoord.xy); // NOTE: PBR linear Emissive
+ vec4 spec = texture(specularRect, tc); // NOTE: PBR linear Emissive
#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
vec2 scol_ambocc = texture(lightMap, vary_fragcoord.xy).rg;
@@ -168,15 +169,15 @@ void main()
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
- vec3 orm = texture(specularRect, tc).rgb;
+ vec3 orm = spec.rgb;
float perceptualRoughness = orm.g;
float metallic = orm.b;
float ao = orm.r;
- vec3 colorEmissive = texture(emissiveRect, tc).rgb;
+
// PBR IBL
float gloss = 1.0 - perceptualRoughness;
-
+
sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss, false, amblit_linear);
adjustIrradiance(irradiance, ambocc);
@@ -188,10 +189,15 @@ void main()
vec3 v = -normalize(pos.xyz);
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
}
- else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
+ else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI))
+ {
+ // actual HDRI sky, just copy color value
+ color = colorEmissive.rgb;
+ }
+ else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_SKIP_ATMOS))
{
- //should only be true of WL sky, just port over base color value
- color = texture(emissiveRect, tc).rgb;
+ //should only be true of WL sky, port over base color value and scale for fake HDR
+ color = colorEmissive.rgb;
color = srgb_to_linear(color);
color *= sky_hdr_scale;
}
@@ -199,7 +205,7 @@ void main()
{
// legacy shaders are still writng sRGB to gbuffer
baseColor.rgb = srgb_to_linear(baseColor.rgb);
-
+
spec.rgb = srgb_to_linear(spec.rgb);
float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
@@ -218,7 +224,7 @@ void main()
vec3 sun_contrib = min(da, scol) * sunlit_linear;
color.rgb += sun_contrib;
color.rgb *= baseColor.rgb;
-
+
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
if (spec.a > 0.0)
@@ -244,10 +250,11 @@ void main()
// add radiance map
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
+
}
color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a);
-
+
if (envIntensity > 0.0)
{ // add environment map
applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
index 871c7ce812..319fa86148 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
@@ -1,28 +1,28 @@
-/**
+/**
* @file class3\deferred\spotLightF.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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$
*/
-
+
/*[EXTRA_CODE_HERE]*/
out vec4 frag_color;
@@ -72,7 +72,7 @@ uniform mat4 inv_proj;
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
-vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec4 getNorm(vec2 screenpos);
vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
vec2 getScreenCoord(vec4 clip);
@@ -83,8 +83,8 @@ vec4 getPosition(vec2 pos_screen);
const float M_PI = 3.14159265;
-vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
- float perceptualRoughness,
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+ float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
@@ -112,18 +112,17 @@ void main()
}
float shadow = 1.0;
-
+
if (proj_shadow_idx >= 0)
{
vec4 shd = texture(lightMap, tc);
shadow = (proj_shadow_idx==0)?shd.b:shd.a;
shadow += shadow_fade;
- shadow = clamp(shadow, 0.0, 1.0);
+ shadow = clamp(shadow, 0.0, 1.0);
}
- float envIntensity;
- vec3 n;
- vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity);
+ vec4 norm = getNorm(tc);
+ vec3 n = norm.xyz;
float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
if (dist_atten <= 0.0)
@@ -145,13 +144,12 @@ void main()
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
- vec3 colorEmissive = texture(emissiveRect, tc).rgb;
vec3 orm = spec.rgb;
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
-
+
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
@@ -169,7 +167,7 @@ void main()
if (nl > 0.0)
{
amb_da += (nl*0.5 + 0.5) * proj_ambiance;
-
+
dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
vec3 intensity = dist_atten * dlit * 3.25 * shadow; // Legacy attenuation, magic number to balance with legacy materials
@@ -182,6 +180,8 @@ void main()
}
else
{
+ float envIntensity = texture(emissiveRect, tc).r;
+
diffuse = srgb_to_linear(diffuse);
spec.rgb = srgb_to_linear(spec.rgb);
@@ -205,11 +205,11 @@ void main()
// unshadowed for consistency between forward and deferred?
amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
}
-
+
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb * max(dot(-normalize(lv), n), 0.0);
}
-
+
if (spec.a > 0.0)
{
dlit *= min(nl*6.0, 1.0) * dist_atten;
@@ -218,7 +218,7 @@ void main()
float gtdenom = 2 * nh;
float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
-
+
if (nh > 0.0)
{
float scol = fres*texture(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
@@ -226,26 +226,26 @@ void main()
speccol = clamp(speccol, vec3(0), vec3(1));
final_color += speccol;
}
- }
+ }
if (envIntensity > 0.0)
{
vec3 ref = reflect(normalize(pos), n);
-
+
//project from point pos in direction ref to plane proj_p, proj_n
vec3 pdelta = proj_p-pos;
float ds = dot(ref, proj_n);
-
+
if (ds < 0.0)
{
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
-
+
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
if (stc.z > 0.0)
{
stc /= stc.w;
-
+
if (stc.x < 1.0 &&
stc.y < 1.0 &&
stc.x > 0.0 &&
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl
index 61059e2339..f6bef1e498 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl
@@ -43,7 +43,7 @@ void main()
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
@@ -56,10 +56,9 @@ void main()
}
vec4 pos = getPositionWithDepth(tc, depth);
- vec4 norm = texture(normalMap, tc);
vec4 fogged = getWaterFogView(pos.xyz);
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 3bf606a252..728d70ebb2 100644
--- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
@@ -55,9 +55,11 @@ in vec4 view;
in vec3 vary_position;
vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color);
+void mirrorClip(vec3 position);
void main()
{
+ mirrorClip(vary_position);
vec4 color;
//get detail normals
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
index 88c38c46a2..a5592188a9 100644
--- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -35,6 +35,8 @@ vec3 scaleSoftClipFragLinear(vec3 l);
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);
+void mirrorClip(vec3 pos);
+
// PBR interface
vec2 BRDF(float NoV, float roughness);
@@ -129,6 +131,7 @@ vec3 getPositionWithNDC(vec3 ndc);
void main()
{
+ mirrorClip(vary_position);
vN = vary_normal;
vT = vary_tangent;
vB = cross(vN, vT);