diff options
Diffstat (limited to 'indra/newview/app_settings/shaders')
30 files changed, 533 insertions, 289 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl index ce018623a8..1a065daf89 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl @@ -78,10 +78,10 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen) { float ret = 1.0; vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture(noiseMap, pos_screen.xy * (screen_res / 128)).xy; + vec2 noise_reflect = texture(noiseMap, pos_screen.xy * (screen_res / 128.0)).xy; float angle_hidden = 0.0; - float points = 0; + float points = 0.0; float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index 94711be473..63ab0b9b38 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -80,6 +80,18 @@ vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten); vec4 decodeNormal(vec4 norm); +vec3 clampHDRRange(vec3 color) +{ + // Why do this? + // There are situations where the color range will go to something insane - potentially producing infs and NaNs even. + // This is a safety measure to prevent that. + // As to the specific number there - allegedly some HDR displays expect values to be in the 0-11.2 range. Citation needed. + // -Geenz 2025-03-05 + color = mix(color, vec3(1), isinf(color)); + color = mix(color, vec3(0.0), isnan(color)); + return clamp(color, vec3(0.0), vec3(11.2)); +} + float calcLegacyDistanceAttenuation(float distance, float falloff) { float dist_atten = 1.0 - clamp((distance + falloff)/(1.0 + falloff), 0.0, 1.0); @@ -253,7 +265,7 @@ vec4 texture2DLodSpecular(vec2 tc, float lod) vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); float det = min(lod/(proj_lod*0.5), 1.0); float d = min(dist.x, dist.y); - d *= min(1, d * (proj_lod - lod)); // BUG? extra factor compared to diffuse causes N repeats + d *= min(1.0, d * (proj_lod - lod)); // BUG? extra factor compared to diffuse causes N repeats float edge = 0.25*det; ret *= clamp(d/edge, 0.0, 1.0); @@ -371,7 +383,7 @@ void pbrIbl(vec3 diffuseColor, out vec3 specularOut) { // retrieve a scale and bias to F0. See [1], Figure 3 - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough); + vec2 brdf = BRDF(clamp(nv, 0.0, 1.0), 1.0-perceptualRough); vec3 diffuseLight = irradiance; vec3 specularLight = radiance; @@ -426,9 +438,10 @@ float geometricOcclusion(PBRInfo pbrInputs) float NdotL = pbrInputs.NdotL; float NdotV = pbrInputs.NdotV; float r = pbrInputs.alphaRoughness; + float r2 = r * r; - float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); - float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); + float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r2 + (1.0 - r2) * (NdotL * NdotL))); + float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r2 + (1.0 - r2) * (NdotV * NdotV))); return attenuationL * attenuationV; } @@ -613,24 +626,11 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, uniform vec4 waterPlane; uniform float waterSign; -// discard if given position in eye space is on the wrong side of the waterPlane according to waterSign void waterClip(vec3 pos) { - // TODO: make this less branchy - if (waterSign > 0) + if (((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) * waterSign) < 0.0) { - if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < 0.0) - { - discard; - } + discard; } - else - { - if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) > 0.0) - { - discard; - } - } - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl index 2ed4ba3163..9060d358cf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl @@ -34,7 +34,7 @@ uniform float clipSign; void mirrorClip(vec3 pos) { - if (mirror_flag > 0) + if (mirror_flag > 0.0) { if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl index 4acab159cb..4331418b33 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -37,14 +37,10 @@ uniform sampler2D emissiveRect; uniform sampler2D normalMap; uniform float diffuse_luminance_scale; -float lum(vec3 col) -{ - vec3 l = vec3(0.2126, 0.7152, 0.0722); - return dot(l, col); -} void main() { + const vec3 l = vec3(0.2126, 0.7152, 0.0722); 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; @@ -62,7 +58,7 @@ void main() c += texture(emissiveRect, tc).rgb; - float L = lum(c); + float L = dot(l, c); frag_color = vec4(max(L, 0.0)); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index dc43007dca..fb4b139662 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -297,7 +297,7 @@ vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero) 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); + vNt1.xy = (min(0.0, sign) * vNt1.xy) + (min(0.0, -sign) * -vNt1.xy); return vNt1; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 9797bcd2ce..4e737492a7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -69,6 +69,8 @@ void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc) w += wg; } +vec3 clampHDRRange(vec3 color); + void main() { vec2 tc = vary_fragcoord.xy; @@ -120,5 +122,6 @@ void main() diff /= w; } + diff.rgb = clampHDRRange(diff.rgb); frag_color = diff; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index befd2ae6da..4ccc6f54a8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -43,6 +43,8 @@ vec3 legacyGamma(vec3 color) return c; } +vec3 clampHDRRange(vec3 color); + void main() { //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB) @@ -53,6 +55,7 @@ void main() diff.rgb = legacyGamma(diff.rgb); #endif - frag_color = max(diff, vec4(0)); + diff.rgb = clampHDRRange(diff.rgb); + frag_color = diff; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl index 32b0a1ac8e..c05b4eed7a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl @@ -71,6 +71,7 @@ float noise(vec2 x) { //============================= +vec3 clampHDRRange(vec3 color); void main() @@ -84,6 +85,7 @@ void main() diff.rgb += nz*0.003; #endif + diff.rgb = clampHDRRange(diff.rgb); frag_color = diff; gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl index fc6d4d7727..1f01c7f16a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl @@ -28,138 +28,13 @@ out vec4 frag_color; uniform sampler2D diffuseRect; -uniform sampler2D exposureMap; -uniform vec2 screen_res; in vec2 vary_fragcoord; vec3 linear_to_srgb(vec3 cl); +vec3 toneMap(vec3 color); -//=============================================================== -// tone mapping taken from Khronos sample implementation -//=============================================================== - -// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT -const mat3 ACESInputMat = mat3 -( - 0.59719, 0.07600, 0.02840, - 0.35458, 0.90834, 0.13383, - 0.04823, 0.01566, 0.83777 -); - - -// ODT_SAT => XYZ => D60_2_D65 => sRGB -const mat3 ACESOutputMat = mat3 -( - 1.60475, -0.10208, -0.00327, - -0.53108, 1.10813, -0.07276, - -0.07367, -0.00605, 1.07602 -); - -// ACES tone map (faster approximation) -// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ -vec3 toneMapACES_Narkowicz(vec3 color) -{ - const float A = 2.51; - const float B = 0.03; - const float C = 2.43; - const float D = 0.59; - const float E = 0.14; - return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0); -} - - -// ACES filmic tone map approximation -// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl -vec3 RRTAndODTFit(vec3 color) -{ - vec3 a = color * (color + 0.0245786) - 0.000090537; - vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081; - return a / b; -} - - -// tone mapping -vec3 toneMapACES_Hill(vec3 color) -{ - color = ACESInputMat * color; - - // Apply RRT and ODT - color = RRTAndODTFit(color); - - color = ACESOutputMat * color; - - // Clamp to [0, 1] - color = clamp(color, 0.0, 1.0); - - return color; -} - -// Khronos Neutral tonemapping -// https://github.com/KhronosGroup/ToneMapping/tree/main -// Input color is non-negative and resides in the Linear Rec. 709 color space. -// Output color is also Linear Rec. 709, but in the [0, 1] range. -vec3 PBRNeutralToneMapping( vec3 color ) -{ - const float startCompression = 0.8 - 0.04; - const float desaturation = 0.15; - - float x = min(color.r, min(color.g, color.b)); - float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; - color -= offset; - - float peak = max(color.r, max(color.g, color.b)); - if (peak < startCompression) return color; - - const float d = 1. - startCompression; - float newPeak = 1. - d * d / (peak + d - startCompression); - color *= newPeak / peak; - - float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); - return mix(color, newPeak * vec3(1, 1, 1), g); -} - -uniform float exposure; -uniform float tonemap_mix; -uniform int tonemap_type; - -vec3 toneMap(vec3 color) -{ -#ifndef NO_POST - float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; - - color *= exposure * exp_scale; - - vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); - - switch(tonemap_type) - { - case 0: - color = PBRNeutralToneMapping(color); - break; - case 1: - color = toneMapACES_Hill(color); - break; - } - - // mix tonemapped and linear here to provide adjustment - color = mix(clamped_color, color, tonemap_mix); -#endif - - return color; -} - -//=============================================================== - -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 clampHDRRange(vec3 color); void main() { @@ -172,6 +47,7 @@ void main() diff.rgb = clamp(diff.rgb, vec3(0.0), vec3(1.0)); #endif + diff.rgb = clampHDRRange(diff.rgb); //debugExposure(diff.rgb); frag_color = max(diff, vec4(0)); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl new file mode 100644 index 0000000000..a63b8d7c2b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl @@ -0,0 +1,180 @@ +/** + * @file postDeferredTonemap.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$ + */ + +/*[EXTRA_CODE_HERE]*/ + +uniform sampler2D exposureMap; +uniform vec2 screen_res; +in vec2 vary_fragcoord; + +//=============================================================== +// tone mapping taken from Khronos sample implementation +//=============================================================== + +// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT +const mat3 ACESInputMat = mat3 +( + 0.59719, 0.07600, 0.02840, + 0.35458, 0.90834, 0.13383, + 0.04823, 0.01566, 0.83777 +); + + +// ODT_SAT => XYZ => D60_2_D65 => sRGB +const mat3 ACESOutputMat = mat3 +( + 1.60475, -0.10208, -0.00327, + -0.53108, 1.10813, -0.07276, + -0.07367, -0.00605, 1.07602 +); + +// ACES tone map (faster approximation) +// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ +vec3 toneMapACES_Narkowicz(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0); +} + + +// ACES filmic tone map approximation +// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl +vec3 RRTAndODTFit(vec3 color) +{ + vec3 a = color * (color + 0.0245786) - 0.000090537; + vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081; + return a / b; +} + + +// tone mapping +vec3 toneMapACES_Hill(vec3 color) +{ + color = ACESInputMat * color; + + // Apply RRT and ODT + color = RRTAndODTFit(color); + + color = ACESOutputMat * color; + + // Clamp to [0, 1] + color = clamp(color, 0.0, 1.0); + + return color; +} + +// Khronos Neutral tonemapping +// https://github.com/KhronosGroup/ToneMapping/tree/main +// Input color is non-negative and resides in the Linear Rec. 709 color space. +// Output color is also Linear Rec. 709, but in the [0, 1] range. +vec3 PBRNeutralToneMapping( vec3 color ) +{ + const float startCompression = 0.8 - 0.04; + const float desaturation = 0.15; + + float x = min(color.r, min(color.g, color.b)); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + + float peak = max(color.r, max(color.g, color.b)); + if (peak < startCompression) return color; + + const float d = 1. - startCompression; + float newPeak = 1. - d * d / (peak + d - startCompression); + color *= newPeak / peak; + + float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); + return mix(color, newPeak * vec3(1, 1, 1), g); +} + +uniform float exposure; +uniform float tonemap_mix; +uniform int tonemap_type; + +vec3 toneMap(vec3 color) +{ +#ifndef NO_POST + float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; + + color *= exposure * exp_scale; + + vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + + switch(tonemap_type) + { + case 0: + color = PBRNeutralToneMapping(color); + break; + case 1: + color = toneMapACES_Hill(color); + break; + } + + // mix tonemapped and linear here to provide adjustment + color = mix(clamped_color, color, tonemap_mix); +#endif + + return color; +} + + +vec3 toneMapNoExposure(vec3 color) +{ +#ifndef NO_POST + vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + + switch(tonemap_type) + { + case 0: + color = PBRNeutralToneMapping(color); + break; + case 1: + color = toneMapACES_Hill(color); + break; + } + + // mix tonemapped and linear here to provide adjustment + color = mix(clamped_color, color, tonemap_mix); +#endif + + return color; +} + + +//=============================================================== + +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); + } +} diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 72eda80716..bfb592be9b 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -49,7 +49,7 @@ void main() float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); #if HAS_NOISE - float TRUE_NOISE_RES = 128; // See mTrueNoiseMap + float TRUE_NOISE_RES = 128.0; // See mTrueNoiseMap // *NOTE: Usually this is vary_fragcoord not vary_texcoord0, but glow extraction is in screen space vec3 glow_noise = texture(glowNoiseMap, vary_texcoord0.xy * (screen_res / TRUE_NOISE_RES)).xyz; // Dithering. Reduces banding effects in the reduced precision glow buffer. diff --git a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl index d7f6d20547..bf8737615f 100644 --- a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl @@ -41,6 +41,26 @@ vec3 srgb_to_linear(vec3 cs) } + +vec4 srgb_to_linear4(vec4 cs) +{ + vec4 low_range = cs / vec4(12.92); + vec4 high_range = pow((cs+vec4(0.055))/vec4(1.055), vec4(2.4)); + bvec4 lte = lessThanEqual(cs,vec4(0.04045)); + +#ifdef OLD_SELECT + vec4 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + result.a = lte.a ? low_range.a : high_range.a; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + vec3 linear_to_srgb(vec3 cl) { cl = clamp(cl, vec3(0), vec3(1)); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl index 20b61e9302..44a979e565 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl @@ -66,11 +66,11 @@ vec4 getWaterFogViewNoClip(vec3 pos) float t2 = kd + ks * es; float t3 = pow(F, t2*l) - 1.0; - float L = min(t1/t2*t3, 1.0); + float L = pow(min(t1/t2*t3, 1.0), 1.0/1.7); float D = pow(0.98, l*kd); - return vec4(srgb_to_linear(kc.rgb*L), D); + return vec4(srgb_to_linear(kc.rgb)*L, D); } vec4 getWaterFogView(vec3 pos) diff --git a/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl b/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl index 09eb7a6a6a..82f32da048 100644 --- a/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl @@ -45,7 +45,7 @@ void main() for (int i = 0; i < 9; ++i) { - vec2 tc = vary_texcoord0 + (i-4)*direction*resScale; + vec2 tc = vary_texcoord0 + float(i-4)*direction*resScale; col += texture(diffuseRect, tc).rgb * w[i]; } diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl new file mode 100644 index 0000000000..30d70122cb --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl @@ -0,0 +1,46 @@ +/** + * @file simpleColorF.glsl + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +out vec4 frag_color; + +in vec4 vertex_color; +in vec4 vertex_position; + +uniform vec4 waterPlane; +uniform float waterSign; + +void waterClip(vec3 pos) +{ + if (((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) * waterSign) < 0.0) + { + discard; + } +} + +void main() +{ + + frag_color = vertex_color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl new file mode 100644 index 0000000000..4564e56313 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl @@ -0,0 +1,43 @@ +/** + * @file simpleNoAtmosV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_matrix; +uniform mat4 modelview_projection_matrix; + +uniform vec4 color; + +in vec3 position; + +out vec4 vertex_color; +out vec4 vertex_position; + +void main() +{ + //transform vertex + vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); + vertex_position = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = vertex_position; + vertex_color = color; +} diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 205d4bff6d..9101fc0222 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -99,7 +99,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) haze_glow *= glow.x; // higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = clamp(pow(haze_glow, glow.z), -100000, 100000); + haze_glow = clamp(pow(haze_glow, glow.z), -100000.0, 100000.0); // glow.z should be negative, so we're doing a sort of (1 / "angle") function // add "minimum anti-solar illumination" @@ -154,6 +154,7 @@ void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, ou if (classic_mode < 1) { amblit = srgb_to_linear(amblit); + amblit = vec3(dot(amblit, vec3(0.2126, 0.7152, 0.0722))); sunlit = srgb_to_linear(sunlit); } diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl index 1372ddbcfa..bdc5b58060 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl @@ -47,7 +47,7 @@ void calcAtmospherics(vec3 inPositionEye) { vec3 tmpaddlit = vec3(1); vec3 tmpattenlit = vec3(1); vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; - calcAtmosphericVars(inPositionEye, light_dir, 1, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit); + calcAtmosphericVars(inPositionEye, light_dir, 1.0, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit); setSunlitColor(tmpsunlit); setAmblitColor(tmpamblit); setAdditiveColor(tmpaddlit); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 3e702f26be..50b40e9c20 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -80,7 +80,7 @@ float getAmbientClamp(); void mirrorClip(vec3 pos); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance) @@ -148,9 +148,9 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec float lit = 0.0f; float amb_da = 0.0;//ambiance; - if (da > 0) + if (da > 0.0) { - lit = max(da * dist_atten,0.0); + lit = clamp(da * dist_atten, 0.0, 1.0); col = lit * light_col * diffuse; amb_da += (da*0.5+0.5) * ambiance; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl index c43582e185..2657b2b54e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl @@ -56,7 +56,7 @@ vec4 sampleReflectionProbesDebug(vec3 pos) return vec4(0, 0, 0, 0); } -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear) { ambenv = mix(ambenv, vec3(reflection_probe_ambiance * 0.25), reflection_probe_ambiance); diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl index 03dc3d7113..5e38864d38 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl @@ -48,7 +48,7 @@ vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); // reflection probe interface -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 7f871c0d5e..f8803f1a29 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -62,7 +62,7 @@ out vec4 frag_color; float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); #endif -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); @@ -138,9 +138,9 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float lit = 0.0f; float amb_da = ambiance; - if (da >= 0) + if (da >= 0.0) { - lit = max(da * dist_atten, 0.0); + lit = clamp(da * dist_atten, 0.0, 1.0); col = lit * light_col * diffuse; amb_da += (da*0.5 + 0.5) * ambiance; } @@ -159,10 +159,10 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float nv = dot(n, npos); float vh = dot(npos, h); float sa = nh; - float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5; + float fres = pow(1.0 - dot(h, npos), 5.0)*0.4 + 0.5; - float gtdenom = 2 * nh; - float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); + float gtdenom = 2.0 * nh; + float gt = max(0.0, min(gtdenom * nv / vh, gtdenom * da / vh)); if (nh > 0.0) { @@ -225,7 +225,7 @@ vec3 getNormal(inout float glossiness) #ifdef HAS_NORMAL_MAP vec4 vNt = texture(bumpMap, vary_texcoord1.xy); glossiness *= vNt.a; - vNt.xyz = vNt.xyz * 2 - 1; + vNt.xyz = vNt.xyz * 2.0 - 1.0; float sign = vary_sign; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; @@ -284,10 +284,10 @@ float getShadow(vec3 pos, vec3 norm) #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) return sampleDirectionalShadow(pos, norm, vary_texcoord0.xy); #else - return 1; + return 1.; #endif #else - return 1; + return 1.; #endif } @@ -377,9 +377,9 @@ void main() float lit = min(nl*6.0, 1.0); float sa = nh; - float fres = pow(1 - vh, 5) * 0.4+0.5; - float gtdenom = 2 * nh; - float gt = max(0,(min(gtdenom * nv / vh, gtdenom * nl / vh))); + float fres = pow(1.0 - vh, 5.0) * 0.4+0.5; + float gtdenom = 2.0 * nh; + float gt = max(0.0,(min(gtdenom * nv / vh, gtdenom * nl / vh))); float scol = shadow*fres*texture(lightFunc, vec2(nh, glossiness)).r*gt/(nh*nl); color.rgb += lit*scol*sunlit_linear.rgb*spec.rgb; @@ -396,7 +396,7 @@ void main() applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, env); float cur_glare = max(max(legacyenv.r, legacyenv.g), legacyenv.b); - cur_glare = clamp(cur_glare, 0, 1); + cur_glare = clamp(cur_glare, 0.0, 1.0); cur_glare *= env; glare += cur_glare; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl index 96cda1ef49..b11c2644aa 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl @@ -153,10 +153,10 @@ void main() if (spec.a > 0.0) { lit = min(nl * 6.0, 1.0) * dist_atten; - float fres = pow(1 - vh, 5) * 0.4 + 0.5; + float fres = pow(1.0 - vh, 5.0) * 0.4 + 0.5; - float gtdenom = 2 * nh; - float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh)); + float gtdenom = 2.0 * nh; + float gt = max(0.0, min(gtdenom * nv / vh, gtdenom * nl / vh)); if (nh > 0.0) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl index ceb37f36a5..6a248f25bc 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl @@ -134,9 +134,9 @@ void main() lit = min(nl*6.0, 1.0) * dist_atten; float sa = nh; - float fres = pow(1 - vh, 5) * 0.4+0.5; - float gtdenom = 2 * nh; - float gt = max(0,(min(gtdenom * nv / vh, gtdenom * nl / vh))); + float fres = pow(1.0 - vh, 5.0) * 0.4+0.5; + float gtdenom = 2.0 * nh; + float gt = max(0.0,(min(gtdenom * nv / vh, gtdenom * nl / vh))); if (nh > 0.0) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 5dfa196cf6..2f577f8459 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -38,6 +38,8 @@ uniform float max_probe_lod; uniform bool transparent_surface; +uniform int classic_mode; + #define MAX_REFMAP_COUNT 256 // must match LL_MAX_REFLECTION_PROBE_COUNT layout (std140) uniform ReflectionProbes @@ -739,7 +741,10 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, amblit); + ambenv = amblit; + + if (classic_mode == 0) + ambenv = sampleProbeAmbient(pos, norm, amblit); float lod = (1.0-glossiness)*reflection_lods; glossenv = sampleProbes(pos, normalize(refnormpersp), lod); @@ -784,9 +789,6 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, probeIndex[probeInfluences++] = 0; doProbeSample(ambenv, glossenv, tc, pos, norm, glossiness, false, amblit); - - // fudge factor to get PBR water at a similar luminance ot legacy water - glossenv *= 0.4; } void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) @@ -837,7 +839,7 @@ vec4 sampleReflectionProbesDebug(vec3 pos) return col; } -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit) { float reflection_lods = max_probe_lod; @@ -845,7 +847,10 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, amblit); + ambenv = amblit; + + if (classic_mode == 0) + ambenv = sampleProbeAmbient(pos, norm, amblit); if (glossiness > 0.0) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index aac75a0739..6cec65ad83 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -69,7 +69,7 @@ vec3 scaleSoftClipFragLinear(vec3 l); // reflection probe interface void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); @@ -104,6 +104,7 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 atten); GBufferInfo getGBuffer(vec2 screenpos); +vec3 clampHDRRange(vec3 color); void adjustIrradiance(inout vec3 irradiance, float ambocc) { @@ -278,6 +279,7 @@ void main() float final_scale = 1; if (classic_mode > 0) final_scale = 1.1; - frag_color.rgb = max(color.rgb * final_scale, vec3(0)); //output linear since local lights will be added to this shader's results + + frag_color.rgb = clampHDRRange(color.rgb * final_scale); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl index a46e3688dc..017f8bc844 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl @@ -199,7 +199,7 @@ void main() proj_tc.x > 0.0 && proj_tc.y > 0.0) { - float amb_da = 0; + float amb_da = 0.0; float lit = 0.0; if (nl > 0.0) @@ -222,10 +222,10 @@ void main() { dlit *= min(nl*6.0, 1.0) * dist_atten; - float fres = pow(1 - vh, 5)*0.4+0.5; + float fres = pow(1.0 - vh, 5.0)*0.4+0.5; - float gtdenom = 2 * nh; - float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh)); + float gtdenom = 2.0 * nh; + float gt = max(0.0, min(gtdenom * nv / vh, gtdenom * nl / vh)); if (nh > 0.0) { @@ -259,7 +259,7 @@ void main() stc.x > 0.0 && stc.y > 0.0) { - final_color += color.rgb * texture2DLodSpecular(stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity; + final_color += color.rgb * texture2DLodSpecular(stc.xy, (1.0 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity; } } } diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl index 2bf785e773..091c25d15e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl @@ -35,13 +35,25 @@ vec4 getWaterFogView(vec3 pos); uniform int above_water; +uniform sampler2D exclusionTex; + void main() { vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5; float depth = getDepth(tc.xy); + float mask = texture(exclusionTex, tc.xy).r; if (above_water > 0) { + // Just discard if we're in the exclusion mask. + // The previous invisiprim hack we're replacing would also crank up water fog desntiy. + // But doing that makes exclusion surfaces very slow as we'd need to render even more into the mask. + // - Geenz 2025-02-06 + if (mask < 1) + { + discard; + } + // we want to depth test when the camera is above water, but some GPUs have a hard time // with depth testing against render targets that are bound for sampling in the same shader // so we do it manually here @@ -51,11 +63,13 @@ void main() { discard; } + } vec4 pos = getPositionWithDepth(tc, depth); vec4 fogged = getWaterFogView(pos.xyz); + fogged.a = max(pow(fogged.a, 1.7), 0); frag_color = max(fogged, vec4(0)); //output linear since local lights will be added to this shader's results diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index 1c02dc764d..fa410e9f11 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -26,6 +26,7 @@ out vec4 frag_color; uniform sampler2D bumpMap; +uniform sampler2D exclusionTex; #ifdef TRANSPARENT_WATER uniform sampler2D screenTex; @@ -59,6 +60,9 @@ void mirrorClip(vec3 position); void main() { mirrorClip(vary_position); + vec2 screen_tc = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + float water_mask = texture(exclusionTex, screen_tc).r; + vec4 color; //get detail normals @@ -68,8 +72,8 @@ void main() vec3 wavef = normalize(wave1+wave2+wave3); //figure out distortion vector (ripply) - vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - distort = distort+wavef.xy*refScale; + vec2 distort = screen_tc; + distort = mix(distort, distort+wavef.xy*refScale, water_mask); #ifdef TRANSPARENT_WATER vec4 fb = texture(screenTex, distort); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 8bf4ec0a7e..b9de4edc67 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -25,6 +25,8 @@ // class3/environment/waterF.glsl +#define WATER_MINIMAL 1 + out vec4 frag_color; #ifdef HAS_SUN_SHADOW @@ -86,23 +88,17 @@ uniform sampler2D screenTex; uniform sampler2D depthMap; #endif -uniform sampler2D refTex; +uniform sampler2D exclusionTex; -uniform float sunAngle; -uniform float sunAngle2; +uniform int classic_mode; uniform vec3 lightDir; uniform vec3 specular; -uniform float lightExp; +uniform float blurMultiplier; uniform float refScale; uniform float kd; -uniform vec2 screenRes; uniform vec3 normScale; uniform float fresnelScale; uniform float fresnelOffset; -uniform float blurMultiplier; -uniform vec4 waterFogColor; -uniform vec3 waterFogColorLinear; - //bigWave is (refCoord.w, view.w); in vec4 refCoord; @@ -122,6 +118,10 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2) vec3 srgb_to_linear(vec3 col); vec3 linear_to_srgb(vec3 col); +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); +vec3 toneMapNoExposure(vec3 color); + vec3 vN, vT, vB; vec3 transform_normal(vec3 vNt) @@ -132,59 +132,109 @@ vec3 transform_normal(vec3 vNt) void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, vec3 amblit_linear); +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear); + +/* +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); +*/ + + vec3 getPositionWithNDC(vec3 ndc); +void generateWaveNormals(out vec3 wave1, out vec3 wave2, out vec3 wave3) +{ + // Generate all of our wave normals. + // We layer these back and forth. + + vec2 bigwave = vec2(refCoord.w, view.w); + + vec3 wave1_a = texture(bumpMap, bigwave).xyz * 2.0 - 1.0; + vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz * 2.0 - 1.0; + vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz * 2.0 - 1.0; + + vec3 wave1_b = texture(bumpMap2, bigwave).xyz * 2.0 - 1.0; + vec3 wave2_b = texture(bumpMap2, littleWave.xy).xyz * 2.0 - 1.0; + vec3 wave3_b = texture(bumpMap2, littleWave.zw).xyz * 2.0 - 1.0; + + wave1 = BlendNormal(wave1_a, wave1_b); + wave2 = BlendNormal(wave2_a, wave2_b); + wave3 = BlendNormal(wave3_a, wave3_b); +} + +void calculateFresnelFactors(out vec3 df3, out vec2 df2, vec3 viewVec, vec3 wave1, vec3 wave2, vec3 wave3, vec3 wavef) +{ + // We calculate the fresnel here. + // We do this by getting the dot product for each sets of waves, and applying scale and offset. + + df3 = max(vec3(0), vec3( + dot(viewVec, wave1), + dot(viewVec, (wave2 + wave3) * 0.5), + dot(viewVec, wave3) + ) * fresnelScale + fresnelOffset); + + df3 *= df3; + + df2 = max(vec2(0), vec2( + df3.x + df3.y + df3.z, + dot(viewVec, wavef) * fresnelScale + fresnelOffset + )); +} + void main() { mirrorClip(vary_position); + vN = vary_normal; vT = vary_tangent; vB = cross(vN, vT); vec3 pos = vary_position.xyz; + float linear_depth = 1.0 / -pos.z; float dist = length(pos.xyz); //normalize view vector vec3 viewVec = normalize(pos.xyz); - //get wave normals - vec2 bigwave = vec2(refCoord.w, view.w); - vec3 wave1_a = texture(bumpMap, bigwave, -2 ).xyz*2.0-1.0; - vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz*2.0-1.0; - vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz*2.0-1.0; + // Setup our waves. - vec3 wave1_b = texture(bumpMap2, bigwave ).xyz*2.0-1.0; - vec3 wave2_b = texture(bumpMap2, littleWave.xy).xyz*2.0-1.0; - vec3 wave3_b = texture(bumpMap2, littleWave.zw).xyz*2.0-1.0; + vec3 wave1 = vec3(0, 0, 1); + vec3 wave2 = vec3(0, 0, 1); + vec3 wave3 = vec3(0, 0, 1); - //wave1_a = wave2_a = wave3_a = wave1_b = wave2_b = wave3_b = vec3(0,0,1); - - vec3 wave1 = BlendNormal(wave1_a, wave1_b); - vec3 wave2 = BlendNormal(wave2_a, wave2_b); - vec3 wave3 = BlendNormal(wave3_a, wave3_b); + generateWaveNormals(wave1, wave2, wave3); + float dmod = sqrt(dist); vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - //wave1 = transform_normal(wave1); - //wave2 = transform_normal(wave2); - //wave3 = transform_normal(wave3); - vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; - vec3 waver = wavef*3; + vec3 df3 = vec3(0); + vec2 df2 = vec2(0); + + vec3 sunlit; + vec3 amblit; + vec3 additive; + vec3 atten; + calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten); + + calculateFresnelFactors(df3, df2, normalize(view.xyz), wave1, wave2, wave3, wavef); + + vec3 waver = wavef*3.0; vec3 up = transform_normal(vec3(0,0,1)); - float vdu = -dot(viewVec, up)*2; + float vdu = -dot(viewVec, up)*2.0; - vec3 wave_ibl = wavef; + vec3 wave_ibl = wavef * normScale; wave_ibl.z *= 2.0; wave_ibl = transform_normal(normalize(wave_ibl)); vec3 norm = transform_normal(normalize(wavef)); - vdu = clamp(vdu, 0, 1); - wavef.z *= max(vdu*vdu*vdu, 0.1); + vdu = clamp(vdu, 0.0, 1.0); + //wavef.z *= max(vdu*vdu*vdu, 0.1); wavef = normalize(wavef); @@ -194,62 +244,71 @@ void main() float dist2 = dist; dist = max(dist, 5.0); - float dmod = sqrt(dist); - //figure out distortion vector (ripply) - vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0); + vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0) * 2.0; distort2 = clamp(distort2, vec2(0), vec2(0.999)); - vec3 sunlit; - vec3 amblit; - vec3 additive; - vec3 atten; - float shadow = 1.0f; + float water_mask = texture(exclusionTex, distort).r; + #ifdef HAS_SUN_SHADOW shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, distort); #endif - calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = sunlit; + float fade = 1.0; +#ifdef TRANSPARENT_WATER + float depth = texture(depthMap, distort).r; - vec3 sunlit_linear = srgb_to_linear(sunlit); + vec3 refPos = getPositionWithNDC(vec3(distort*2.0-vec2(1.0), depth*2.0-1.0)); -#ifdef TRANSPARENT_WATER - vec4 fb = texture(screenTex, distort2); - float depth = texture(depthMap, distort2).r; - vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0)); + // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". +#ifdef SHORELINE_FADE + fade = max(0.0,min(1.0, (pos.z - refPos.z) / 10.0)); +#else + fade = 1.0; +#endif + fade *= water_mask; + distort2 = mix(distort, distort2, min(1.0, fade * 10.0)); + depth = texture(depthMap, distort2).r; + + refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0)); - if (refPos.z > pos.z-0.05) + if (pos.z < refPos.z - 0.05) { - //we sampled an above water sample, don't distort distort2 = distort; - fb = texture(screenTex, distort2); - depth = texture(depthMap, distort2).r; - refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0)); } + vec4 fb = texture(screenTex, distort2); + #else vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0)); -#endif - // fudge sample on other side of water to be a tad darker - fb.rgb *= 0.75; + if (water_mask < 1.0) + discard; +#endif - float metallic = 0.0; - float perceptualRoughness = 0.05; + float metallic = 1.0; + float perceptualRoughness = blurMultiplier; float gloss = 1.0 - perceptualRoughness; vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit); + vec3 legacyenv = vec3(0); - irradiance = vec3(0); + // TODO: Make this an option. +#ifdef WATER_MINIMAL + sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit); +#elif WATER_MINIMAL_PLUS + sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, false, amblit); +#endif vec3 diffuseColor = vec3(0); vec3 specularColor = vec3(0); - calcDiffuseSpecular(vec3(1), metallic, diffuseColor, specularColor); + vec3 specular_linear = srgb_to_linear(specular); + calcDiffuseSpecular(specular_linear, metallic, diffuseColor, specularColor); vec3 v = -normalize(pos.xyz); @@ -257,46 +316,36 @@ void main() float ao = 1.0; vec3 light_dir = transform_normal(lightDir); - perceptualRoughness = 0.0; - metallic = 1.0; - float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0); - float nl = 0; + float nl = 0.0; vec3 diffPunc = vec3(0); vec3 specPunc = vec3(0); - pbrPunctual(vec3(0), specularColor, 0.1, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc); - - vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)); - - vec3 color = punctual * sunlit_linear * 2.75 * shadow; - vec3 iblDiff; - vec3 iblSpec; - pbrIbl(vec3(0), vec3(1), radiance, vec3(0), ao, NdotV, 0.0, iblDiff, iblSpec); - - color += iblDiff + iblSpec; + pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc); - float nv = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0); - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0); - float f = 1.0-brdf.y; //1.0 - (brdf.x+brdf.y); - f *= 0.9; - f *= f; + vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)) * sunlit_linear * shadow * atten; + radiance *= df2.y; + //radiance = toneMapNoExposure(radiance); + vec3 color = vec3(0); + color = mix(fb.rgb, radiance, min(1.0, df2.x)) + punctual.rgb; - // incoming scale is [0, 1] with 0.5 being default - // shift to 0.5 to 1.5 - f *= (fresnelScale - 0.5)+1.0; + float water_haze_scale = 4.0; - // incoming offset is [0, 1] with 0.5 being default - // shift from -1 to 1 - f += (fresnelOffset - 0.5) * 2.0; + if (classic_mode > 0) + water_haze_scale = 1.0; - f = clamp(f, 0, 1); + // This looks super janky, but we do this to restore water haze in the distance. + // These values were finagled in to try and bring back some of the distant brightening on legacy water. Also works reasonably well on PBR skies such as PBR midday. + // color = mix(color, additive * water_haze_scale, (1 - atten)); - color = ((1.0 - f) * color) + fb.rgb; + // We shorten the fade here at the shoreline so it doesn't appear too soft from a distance. + fade *= 60.0; + fade = min(1.0, fade); + color = mix(fb.rgb, color, fade); - float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05); + float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.0); - frag_color = max(vec4(color, spec), vec4(0)); + frag_color = min(vec4(1),max(vec4(color.rgb, spec * water_mask), vec4(0))); } |