summaryrefslogtreecommitdiff
path: root/indra/newview/app_settings/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/app_settings/shaders')
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl7
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/globalF.glsl45
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl7
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl7
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl344
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl473
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl93
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl33
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl76
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/bumpF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/bumpV.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/materialF.glsl18
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl101
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/waterF.glsl3
38 files changed, 1361 insertions, 36 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
index 83b0ba096c..43863dd37a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
@@ -26,6 +26,7 @@
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix;
+uniform mat4 modelview_matrix;
in vec3 position;
in vec3 normal;
@@ -35,10 +36,12 @@ in vec2 texcoord0;
out vec3 vary_normal;
out vec4 vertex_color;
out vec2 vary_texcoord0;
+out vec3 vary_position;
void main()
{
//transform vertex
+ vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 6ebe4ce251..c0607d0149 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -33,11 +33,15 @@ uniform float minimum_alpha;
in vec3 vary_normal;
in vec2 vary_texcoord0;
+in vec3 vary_position;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 pos);
void main()
{
+ mirrorClip(vary_position);
+
vec4 diff = texture(diffuseMap, vary_texcoord0.xy);
if (diff.a < minimum_alpha)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
index bc0c11ec46..5cc2846156 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
@@ -35,6 +35,7 @@ in vec4 weight;
out vec3 vary_normal;
out vec2 vary_texcoord0;
+out vec3 vary_position;
void main()
{
@@ -57,6 +58,7 @@ void main()
vary_normal = norm;
+ vary_position = pos.xyz;
gl_Position = projection_matrix * pos;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index 35f483f633..a22c174349 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -37,11 +37,15 @@ in vec3 vary_mat2;
in vec4 vertex_color;
in vec2 vary_texcoord0;
+in vec3 vary_position;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 pos);
void main()
{
+ mirrorClip(vary_position);
+
vec4 col = texture(diffuseMap, vary_texcoord0.xy);
if(col.a < minimum_alpha)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
index 3af2eab1e4..74319349f6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
@@ -23,6 +23,7 @@
* $/LicenseInfo$
*/
+uniform mat4 modelview_matrix;
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix;
@@ -38,11 +39,11 @@ out vec3 vary_mat1;
out vec3 vary_mat2;
out vec4 vertex_color;
out vec2 vary_texcoord0;
+out vec3 vary_position;
#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
uniform mat4 projection_matrix;
-uniform mat4 modelview_matrix;
#endif
void main()
@@ -52,11 +53,13 @@ void main()
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
+ vary_position = pos;
gl_Position = projection_matrix*vec4(pos, 1.0);
vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz);
vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz);
#else
+ vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vec3 n = normalize(normal_matrix * normal);
vec3 t = normalize(normal_matrix * tangent.xyz);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
index 6f3b94f734..e8ead91504 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
@@ -31,14 +31,20 @@ uniform float minimum_alpha;
uniform sampler2D diffuseMap;
+in vec3 vary_position;
+
in vec3 vary_normal;
in vec4 vertex_color;
in vec2 vary_texcoord0;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 pos);
+
void main()
{
+ mirrorClip(vary_position);
+
vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color;
if (col.a < minimum_alpha)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
index e5f2af2c53..a07c892d8e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
@@ -28,6 +28,7 @@
out vec4 frag_data[4];
in vec3 vary_normal;
+in vec3 vary_position;
uniform float minimum_alpha;
@@ -36,8 +37,12 @@ in vec2 vary_texcoord0;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 pos);
+
void main()
{
+ mirrorClip(vary_position);
+
vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color;
if (col.a < minimum_alpha)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 68fb8bf499..76776ede2c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -32,11 +32,14 @@ uniform sampler2D diffuseMap;
in vec3 vary_normal;
in vec4 vertex_color;
in vec2 vary_texcoord0;
+in vec3 vary_position;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 pos);
void main()
{
+ mirrorClip(vary_position);
vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb;
frag_data[0] = vec4(col, 0.0);
frag_data[1] = vertex_color.aaaa; // spec
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
index 93d561504e..b983acf657 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -30,12 +30,15 @@ out vec4 frag_data[4];
in vec3 vary_normal;
in vec4 vertex_color;
in vec2 vary_texcoord0;
+in vec3 vary_position;
+void mirrorClip(vec3 pos);
vec2 encode_normal(vec3 n);
vec3 linear_to_srgb(vec3 c);
void main()
{
+ mirrorClip(vary_position);
vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
vec3 spec;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 2402cc3b70..64230dc680 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -36,13 +36,16 @@ out vec3 vary_normal;
out vec4 vertex_color;
out vec2 vary_texcoord0;
+out vec3 vary_position;
void passTextureIndex();
+uniform mat4 modelview_matrix;
+
#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
uniform mat4 projection_matrix;
-uniform mat4 modelview_matrix;
+
#endif
void main()
@@ -51,9 +54,11 @@ void main()
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
vec4 pos = mat * vec4(position.xyz, 1.0);
+ vary_position = pos.xyz;
gl_Position = projection_matrix * pos;
vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
#else
+ vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_normal = normalize(normal_matrix * normal);
#endif
diff --git a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl
index 9ac4ceb37e..eff7221ae7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl
@@ -28,7 +28,9 @@
out vec4 frag_color;
uniform sampler2D emissiveRect;
+#ifdef USE_LAST_EXPOSURE
uniform sampler2D exposureMap;
+#endif
uniform float dt;
uniform vec2 noiseVec;
@@ -51,10 +53,12 @@ void main()
L /= max_L;
L = pow(L, 2.0);
float s = mix(dynamic_exposure_params.z, dynamic_exposure_params.y, L);
-
+
+#ifdef USE_LAST_EXPOSURE
float prev = texture(exposureMap, vec2(0.5,0.5)).r;
s = mix(prev, s, min(dt*2.0*abs(prev-s), 0.04));
+#endif
frag_color = max(vec4(s, s, s, dt), vec4(0.0));
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index a6fab10791..52dfed06ae 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -50,9 +50,11 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color);
#endif
+void mirrorClip(vec3 pos);
+
void main()
{
-
+ mirrorClip(vary_position);
#ifdef IS_ALPHA
waterClip(vary_position.xyz);
#endif
diff --git a/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl
new file mode 100644
index 0000000000..7e3e7d9271
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl
@@ -0,0 +1,45 @@
+/**
+ * @file class1/deferred/globalF.glsl
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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$
+ */
+
+
+ // Global helper functions included in every fragment shader
+ // DO NOT declare sampler uniforms here as OS X doesn't compile
+ // them out
+
+uniform float mirror_flag;
+uniform vec4 clipPlane;
+uniform float clipSign;
+
+void mirrorClip(vec3 pos)
+{
+ if (mirror_flag > 0)
+ {
+ if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0)
+ {
+ discard;
+ }
+ }
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
index 7cdddfe8db..ddf878ae60 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
@@ -28,25 +28,18 @@
#define DIFFUSE_ALPHA_MODE_MASK 2
#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-#ifdef HAS_SKIN
uniform mat4 modelview_matrix;
uniform mat4 projection_matrix;
+uniform mat4 modelview_projection_matrix;
+
+#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
#else
uniform mat3 normal_matrix;
-uniform mat4 modelview_projection_matrix;
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#if !defined(HAS_SKIN)
-uniform mat4 modelview_matrix;
#endif
out vec3 vary_position;
-#endif
-
uniform mat4 texture_matrix0;
in vec3 position;
@@ -85,9 +78,7 @@ void main()
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
vary_position = pos;
-#endif
gl_Position = projection_matrix*vec4(pos,1.0);
@@ -133,10 +124,8 @@ void main()
vertex_color = diffuse_color;
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
#if !defined(HAS_SKIN)
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
#endif
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
index faa273b834..0683236460 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -58,10 +58,17 @@ vec2 encode_normal(vec3 n);
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
+uniform vec4 clipPlane;
+uniform float clipSign;
+
+void mirrorClip(vec3 pos);
+
uniform mat3 normal_matrix;
void main()
{
+ mirrorClip(vary_position);
+
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
if (basecolor.a < minimum_alpha)
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
index 160ae7a215..5e0141910b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
@@ -28,8 +28,9 @@
//deferred opaque implementation
-#ifdef HAS_SKIN
uniform mat4 modelview_matrix;
+
+#ifdef HAS_SKIN
uniform mat4 projection_matrix;
mat4 getObjectSkinnedTransform();
#else
@@ -59,6 +60,7 @@ out vec4 vertex_color;
out vec3 vary_tangent;
flat out float vary_sign;
out vec3 vary_normal;
+out vec3 vary_position;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
@@ -71,10 +73,11 @@ void main()
mat = modelview_matrix * mat;
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
-
+ vary_position = pos;
gl_Position = projection_matrix*vec4(pos,1.0);
#else
+ vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
//transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
#endif
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl
new file mode 100644
index 0000000000..c83a6be85d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl
@@ -0,0 +1,344 @@
+/**
+ * @file class1\deferred\terrainF.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+/*[EXTRA_CODE_HERE]*/
+
+#define TERRAIN_PBR_DETAIL_EMISSIVE 0
+#define TERRAIN_PBR_DETAIL_OCCLUSION -1
+#define TERRAIN_PBR_DETAIL_NORMAL -2
+#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
+
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+#define TerrainCoord vec4[2]
+#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
+#define TerrainCoord vec2
+#endif
+
+#define MIX_X 1 << 3
+#define MIX_Y 1 << 4
+#define MIX_Z 1 << 5
+#define MIX_W 1 << 6
+
+struct TerrainMix
+{
+ vec4 weight;
+ int type;
+};
+
+TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal);
+
+struct PBRMix
+{
+ vec4 col; // RGB color with alpha, linear space
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ vec3 orm; // Occlusion, roughness, metallic
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ vec2 rm; // Roughness, metallic
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ vec3 vNt; // Unpacked normal texture sample, vector
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ vec3 emissive; // RGB emissive color, linear space
+#endif
+};
+
+PBRMix init_pbr_mix();
+
+PBRMix terrain_sample_and_multiply_pbr(
+ TerrainCoord terrain_coord
+ , sampler2D tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , sampler2D tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , sampler2D tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , sampler2D tex_emissive
+#endif
+ , vec4 factor_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , vec3 factor_orm
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , vec2 factor_rm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , vec3 factor_emissive
+#endif
+ );
+
+PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight);
+
+out vec4 frag_data[4];
+
+uniform sampler2D alpha_ramp;
+
+// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures
+uniform sampler2D detail_0_base_color;
+uniform sampler2D detail_1_base_color;
+uniform sampler2D detail_2_base_color;
+uniform sampler2D detail_3_base_color;
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+uniform sampler2D detail_0_normal;
+uniform sampler2D detail_1_normal;
+uniform sampler2D detail_2_normal;
+uniform sampler2D detail_3_normal;
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+uniform sampler2D detail_0_metallic_roughness;
+uniform sampler2D detail_1_metallic_roughness;
+uniform sampler2D detail_2_metallic_roughness;
+uniform sampler2D detail_3_metallic_roughness;
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+uniform sampler2D detail_0_emissive;
+uniform sampler2D detail_1_emissive;
+uniform sampler2D detail_2_emissive;
+uniform sampler2D detail_3_emissive;
+#endif
+
+uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+uniform vec4 metallicFactors;
+uniform vec4 roughnessFactors;
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+uniform vec3[4] emissiveColors;
+#endif
+uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
+
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+in vec4[2] vary_coords;
+#endif
+in vec3 vary_normal;
+in vec3 vary_tangent;
+flat in float vary_sign;
+in vec4 vary_texcoord0;
+in vec4 vary_texcoord1;
+
+vec2 encode_normal(vec3 n);
+
+float terrain_mix(TerrainMix tm, vec4 tms4);
+
+void main()
+{
+
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+ TerrainCoord terrain_texcoord = vary_coords;
+#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
+ TerrainCoord terrain_texcoord = vary_texcoord0.xy;
+#endif
+
+ float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a;
+ float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a;
+ float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a;
+
+ TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal);
+
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ // RGB = Occlusion, Roughness, Metal
+ // default values, see LLViewerTexture::sDefaultPBRORMImagep
+ // occlusion 1.0
+ // roughness 0.0
+ // metal 0.0
+ vec3[4] orm_factors;
+ orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x);
+ orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y);
+ orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z);
+ orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w);
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ vec2[4] rm_factors;
+ rm_factors[0] = vec2(roughnessFactors.x, metallicFactors.x);
+ rm_factors[1] = vec2(roughnessFactors.y, metallicFactors.y);
+ rm_factors[2] = vec2(roughnessFactors.z, metallicFactors.z);
+ rm_factors[3] = vec2(roughnessFactors.w, metallicFactors.w);
+#endif
+
+ PBRMix mix = init_pbr_mix();
+ PBRMix mix2;
+ switch (tm.type & MIX_X)
+ {
+ case MIX_X:
+ mix2 = terrain_sample_and_multiply_pbr(
+ terrain_texcoord
+ , detail_0_base_color
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , detail_0_metallic_roughness
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , detail_0_normal
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , detail_0_emissive
+#endif
+ , baseColorFactors[0]
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , orm_factors[0]
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , rm_factors[0]
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , emissiveColors[0]
+#endif
+ );
+ mix = mix_pbr(mix, mix2, tm.weight.x);
+ break;
+ default:
+ break;
+ }
+ switch (tm.type & MIX_Y)
+ {
+ case MIX_Y:
+ mix2 = terrain_sample_and_multiply_pbr(
+ terrain_texcoord
+ , detail_1_base_color
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , detail_1_metallic_roughness
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , detail_1_normal
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , detail_1_emissive
+#endif
+ , baseColorFactors[1]
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , orm_factors[1]
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , rm_factors[1]
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , emissiveColors[1]
+#endif
+ );
+ mix = mix_pbr(mix, mix2, tm.weight.y);
+ break;
+ default:
+ break;
+ }
+ switch (tm.type & MIX_Z)
+ {
+ case MIX_Z:
+ mix2 = terrain_sample_and_multiply_pbr(
+ terrain_texcoord
+ , detail_2_base_color
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , detail_2_metallic_roughness
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , detail_2_normal
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , detail_2_emissive
+#endif
+ , baseColorFactors[2]
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , orm_factors[2]
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , rm_factors[2]
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , emissiveColors[2]
+#endif
+ );
+ mix = mix_pbr(mix, mix2, tm.weight.z);
+ break;
+ default:
+ break;
+ }
+ switch (tm.type & MIX_W)
+ {
+ case MIX_W:
+ mix2 = terrain_sample_and_multiply_pbr(
+ terrain_texcoord
+ , detail_3_base_color
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , detail_3_metallic_roughness
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , detail_3_normal
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , detail_3_emissive
+#endif
+ , baseColorFactors[3]
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , orm_factors[3]
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , rm_factors[3]
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , emissiveColors[3]
+#endif
+ );
+ mix = mix_pbr(mix, mix2, tm.weight.w);
+ break;
+ default:
+ break;
+ }
+
+ float minimum_alpha = terrain_mix(tm, minimum_alphas);
+ if (mix.col.a < minimum_alpha)
+ {
+ discard;
+ }
+ float base_color_factor_alpha = terrain_mix(tm, vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z));
+
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ // from mikktspace.com
+ vec3 vNt = mix.vNt;
+ vec3 vN = vary_normal;
+ vec3 vT = vary_tangent.xyz;
+
+ vec3 vB = vary_sign * cross(vN, vT);
+ vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
+
+ tnorm *= gl_FrontFacing ? 1.0 : -1.0;
+#else
+ vec3 tnorm = vary_normal;
+ tnorm *= gl_FrontFacing ? 1.0 : -1.0;
+#endif
+
+
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+#define emissive mix.emissive
+#else
+#define emissive vec3(0)
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+#define orm mix.orm
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+#define orm vec3(1.0, mix.rm)
+#else
+// Matte plastic potato terrain
+#define orm vec3(1.0, 1.0, 0.0)
+#endif
+ frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse
+ frag_data[1] = max(vec4(orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal.
+ frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags
+ frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl
new file mode 100644
index 0000000000..935c3f9301
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl
@@ -0,0 +1,473 @@
+/**
+ * @file class1\deferred\pbrterrainUtilF.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+/*[EXTRA_CODE_HERE]*/
+
+/**
+ * Triplanar mapping implementation adapted from Inigo Quilez' example shader,
+ * MIT license.
+ * https://www.shadertoy.com/view/MtsGWH
+ * Copyright © 2015 Inigo Quilez
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions: The above copyright
+ * notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
+ * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define TERRAIN_PBR_DETAIL_EMISSIVE 0
+#define TERRAIN_PBR_DETAIL_OCCLUSION -1
+#define TERRAIN_PBR_DETAIL_NORMAL -2
+#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
+
+in vec3 vary_vertex_normal;
+
+vec3 srgb_to_linear(vec3 c);
+
+// A relatively agressive threshold for terrain material mixing sampling
+// cutoff. This ensures that only one or two materials are used in most places,
+// making PBR terrain blending more performant. Should be greater than 0 to work.
+#define TERRAIN_RAMP_MIX_THRESHOLD 0.1
+// A small threshold for triplanar mapping sampling cutoff. This and
+// TERRAIN_TRIPLANAR_BLEND_FACTOR together ensures that only one or two samples
+// per texture are used in most places, making triplanar mapping more
+// performant. Should be greater than 0 to work.
+// There's also an artistic design choice in the use of these factors, and the
+// use of triplanar generally. Don't take these triplanar constants for granted.
+#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01
+
+#define SAMPLE_X 1 << 0
+#define SAMPLE_Y 1 << 1
+#define SAMPLE_Z 1 << 2
+#define MIX_X 1 << 3
+#define MIX_Y 1 << 4
+#define MIX_Z 1 << 5
+#define MIX_W 1 << 6
+
+struct PBRMix
+{
+ vec4 col; // RGB color with alpha, linear space
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ vec3 orm; // Occlusion, roughness, metallic
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ vec2 rm; // Roughness, metallic
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ vec3 vNt; // Unpacked normal texture sample, vector
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ vec3 emissive; // RGB emissive color, linear space
+#endif
+};
+
+PBRMix init_pbr_mix()
+{
+ PBRMix mix;
+ mix.col = vec4(0);
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ mix.orm = vec3(0);
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ mix.rm = vec2(0);
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ mix.vNt = vec3(0);
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ mix.emissive = vec3(0);
+#endif
+ return mix;
+}
+
+// Usage example, for two weights:
+// vec2 weights = ... // Weights must add up to 1
+// PBRMix mix = init_pbr_mix();
+// PBRMix mix1 = ...
+// mix = mix_pbr(mix, mix1, weights.x);
+// PBRMix mix2 = ...
+// mix = mix_pbr(mix, mix2, weights.y);
+PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight)
+{
+ PBRMix mix;
+ mix.col = mix1.col + (mix2.col * mix2_weight);
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ mix.orm = mix1.orm + (mix2.orm * mix2_weight);
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ mix.rm = mix1.rm + (mix2.rm * mix2_weight);
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ mix.vNt = mix1.vNt + (mix2.vNt * mix2_weight);
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ mix.emissive = mix1.emissive + (mix2.emissive * mix2_weight);
+#endif
+ return mix;
+}
+
+PBRMix sample_pbr(
+ vec2 uv
+ , sampler2D tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , sampler2D tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , sampler2D tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , sampler2D tex_emissive
+#endif
+ )
+{
+ PBRMix mix;
+ mix.col = texture(tex_col, uv);
+ mix.col.rgb = srgb_to_linear(mix.col.rgb);
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ mix.orm = texture(tex_orm, uv).xyz;
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ mix.rm = texture(tex_orm, uv).yz;
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ mix.vNt = texture(tex_vNt, uv).xyz*2.0-1.0;
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ mix.emissive = srgb_to_linear(texture(tex_emissive, uv).xyz);
+#endif
+ return mix;
+}
+
+struct TerrainTriplanar
+{
+ vec3 weight;
+ int type;
+};
+
+struct TerrainMix
+{
+ vec4 weight;
+ int type;
+};
+
+#define TerrainMixSample vec4[4]
+#define TerrainMixSample3 vec3[4]
+
+TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal)
+{
+ TerrainMix tm;
+ vec4 sample_x = vec4(1,0,0,0);
+ vec4 sample_y = vec4(0,1,0,0);
+ vec4 sample_z = vec4(0,0,1,0);
+ vec4 sample_w = vec4(0,0,0,1);
+
+ tm.weight = mix( mix(sample_w, sample_z, alpha2), mix(sample_y, sample_x, alpha1), alphaFinal );
+ tm.weight -= TERRAIN_RAMP_MIX_THRESHOLD;
+ ivec4 usage = max(ivec4(0), ivec4(ceil(tm.weight)));
+ // Prevent negative weights and keep weights balanced
+ tm.weight = tm.weight*vec4(usage);
+ tm.weight /= (tm.weight.x + tm.weight.y + tm.weight.z + tm.weight.w);
+
+ tm.type = (usage.x * MIX_X) |
+ (usage.y * MIX_Y) |
+ (usage.z * MIX_Z) |
+ (usage.w * MIX_W);
+ return tm;
+}
+
+TerrainTriplanar _t_triplanar()
+{
+ float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR;
+ float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD;
+ vec3 weight_signed = pow(abs(vary_vertex_normal), vec3(sharpness));
+ weight_signed /= (weight_signed.x + weight_signed.y + weight_signed.z);
+ weight_signed -= vec3(threshold);
+ TerrainTriplanar tw;
+ // *NOTE: Make sure the threshold doesn't affect the materials
+ tw.weight = max(vec3(0), weight_signed);
+ tw.weight /= (tw.weight.x + tw.weight.y + tw.weight.z);
+ ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed))));
+ tw.type = ((usage.x) * SAMPLE_X) |
+ ((usage.y) * SAMPLE_Y) |
+ ((usage.z) * SAMPLE_Z);
+ return tw;
+}
+
+// Assume weights add to 1
+float terrain_mix(TerrainMix tm, vec4 tms4)
+{
+ return (tm.weight.x * tms4[0]) +
+ (tm.weight.y * tms4[1]) +
+ (tm.weight.z * tms4[2]) +
+ (tm.weight.w * tms4[3]);
+}
+
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+// Triplanar mapping
+
+// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused)
+#define TerrainCoord vec4[2]
+
+vec2 _t_uv(vec2 uv_unflipped, float sign_or_zero)
+{
+ // Handle case where sign is 0
+ float sign = (2.0*sign_or_zero) + 1.0;
+ sign /= abs(sign);
+ // If the vertex normal is negative, flip the texture back
+ // right-side up.
+ vec2 uv = uv_unflipped * vec2(sign, 1);
+ return uv;
+}
+
+vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero)
+{
+ // Assume normal is unpacked
+ vec3 vNt1 = vNt0;
+ // Get sign
+ float sign = sign_or_zero;
+ // Handle case where sign is 0
+ sign = (2.0*sign) + 1.0;
+ sign /= abs(sign);
+ // If the sign is negative, rotate normal by 180 degrees
+ vNt1.xy = (min(0, sign) * vNt1.xy) + (min(0, -sign) * -vNt1.xy);
+ return vNt1;
+}
+
+// Triplanar-specific normal texture fixes
+vec3 _t_normal_post_x(vec3 vNt0)
+{
+ vec3 vNt_x = _t_normal_post_1(vNt0, sign(vary_vertex_normal.x));
+ // *HACK: Transform normals according to orientation of the UVs
+ vNt_x.xy = vec2(-vNt_x.y, vNt_x.x);
+ return vNt_x;
+}
+vec3 _t_normal_post_y(vec3 vNt0)
+{
+ vec3 vNt_y = _t_normal_post_1(vNt0, sign(vary_vertex_normal.y));
+ // *HACK: Transform normals according to orientation of the UVs
+ vNt_y.xy = -vNt_y.xy;
+ return vNt_y;
+}
+vec3 _t_normal_post_z(vec3 vNt0)
+{
+ vec3 vNt_z = _t_normal_post_1(vNt0, sign(vary_vertex_normal.z));
+ return vNt_z;
+}
+
+PBRMix terrain_sample_pbr(
+ TerrainCoord terrain_coord
+ , TerrainTriplanar tw
+ , sampler2D tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , sampler2D tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , sampler2D tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , sampler2D tex_emissive
+#endif
+ )
+{
+ PBRMix mix = init_pbr_mix();
+
+#define get_uv_x() _t_uv(terrain_coord[0].zw, sign(vary_vertex_normal.x))
+#define get_uv_y() _t_uv(terrain_coord[1].xy, sign(vary_vertex_normal.y))
+#define get_uv_z() _t_uv(terrain_coord[0].xy, sign(vary_vertex_normal.z))
+ switch (tw.type & SAMPLE_X)
+ {
+ case SAMPLE_X:
+ PBRMix mix_x = sample_pbr(
+ get_uv_x()
+ , tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , tex_emissive
+#endif
+ );
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ // Triplanar-specific normal texture fix
+ mix_x.vNt = _t_normal_post_x(mix_x.vNt);
+#endif
+ mix = mix_pbr(mix, mix_x, tw.weight.x);
+ break;
+ default:
+ break;
+ }
+
+ switch (tw.type & SAMPLE_Y)
+ {
+ case SAMPLE_Y:
+ PBRMix mix_y = sample_pbr(
+ get_uv_y()
+ , tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , tex_emissive
+#endif
+ );
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ // Triplanar-specific normal texture fix
+ mix_y.vNt = _t_normal_post_y(mix_y.vNt);
+#endif
+ mix = mix_pbr(mix, mix_y, tw.weight.y);
+ break;
+ default:
+ break;
+ }
+
+ switch (tw.type & SAMPLE_Z)
+ {
+ case SAMPLE_Z:
+ PBRMix mix_z = sample_pbr(
+ get_uv_z()
+ , tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , tex_emissive
+#endif
+ );
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ // Triplanar-specific normal texture fix
+ // *NOTE: Bottom face has not been tested
+ mix_z.vNt = _t_normal_post_z(mix_z.vNt);
+#endif
+ mix = mix_pbr(mix, mix_z, tw.weight.z);
+ break;
+ default:
+ break;
+ }
+
+ return mix;
+}
+
+#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
+
+#define TerrainCoord vec2
+
+#define terrain_sample_pbr sample_pbr
+
+#endif
+
+PBRMix multiply_factors_pbr(
+ PBRMix mix_in
+ , vec4 factor_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , vec3 factor_orm
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , vec2 factor_rm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , vec3 factor_emissive
+#endif
+ )
+{
+ PBRMix mix = mix_in;
+ mix.col *= factor_col;
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ mix.orm *= factor_orm;
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ mix.rm *= factor_rm;
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ mix.emissive *= factor_emissive;
+#endif
+ return mix;
+}
+
+PBRMix terrain_sample_and_multiply_pbr(
+ TerrainCoord terrain_coord
+ , sampler2D tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , sampler2D tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , sampler2D tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , sampler2D tex_emissive
+#endif
+ , vec4 factor_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , vec3 factor_orm
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , vec2 factor_rm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , vec3 factor_emissive
+#endif
+ )
+{
+ PBRMix mix = terrain_sample_pbr(
+ terrain_coord
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+ , _t_triplanar()
+#endif
+ , tex_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , tex_orm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
+ , tex_vNt
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , tex_emissive
+#endif
+ );
+
+ mix = multiply_factors_pbr(mix
+ , factor_col
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
+ , factor_orm
+#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
+ , factor_rm
+#endif
+#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
+ , factor_emissive
+#endif
+ );
+
+ return mix;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl
new file mode 100644
index 0000000000..dbb9404219
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl
@@ -0,0 +1,93 @@
+/**
+ * @file class1\environment\pbrterrainV.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+uniform mat3 normal_matrix;
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+
+in vec3 position;
+in vec3 normal;
+in vec4 tangent;
+in vec4 diffuse_color;
+in vec2 texcoord1;
+
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+out vec4[2] vary_coords;
+#endif
+out vec3 vary_vertex_normal; // Used by pbrterrainUtilF.glsl
+out vec3 vary_normal;
+out vec3 vary_tangent;
+flat out float vary_sign;
+out vec4 vary_texcoord0;
+out vec4 vary_texcoord1;
+
+// *HACK: tangent_space_transform should use texture_normal_transform, or maybe
+// we shouldn't use tangent_space_transform at all. See the call to
+// tangent_space_transform below.
+uniform vec4[2] texture_base_color_transform;
+
+vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
+vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
+
+void main()
+{
+ //transform vertex
+ gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+ vec3 n = normal_matrix * normal;
+ vary_vertex_normal = normal;
+ vec3 t = normal_matrix * tangent.xyz;
+
+ vary_tangent = normalize(t);
+ // *TODO: Decide if we want this. It may be better to just calculate the
+ // tangents on-the-fly in the fragment shader, due to the subtleties of the
+ // effect of triplanar mapping on UVs.
+ // *HACK: Should be using texture_normal_transform here. The KHR texture
+ // transform spec requires handling texture transforms separately for each
+ // individual texture.
+ vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform, texture_matrix0));
+ vary_sign = tangent.w;
+ vary_normal = normalize(n);
+
+ // Transform and pass tex coords
+ // *HACK: texture_base_color_transform is used for all of these here, but
+ // the KHR texture transform spec requires handling texture transforms
+ // separately for each individual texture.
+#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
+ // xy
+ vary_coords[0].xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0);
+ // yz
+ vary_coords[0].zw = texture_transform(position.yz, texture_base_color_transform, texture_matrix0);
+ // (-x)z
+ vary_coords[1].xy = texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform, texture_matrix0);
+#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
+ vary_texcoord0.xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0);
+#endif
+
+ vec4 tc = vec4(texcoord1,0,1);
+ vary_texcoord0.zw = tc.xy;
+ vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0);
+ vary_texcoord1.zw = tc.xy-vec2(1.0, 0.0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index f6d509e2c6..2dba7cb9d9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -39,9 +39,11 @@ in vec4 vary_texcoord0;
in vec4 vary_texcoord1;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 position);
void main()
{
+ mirrorClip(pos);
/// Note: This should duplicate the blending functionality currently used for the terrain rendering.
vec4 color0 = texture(detail_0, vary_texcoord0.xy);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
index f6d3b59e85..8e1e4b54d5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
@@ -25,12 +25,12 @@
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
in vec3 position;
in vec3 normal;
in vec4 diffuse_color;
-in vec2 texcoord0;
in vec2 texcoord1;
out vec3 pos;
@@ -41,18 +41,16 @@ out vec4 vary_texcoord1;
uniform vec4 object_plane_s;
uniform vec4 object_plane_t;
-vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
+vec2 texgen_object(vec4 vpos, mat4 mat, vec4 tp0, vec4 tp1)
{
vec4 tcoord;
tcoord.x = dot(vpos, tp0);
tcoord.y = dot(vpos, tp1);
- tcoord.z = tc.z;
- tcoord.w = tc.w;
tcoord = mat * tcoord;
- return tcoord;
+ return tcoord.xy;
}
void main()
@@ -62,12 +60,12 @@ void main()
vec4 t_pos = modelview_projection_matrix * pre_pos;
gl_Position = t_pos;
- pos = t_pos.xyz;
+ pos = (modelview_matrix*pre_pos).xyz;
vary_normal = normalize(normal_matrix * normal);
// Transform and pass tex coords
- vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy;
+ vary_texcoord0.xy = texgen_object(vec4(position, 1.0), texture_matrix0, object_plane_s, object_plane_t);
vec4 t = vec4(texcoord1,0,1);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl
index 636dfed4ba..732333311c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl
@@ -65,7 +65,7 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl
// Apply texture animation first to avoid shearing and other artifacts
texcoord = (sl_animation_transform * vec4(texcoord, 0, 1)).xy;
// Convert to left-handed coordinate system. The offset of 1 is necessary
- // for rotations to be applied correctly.
+ // for rotation and scale to be applied correctly.
texcoord.y = 1.0 - texcoord.y;
texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy);
// Convert back to right-handed coordinate system
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index e2d87e68fa..f108faf283 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -32,13 +32,16 @@ uniform sampler2D diffuseMap;
in vec4 vertex_color;
in vec3 vary_normal;
in vec2 vary_texcoord0;
+in vec3 vary_position;
uniform float minimum_alpha;
vec2 encode_normal(vec3 n);
+void mirrorClip(vec3 pos);
void main()
{
+ mirrorClip(vary_position);
vec4 col = texture(diffuseMap, vary_texcoord0.xy);
if (col.a < minimum_alpha)
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
index ce8a10712c..c84fccd4c6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
@@ -24,6 +24,7 @@
*/
uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
uniform mat3 normal_matrix;
@@ -34,11 +35,14 @@ in vec2 texcoord0;
out vec3 vary_normal;
out vec4 vertex_color;
out vec2 vary_texcoord0;
+out vec3 vary_position;
void main()
{
//transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
+
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
vary_normal = normalize(normal_matrix * normal);
diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl
new file mode 100644
index 0000000000..388042e7e0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl
@@ -0,0 +1,33 @@
+/**
+ * @file normaldebugF.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+out vec4 frag_color;
+
+in vec4 vertex_color;
+
+void main()
+{
+ frag_color = max(vertex_color, vec4(0));
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl
new file mode 100644
index 0000000000..51d05cd507
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl
@@ -0,0 +1,76 @@
+/**
+ * @file normaldebugG.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// *NOTE: Geometry shaders have a reputation for being slow. Consider using
+// compute shaders instead, which have a reputation for being fast. This
+// geometry shader in particular seems to run fine on my machine, but I won't
+// vouch for this in performance-critical areas.
+// -Cosmic,2023-09-28
+
+out vec4 vertex_color;
+
+in vec4 normal_g[];
+#ifdef HAS_ATTRIBUTE_TANGENT
+in vec4 tangent_g[];
+#endif
+
+layout(triangles) in;
+#ifdef HAS_ATTRIBUTE_TANGENT
+layout(line_strip, max_vertices = 12) out;
+#else
+layout(line_strip, max_vertices = 6) out;
+#endif
+
+void triangle_normal_debug(int i)
+{
+ // Normal
+ vec4 normal_color = vec4(1.0, 1.0, 0.0, 1.0);
+ gl_Position = gl_in[i].gl_Position;
+ vertex_color = normal_color;
+ EmitVertex();
+ gl_Position = normal_g[i];
+ vertex_color = normal_color;
+ EmitVertex();
+ EndPrimitive();
+
+#ifdef HAS_ATTRIBUTE_TANGENT
+ // Tangent
+ vec4 tangent_color = vec4(0.0, 1.0, 1.0, 1.0);
+ gl_Position = gl_in[i].gl_Position;
+ vertex_color = tangent_color;
+ EmitVertex();
+ gl_Position = tangent_g[i];
+ vertex_color = tangent_color;
+ EmitVertex();
+ EndPrimitive();
+#endif
+}
+
+void main()
+{
+ triangle_normal_debug(0);
+ triangle_normal_debug(1);
+ triangle_normal_debug(2);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl
new file mode 100644
index 0000000000..b198bc2485
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl
@@ -0,0 +1,74 @@
+/**
+ * @file normaldebugV.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+in vec3 position;
+in vec3 normal;
+out vec4 normal_g;
+#ifdef HAS_ATTRIBUTE_TANGENT
+in vec4 tangent;
+out vec4 tangent_g;
+#endif
+
+uniform float debug_normal_draw_length;
+
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+#else
+uniform mat3 normal_matrix;
+#endif
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+
+// *NOTE: Should use the modelview_projection_matrix here in the non-skinned
+// case for efficiency, but opting for the simplier implementation for now as
+// this is debug code. Also, the skinned version hasn't beeen tested yet.
+// world_pos = mat * vec4(position.xyz, 1.0)
+vec4 get_screen_normal(vec3 position, vec4 world_pos, vec3 normal, mat4 mat)
+{
+ vec4 world_norm = mat * vec4((position + normal), 1.0);
+ world_norm.xyz -= world_pos.xyz;
+ world_norm.xyz = debug_normal_draw_length * normalize(world_norm.xyz);
+ world_norm.xyz += world_pos.xyz;
+ return projection_matrix * world_norm;
+}
+
+void main()
+{
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+#else
+#define mat modelview_matrix
+#endif
+
+ vec4 world_pos = mat * vec4(position.xyz,1.0);
+
+ gl_Position = projection_matrix * world_pos;
+ normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat);
+#ifdef HAS_ATTRIBUTE_TANGENT
+ tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat);
+#endif
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
index 9ecdf0bf77..c1ed1bfe6e 100644
--- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
@@ -38,6 +38,7 @@ in vec3 vary_dir;
uniform float mipLevel;
uniform int u_width;
uniform float max_probe_lod;
+uniform float probe_strength;
// =============================================================================================================
@@ -129,7 +130,7 @@ vec4 prefilterEnvMap(vec3 R)
float totalWeight = 0.0;
float envMapDim = float(textureSize(reflectionProbes, 0).s);
float roughness = mipLevel/max_probe_lod;
- int numSamples = max(int(32*roughness), 1);
+ int numSamples = max(int(PROBE_FILTER_SAMPLES*roughness), 1);
float numMips = max_probe_lod+1;
@@ -163,5 +164,6 @@ void main()
{
vec3 N = normalize(vary_dir);
frag_color = max(prefilterEnvMap(N), vec4(0));
+ frag_color.a *= probe_strength;
}
// =============================================================================================================
diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl
index 67c99530e3..142f2a5d71 100644
--- a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl
@@ -30,9 +30,13 @@ uniform sampler2D texture1;
in vec2 vary_texcoord0;
in vec2 vary_texcoord1;
+in vec3 vary_position;
+
+void mirrorClip(vec3 pos);
void main()
{
+ mirrorClip(vary_position);
float tex0 = texture(texture0, vary_texcoord0.xy).a;
float tex1 = texture(texture1, vary_texcoord1.xy).a;
diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
index 7d5417919e..b8a02fbdec 100644
--- a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
@@ -23,6 +23,7 @@
* $/LicenseInfo$
*/
+uniform mat4 modelview_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix;
@@ -32,11 +33,11 @@ in vec2 texcoord1;
out vec2 vary_texcoord0;
out vec2 vary_texcoord1;
+out vec3 vary_position;
#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
uniform mat4 projection_matrix;
-uniform mat4 modelview_matrix;
#endif
void main()
@@ -46,8 +47,10 @@ void main()
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
vec4 pos = mat * vec4(position.xyz, 1.0);
+ vary_position = pos.xyz;
gl_Position = projection_matrix * pos;
#else
+ vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
#endif
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index acd32a81b3..4aef22c296 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -78,6 +78,8 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
float getAmbientClamp();
+void mirrorClip(vec3 pos);
+
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
@@ -167,6 +169,8 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec
void main()
{
+ mirrorClip(vary_position);
+
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
vec4 pos = vec4(vary_position, 1.0);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
index 003dd05e6f..059c2a64ce 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
@@ -90,6 +90,7 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
+void mirrorClip(vec3 pos);
void waterClip(vec3 pos);
void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor);
@@ -156,6 +157,8 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
void main()
{
+ mirrorClip(vary_position);
+
vec3 color = vec3(0,0,0);
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
index 8430cca325..c382a9fbc0 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/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
index ec1e49eeb4..0476b98e10 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;
@@ -285,12 +292,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
@@ -407,9 +414,12 @@ void main()
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
+
+ float flag = GBUFFER_FLAG_HAS_ATMOS;
+
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[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
frag_data[3] = vec4(0);
#endif
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 906e66ecc8..14d9cf798f 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;
@@ -681,6 +682,100 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
return col[1]+col[0];
}
+
+#if defined(HERO_PROBES)
+
+uniform vec4 clipPlane;
+
+uniform samplerCubeArray heroProbes;
+
+layout (std140) uniform HeroProbeData
+{
+ mat4 heroBox[1];
+ vec4 heroSphere[1];
+ uint heroShape[1];
+ int heroMipCount;
+ int heroProbeCount;
+};
+
+vec3 boxIntersectHero(vec3 origin, vec3 dir, int 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 = heroBox[i];
+
+ vec3 RayLS = mat3(clipToLocal) * dir;
+ vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
+
+ d = 1.0-max(max(abs(PositionLS.x), abs(PositionLS.y)), abs(PositionLS.z));
+
+ vec3 Unitary = vec3(scale);
+ vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS;
+ vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS;
+ vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect);
+ float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z));
+
+ // Use Distance in CS directly to recover intersection
+ vec3 IntersectPositionCS = origin + dir * Distance;
+
+ return IntersectPositionCS;
+}
+
+float sphereWeightHero(vec3 pos, vec3 dir, vec3 origin, float r, out float dw)
+{
+ 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;
+
+ dw = w * atten * max(r, 1.0)*4;
+
+ w *= atten;
+
+ return w;
+}
+
+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;
+ if (heroShape[0] < 1)
+ {
+ float d = 0;
+ boxIntersectHero(pos, norm, 0, d, 1.0);
+
+ w = max(d, 0.001);
+ }
+ else
+ {
+ float r = heroSphere[0].w;
+ //v = sphereIntersect(pos, norm, heroSphere[0].xyz, 4096.0*4096.0);
+
+ w = sphereWeightHero(pos, norm, heroSphere[0].xyz, r, dw);
+ }
+
+ {
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+ if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0)
+ {
+ 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 +807,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,
@@ -799,6 +896,7 @@ 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)
@@ -826,6 +924,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/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 5e8fe9301a..2f90249169 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;
@@ -178,7 +179,7 @@ void main()
float gloss = 1.0 - perceptualRoughness;
sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss, false, amblit_linear);
-
+
adjustIrradiance(irradiance, ambocc);
vec3 diffuseColor;
@@ -209,7 +210,7 @@ void main()
vec3 legacyenv = vec3(0);
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity, false, amblit_linear);
-
+
adjustIrradiance(irradiance, ambocc);
// apply lambertian IBL only (see pbrIbl)
@@ -244,6 +245,7 @@ void main()
// add radiance map
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
+
}
color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a);
diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
index 223e55eb69..ef086fc3be 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 b364e454e8..b2a81aa025 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);