diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-06-11 10:21:19 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-06-11 10:21:19 -0400 |
commit | 30f4163b7b576d96533b61d9b31243960fb83f2e (patch) | |
tree | bd5dc1450e08c674a4619d7f16a9a4816005f9c4 /indra/newview/app_settings/shaders/class1/deferred | |
parent | 3d1aac4f5c369e9d402c41f1c790d9015f7c7773 (diff) | |
parent | f5e2708a0fc4e08d3d0a5dc393bbd4bac09e1c55 (diff) |
Merge branch 'main' of github.com:secondlife/viewer into lua-bradfix
to pick up Featurettes promotion + Brad's GitHub Windows build workaround.
Diffstat (limited to 'indra/newview/app_settings/shaders/class1/deferred')
34 files changed, 1282 insertions, 206 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl index d9a6c9e5f1..d3ca3ec8c1 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 63d8e12e62..b904df3a1b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -25,7 +25,7 @@ /*[EXTRA_CODE_HERE]*/ -out vec4 frag_data[3]; +out vec4 frag_data[4]; uniform sampler2D diffuseMap; @@ -33,11 +33,14 @@ 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) @@ -48,6 +51,7 @@ void main() frag_data[0] = vec4(diff.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 74d16592de..aabbbac12a 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/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 19fc660c2d..8627ab1852 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file blurLightF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -40,18 +40,18 @@ uniform float kern_scale; in vec2 vary_fragcoord; vec4 getPosition(vec2 pos_screen); -vec3 getNorm(vec2 pos_screen); +vec4 getNorm(vec2 pos_screen); -void main() +void main() { vec2 tc = vary_fragcoord.xy; - vec3 norm = getNorm(tc); + vec4 norm = getNorm(tc); vec3 pos = getPosition(tc).xyz; vec4 ccol = texture(lightMap, tc).rgba; - + vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); dlt /= max(-pos.z*dist_factor, 1.0); - + vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' vec4 col = defined_weight.xyxx * ccol; @@ -75,15 +75,15 @@ void main() k[1] = (k[0]+k[2])*0.5f; k[3] = (k[2]+k[4])*0.5f; k[5] = (k[4]+k[6])*0.5f; - + for (int i = 1; i < 7; i++) { vec2 samptc = tc + k[i].z*dlt*2.0; samptc /= screen_res; - vec3 samppos = getPosition(samptc).xyz; + vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - + if (d*d <= pointplanedist_tolerance_pow2) { col += texture(lightMap, samptc)*k[i].xyxx; @@ -95,10 +95,10 @@ void main() { vec2 samptc = tc - k[i].z*dlt*2.0; samptc /= screen_res; - vec3 samppos = getPosition(samptc).xyz; + vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - + if (d*d <= pointplanedist_tolerance_pow2) { col += texture(lightMap, samptc)*k[i].xyxx; @@ -108,7 +108,7 @@ void main() col /= defined_weight.xyxx; //col.y *= col.y; - + frag_color = max(col, vec4(0)); #ifdef IS_AMD_CARD diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 11deecafbb..2cc3085cd0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -37,11 +37,13 @@ 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) @@ -60,6 +62,6 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + frag_data[2] = vec4(nvn, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index 4ac757be65..a381392f6c 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/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index 5ef3d63eb2..01543732d0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -50,6 +50,7 @@ SOFTWARE. uniform sampler2D normalMap; uniform sampler2D depthMap; +uniform sampler2D emissiveRect; uniform sampler2D projectionMap; // rgba uniform sampler2D brdfLut; @@ -140,40 +141,11 @@ vec2 getScreenCoordinate(vec2 screenpos) return sc - vec2(1.0, 1.0); } -// See: https://aras-p.info/texts/CompactNormalStorage.html -// Method #4: Spheremap Transform, Lambert Azimuthal Equal-Area projection -vec3 getNorm(vec2 screenpos) +vec4 getNorm(vec2 screenpos) { - vec2 enc = texture(normalMap, screenpos.xy).xy; - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; -} - -vec3 getNormalFromPacked(vec4 packedNormalEnvIntensityFlags) -{ - vec2 enc = packedNormalEnvIntensityFlags.xy; - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return normalize(n); // TODO: Is this normalize redundant? -} - -// return packedNormalEnvIntensityFlags since GBUFFER_FLAG_HAS_PBR needs .w -// See: C++: addDeferredAttachments(), GLSL: softenLightF -vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity) -{ - vec4 packedNormalEnvIntensityFlags = texture(normalMap, screenpos.xy); - n = getNormalFromPacked( packedNormalEnvIntensityFlags ); - envIntensity = packedNormalEnvIntensityFlags.z; - return packedNormalEnvIntensityFlags; + vec4 norm = texture(normalMap, screenpos.xy); + norm.xyz = normalize(norm.xyz); + return norm; } // get linear depth value given a depth buffer sample d and znear and zfar values diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index c2fb3201f4..1751e17814 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -31,14 +31,18 @@ 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) @@ -49,7 +53,7 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index dce1f91bc3..f5b517a8ea 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -28,16 +28,19 @@ out vec4 frag_data[4]; in vec3 vary_normal; +in vec3 vary_position; uniform float minimum_alpha; in vec4 vertex_color; 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) @@ -48,6 +51,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index 1fc719dde5..89ea0c1710 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -34,8 +34,6 @@ uniform sampler2D diffuseMap; in vec3 vary_normal; in vec2 vary_texcoord0; -vec2 encode_normal(vec3 n); - void main() { vec4 col = texture(diffuseMap, vary_texcoord0.xy); @@ -48,7 +46,7 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index d3d375b20a..7f056a51e8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -32,17 +32,19 @@ 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 //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index afdd043c7c..5c73878ba9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -30,12 +30,14 @@ out vec4 frag_data[4]; 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); vec3 linear_to_srgb(vec3 c); void main() { + mirrorClip(vary_position); vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; vec3 spec; @@ -44,6 +46,6 @@ void main() frag_data[0] = vec4(col, 0.0); frag_data[1] = vec4(spec, vertex_color.a); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 304c01ecc3..4bd31cef9e 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 709b47dcbd..eff7221ae7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl @@ -1,34 +1,36 @@ -/** +/** * @file exposureF.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]*/ out vec4 frag_color; uniform sampler2D emissiveRect; +#ifdef USE_LAST_EXPOSURE uniform sampler2D exposureMap; +#endif uniform float dt; uniform vec2 noiseVec; @@ -41,7 +43,7 @@ float lum(vec3 col) return dot(l, col); } -void main() +void main() { vec2 tc = vec2(0.5,0.5); @@ -51,11 +53,13 @@ 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 ec6a4a502f..52dfed06ae 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file deferred/fullbrightF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - + /*[EXTRA_CODE_HERE]*/ out vec4 frag_color; @@ -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 main() -{ +void mirrorClip(vec3 pos); +void main() +{ + mirrorClip(vary_position); #ifdef IS_ALPHA waterClip(vary_position.xyz); #endif @@ -88,7 +90,7 @@ void main() calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten); color.rgb = applySkyAndWaterFog(pos, additive, atten, color).rgb; - + #endif #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/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index 5561a3d488..99cb23839a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -37,7 +37,6 @@ uniform sampler2D specularMap; in vec2 vary_texcoord0; vec3 linear_to_srgb(vec3 c); -vec2 encode_normal (vec3 n); void main() { @@ -53,6 +52,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = spec; - frag_data[2] = vec4(encode_normal(norm.xyz),0,GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(norm.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl index b9337a357f..95b2f80e06 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -1,32 +1,32 @@ -/** +/** * @file luminanceF.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]*/ -// take a luminance sample of diffuseRect and emissiveRect +// take a luminance sample of diffuseRect and emissiveRect out vec4 frag_color; @@ -34,6 +34,8 @@ in vec2 vary_fragcoord; uniform sampler2D diffuseRect; uniform sampler2D emissiveRect; +uniform sampler2D normalMap; +uniform float diffuse_luminance_scale; float lum(vec3 col) { @@ -41,11 +43,25 @@ float lum(vec3 col) return dot(l, col); } -void main() +void main() { vec2 tc = vary_fragcoord*0.6+0.2; tc.y -= 0.1; // HACK - nudge exposure sample down a little bit to favor ground over sky - vec3 c = texture(diffuseRect, tc).rgb + texture(emissiveRect, tc).rgb; + vec3 c = texture(diffuseRect, tc).rgb; + + vec4 norm = texture(normalMap, tc); + + if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI) && + !GET_GBUFFER_FLAG(GBUFFER_FLAG_SKIP_ATMOS)) + { + // Apply the diffuse luminance scale to objects but not the sky + // Prevents underexposing when looking at bright environments + // while still allowing for realistically bright skies. + c *= diffuse_luminance_scale; + } + + c += texture(emissiveRect, tc).rgb; + float L = lum(c); frag_color = vec4(max(L, 0.0)); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 5e48ff709f..b6528dfcf8 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/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl index 03a8518c36..6ef556d7e8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file class1\deferred\moonF.glsl * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2005, 2020 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_data[4]; @@ -34,7 +34,7 @@ uniform sampler2D diffuseMap; in vec2 vary_texcoord0; -void main() +void main() { // Restore Pre-EEP alpha fade moon near horizon float fade = 1.0; @@ -55,7 +55,7 @@ void main() frag_data[0] = vec4(0); frag_data[1] = vec4(0.0); - frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); frag_data[3] = vec4(c.rgb, c.a); // Added and commented out for a ground truth. Do not uncomment - Geenz diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl index c1fb9f5d84..35b7602569 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file pbrShadowAlphaMaskF.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$ */ @@ -33,9 +33,9 @@ in vec4 vertex_color; in vec2 vary_texcoord0; uniform float minimum_alpha; -void main() +void main() { - float alpha = texture(diffuseMap,vary_texcoord0.xy).a; + float alpha = texture(diffuseMap,vary_texcoord0.xy).a * vertex_color.a; if (alpha < minimum_alpha) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index ed19fba228..380d493636 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file pbropaqueF.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$ */ @@ -28,7 +28,7 @@ #ifndef IS_HUD -// deferred opaque implementation +// deferred opaque implementation uniform sampler2D diffuseMap; //always in sRGB space @@ -54,28 +54,38 @@ in vec2 emissive_texcoord; uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() -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; + basecolor.rgb = srgb_to_linear(basecolor.rgb); + + basecolor *= vertex_color; + if (basecolor.a < minimum_alpha) { discard; } - vec3 col = vertex_color.rgb * srgb_to_linear(basecolor.rgb); + vec3 col = basecolor.rgb; // from mikktspace.com vec3 vNt = texture(bumpMap, normal_texcoord.xy).xyz*2.0-1.0; float sign = vary_sign; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; - + vec3 vB = sign * cross(vN, vT); vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); @@ -85,7 +95,7 @@ void main() // roughness 0.0 // metal 0.0 vec3 spec = texture(specularMap, metallic_roughness_texcoord.xy).rgb; - + spec.g *= roughnessFactor; spec.b *= metallicFactor; @@ -102,8 +112,8 @@ void main() //emissive = tnorm*0.5+0.5; // See: C++: addDeferredAttachments(), GLSL: softenLightF frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse - frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(encode_normal(tnorm), vertex_color.a, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags + frag_data[1] = max(vec4(spec.rgb,0.0), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // 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/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl index 53e4b732df..fd020afd57 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..0de2d348c3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -0,0 +1,347 @@ +/** + * @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_position; +in vec3 vary_normal; +in vec3 vary_tangent; +flat in float vary_sign; +in vec4 vary_texcoord0; +in vec4 vary_texcoord1; + +void mirrorClip(vec3 position); + +float terrain_mix(TerrainMix tm, vec4 tms4); + +void main() +{ + // Make sure we clip the terrain if we're in a mirror. + mirrorClip(vary_position); + +#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 pbr_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 + ); + pbr_mix = mix_pbr(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 + ); + pbr_mix = mix_pbr(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 + ); + pbr_mix = mix_pbr(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 + ); + pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.w); + break; + default: + break; + } + + float minimum_alpha = terrain_mix(tm, minimum_alphas); + if (pbr_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 = pbr_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 mix_emissive pbr_mix.emissive +#else +#define mix_emissive vec3(0) +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) +#define mix_orm pbr_mix.orm +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) +#define mix_orm vec3(1.0, pbr_mix.rm) +#else +// Matte plastic potato terrain +#define mix_orm vec3(1.0, 1.0, 0.0) +#endif + frag_data[0] = max(vec4(pbr_mix.col.xyz, 0.0), vec4(0)); // Diffuse + frag_data[1] = max(vec4(mix_orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, flags + frag_data[3] = max(vec4(mix_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..ed52297314 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -0,0 +1,96 @@ +/** + * @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_matrix; +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; +out vec3 vary_position; + +// *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 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform); +vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform); + +void main() +{ + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; + + 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(terrain_tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform)); + 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 = terrain_texture_transform(position.xy, texture_base_color_transform); + // yz + vary_coords[0].zw = terrain_texture_transform(position.yz, texture_base_color_transform); + // (-x)z + vary_coords[1].xy = terrain_texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform); +#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 + vary_texcoord0.xy = terrain_texture_transform(position.xy, texture_base_color_transform); +#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/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index 7a25f63260..a0eb6cfbb8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -97,6 +97,7 @@ vec3 toneMapACES_Hill(vec3 color) uniform float exposure; uniform float gamma; +uniform float aces_mix; vec3 toneMap(vec3 color) { @@ -106,7 +107,7 @@ vec3 toneMap(vec3 color) color *= exposure * exp_scale; // mix ACES and Linear here as a compromise to avoid over-darkening legacy content - color = mix(toneMapACES_Hill(color), color, 0.3); + color = mix(toneMapACES_Hill(color), color, aces_mix); #endif return color; @@ -152,6 +153,15 @@ float noise(vec2 x) { //============================= +void debugExposure(inout vec3 color) +{ + float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; + exp_scale *= 0.5; + if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1) + { + color = vec3(1,0,0); + } +} vec3 legacyGamma(vec3 color) { @@ -181,6 +191,7 @@ void main() vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb)); diff.rgb += nz*0.003; + //debugExposure(diff.rgb); frag_color = max(diff, vec4(0)); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index a07a4301bc..785c748234 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file class1/deferred/skyF.glsl * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2005, 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$ */ @@ -27,6 +27,15 @@ in vec3 vary_HazeColor; in float vary_LightNormPosDot; +#ifdef HAS_HDRI +in vec4 vary_position; +in vec3 vary_rel_pos; +uniform float sky_hdr_scale; +uniform float hdri_split_screen; +uniform mat3 env_mat; +uniform sampler2D environmentMap; +#endif + uniform sampler2D rainbow_map; uniform sampler2D halo_map; @@ -37,6 +46,9 @@ uniform float ice_level; out vec4 frag_data[4]; vec3 srgb_to_linear(vec3 c); +vec3 linear_to_srgb(vec3 c); + +#define PI 3.14159265 ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky @@ -71,24 +83,42 @@ vec3 halo22(float d) void main() { - // Potential Fill-rate optimization. Add cloud calculation - // back in and output alpha of 0 (so that alpha culling kills - // the fragment) if the sky wouldn't show up because the clouds - // are fully opaque. - - vec3 color = vary_HazeColor; - - float rel_pos_lightnorm = vary_LightNormPosDot; - float optic_d = rel_pos_lightnorm; - vec3 halo_22 = halo22(optic_d); - color.rgb += rainbow(optic_d); - color.rgb += halo_22; - color.rgb *= 2.; - color.rgb = clamp(color.rgb, vec3(0), vec3(5)); + vec3 color; +#ifdef HAS_HDRI + vec3 frag_coord = vary_position.xyz/vary_position.w; + if (-frag_coord.x > ((1.0-hdri_split_screen)*2.0-1.0)) + { + vec3 pos = normalize(vary_rel_pos); + pos = env_mat * pos; + vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI); + color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale; + color = min(color, vec3(8192*8192*16)); // stupidly large value arrived at by binary search -- avoids framebuffer corruption from some HDRIs + + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_HAS_HDRI); + } + else +#endif + { + // Potential Fill-rate optimization. Add cloud calculation + // back in and output alpha of 0 (so that alpha culling kills + // the fragment) if the sky wouldn't show up because the clouds + // are fully opaque. + + color = vary_HazeColor; + + float rel_pos_lightnorm = vary_LightNormPosDot; + float optic_d = rel_pos_lightnorm; + vec3 halo_22 = halo22(optic_d); + color.rgb += rainbow(optic_d); + color.rgb += halo_22; + color.rgb *= 2.; + color.rgb = clamp(color.rgb, vec3(0), vec3(5)); + + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); + } frag_data[0] = vec4(0); frag_data[1] = vec4(0); - frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog frag_data[3] = vec4(color.rgb, 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 6110b6ade0..24d2db2183 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -35,6 +35,11 @@ in vec3 position; out vec3 vary_HazeColor; out float vary_LightNormPosDot; +#ifdef HAS_HDRI +out vec4 vary_position; +out vec3 vary_rel_pos; +#endif + // Inputs uniform vec3 camPosLocal; @@ -72,6 +77,11 @@ void main() // Get relative position vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0); +#ifdef HAS_HDRI + vary_rel_pos = rel_pos; + vary_position = pos; +#endif + // Adj position vector to clamp altitude if (rel_pos.y > 0.) { @@ -92,13 +102,13 @@ void main() // Initialize temp variables vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color * 0.7; //magic 0.7 to match legacy color - + // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights - vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density)); + vec3 combined_haze = max(abs(blue_density) + vec3(abs(haze_density)), vec3(1e-6)); vec3 blue_weight = blue_density / combined_haze; vec3 haze_weight = haze_density / combined_haze; @@ -142,7 +152,7 @@ void main() sunlight *= max(0.0, (1. - cloud_shadow)); // Haze color below cloud - vec3 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient) + vec3 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient)); // Attenuate cloud color by atmosphere diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index bee9e6d2fe..5f598f84a7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file class1\deferred\terrainF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - + /*[EXTRA_CODE_HERE]*/ out vec4 frag_data[4]; @@ -38,12 +38,13 @@ in vec3 vary_normal; 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); vec4 color1 = texture(detail_1, vary_texcoord0.xy); vec4 color2 = texture(detail_2, vary_texcoord0.xy); @@ -53,13 +54,13 @@ void main() float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a; vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); - - outColor.a = 0.0; // yes, downstream atmospherics - + + outColor.a = 0.0; // yes, downstream atmospherics + frag_data[0] = outColor; frag_data[1] = vec4(0.0,0.0,0.0,-1.0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index aab2abff1e..b4ab7cd169 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -1,36 +1,36 @@ -/** +/** * @file class1\environment\terrainV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ uniform 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,18 @@ 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.z = 0; + tcoord.w = 1; - tcoord = mat * tcoord; - - return tcoord; + tcoord = mat * tcoord; + + return tcoord.xy; } void main() @@ -62,15 +62,15 @@ 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); - + vary_texcoord0.zw = t.xy; vary_texcoord1.xy = t.xy-vec2(2.0, 0.0); vary_texcoord1.zw = t.xy-vec2(1.0, 0.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl index 8e641522e3..7c02cb9d4a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file class1/deferred/textureUtilV.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$ */ @@ -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 @@ -77,6 +77,19 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl return texcoord; } +// Similar to texture_transform but no offset during coordinate system +// conversion, and no texture animation support. +vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform) +{ + vec2 texcoord = vertex_texcoord; + + texcoord.y = -texcoord.y; + texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy); + texcoord.y = -texcoord.y; + + return texcoord; +} + // Take the rotation only from both transforms and apply to the tangent. This // accounts for the change of the topology of the normal texture when a texture // rotation is applied to it. @@ -120,3 +133,25 @@ vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] kh return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); } + +// Similar to tangent_space_transform but no no texture animation support. +vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform) +{ + // Immediately convert to left-handed coordinate system ((0,1) -> (0, -1)) + vec2 weights = vec2(0, -1); + + // Apply KHR_texture_transform (rotation only) + float khr_rotation = khr_gltf_transform[0].z; + mat2 khr_rotation_mat = mat2( + cos(khr_rotation),-sin(khr_rotation), + sin(khr_rotation), cos(khr_rotation) + ); + weights = khr_rotation_mat * weights; + + // Convert back to right-handed coordinate system + weights.y = -weights.y; + + vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz); + + return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index db6070f328..05922ecb1a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -32,13 +32,14 @@ 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) { @@ -48,6 +49,6 @@ void main() frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index 81900fba70..ef5602f1e5 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); |