diff options
Diffstat (limited to 'indra/newview/app_settings/shaders/class3/deferred')
4 files changed, 293 insertions, 192 deletions
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 8d2a65d4a9..add1cb2a37 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -92,7 +92,7 @@ uniform vec3 light_diffuse[8]; float getAmbientClamp(); void waterClip(vec3 pos); -vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance) +vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance) { // SL-14895 inverted attenuation work-around // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct @@ -170,6 +170,11 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe vec3 speccol = lit*scol*light_col.rgb*spec.rgb; speccol = clamp(speccol, vec3(0), vec3(1)); col += speccol; + + float cur_glare = max(speccol.r, speccol.g); + cur_glare = max(cur_glare, speccol.b); + glare = max(glare, speccol.r); + glare += max(cur_glare, 0.0); } } } @@ -218,83 +223,105 @@ VARYING vec2 vary_texcoord0; vec2 encode_normal(vec3 n); -void main() +// get the transformed normal and apply glossiness component from normal map +vec3 getNormal(inout float glossiness) { -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) - waterClip(vary_position.xyz); -#endif +#ifdef HAS_NORMAL_MAP + vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); + glossiness *= norm.a; - vec2 pos_screen = vary_texcoord0.xy; + norm.xyz = norm.xyz * 2 - 1; - vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); - diffcol.rgb *= vertex_color.rgb; + return normalize(vec3(dot(norm.xyz,vary_mat0), + dot(norm.xyz,vary_mat1), + dot(norm.xyz,vary_mat2))); +#else + return normalize(vary_normal); +#endif +} -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) +vec4 getSpecular() +{ +#ifdef HAS_SPECULAR_MAP + vec4 spec = texture2D(specularMap, vary_texcoord2.xy); + spec.rgb *= specular_color.rgb; +#else + vec4 spec = vec4(specular_color.rgb, 1.0); +#endif + return spec; +} +void alphaMask(float alpha) +{ +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points float bias = 0.001953125; // 1/512, or half an 8-bit quantization - if (diffcol.a < minimum_alpha-bias) + if (alpha < minimum_alpha-bias) { discard; } #endif +} -#ifdef HAS_SPECULAR_MAP - vec4 spec = texture2D(specularMap, vary_texcoord2.xy); - spec.rgb *= specular_color.rgb; -#else - vec4 spec = vec4(specular_color.rgb, 1.0); +void waterClip() +{ +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + waterClip(vary_position.xyz); #endif +} -#ifdef HAS_NORMAL_MAP - vec4 norm = texture2D(bumpMap, vary_texcoord1.xy); - - norm.xyz = norm.xyz * 2 - 1; +float getEmissive(vec4 diffcol) +{ +#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE) + return emissive_brightness; +#else + return max(diffcol.a, emissive_brightness); +#endif +} - vec3 tnorm = vec3(dot(norm.xyz,vary_mat0), - dot(norm.xyz,vary_mat1), - dot(norm.xyz,vary_mat2)); +float getShadow(vec3 pos, vec3 norm) +{ +#ifdef HAS_SUN_SHADOW + #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) + return sampleDirectionalShadow(pos, norm, vary_texcoord0.xy); + #else + return 1; + #endif #else - vec4 norm = vec4(0,0,0,1.0); - vec3 tnorm = vary_normal; + return 1; #endif +} - norm.xyz = normalize(tnorm.xyz); +void main() +{ + waterClip(); - vec2 abnormal = encode_normal(norm.xyz); + // diffcol == diffuse map combined with vertex color + vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); + diffcol.rgb *= vertex_color.rgb; - vec4 final_color = diffcol; + alphaMask(diffcol.a); -#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE) - final_color.a = emissive_brightness; -#else - final_color.a = max(final_color.a, emissive_brightness); -#endif + // spec == specular map combined with specular color + vec4 spec = getSpecular(); + float env = env_intensity * spec.a; + float glossiness = specular_color.a; + vec3 norm = getNormal(glossiness); - vec4 final_specular = spec; - -#ifdef HAS_SPECULAR_MAP - vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, GBUFFER_FLAG_HAS_ATMOS); - final_specular.a = specular_color.a * norm.a; -#else - vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, GBUFFER_FLAG_HAS_ATMOS); - final_specular.a = specular_color.a; -#endif + vec2 abnormal = encode_normal(norm.xyz); + + float emissive = getEmissive(diffcol); #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) //forward rendering, output lit linear color diffcol.rgb = srgb_to_linear(diffcol.rgb); - final_specular.rgb = srgb_to_linear(final_specular.rgb); + spec.rgb = srgb_to_linear(spec.rgb); vec3 pos = vary_position; - float shadow = 1.0f; + float shadow = getShadow(pos, norm); -#ifdef HAS_SUN_SHADOW - shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen); -#endif - - vec4 diffuse = final_color; + vec4 diffuse = diffcol; vec3 color = vec3(0,0,0); @@ -307,54 +334,63 @@ void main() vec3 atten; calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + vec3 amblit_linear = amblit; + vec3 ambenv; vec3 glossenv; vec3 legacyenv; - sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos_screen, pos.xyz, norm.xyz, final_specular.a, env_intensity); + sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xy*0.5+0.5, pos.xyz, norm.xyz, glossiness, env); // use sky settings ambient or irradiance map sample, whichever is brighter - color = max(amblit, ambenv); + color = max(amblit_linear, ambenv); float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); - vec3 sun_contrib = min(da, shadow) * sunlit; + vec3 sun_contrib = min(da, shadow) * sunlit_linear; color.rgb += sun_contrib; color *= diffcol.rgb; vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - if (final_specular.a > 0.0) // specular reflection + float glare = 0.0; + + if (glossiness > 0.0) // specular reflection { float sa = dot(normalize(refnormpersp), light_dir.xyz); - vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, final_specular.a)).r); + vec3 dumbshiny = sunlit_linear * shadow * (texture2D(lightFunc, vec2(sa, glossiness)).r); // add the two types of shiny together - vec3 spec_contrib = dumbshiny * final_specular.rgb; + vec3 spec_contrib = dumbshiny * spec.rgb; bloom = dot(spec_contrib, spec_contrib) / 6; + glare = max(spec_contrib.r, spec_contrib.g); + glare = max(glare, spec_contrib.b); + color += spec_contrib; - applyGlossEnv(color, glossenv, final_specular, pos.xyz, norm.xyz); + applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); } - color = mix(color.rgb, diffcol.rgb, diffuse.a); + color = mix(color.rgb, diffcol.rgb, emissive); - if (env_intensity > 0.0) + if (env > 0.0) { // add environmentmap - applyLegacyEnv(color, legacyenv, final_specular, pos.xyz, norm.xyz, env_intensity); + applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, env); + + float cur_glare = max(max(legacyenv.r, legacyenv.g), legacyenv.b); + cur_glare *= env*4.0; + glare += cur_glare; } - color.rgb = mix(atmosFragLightingLinear(color.rgb, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), diffuse.a); + color.rgb = linear_to_srgb(color.rgb); + color.rgb = atmosFragLightingLinear(color.rgb, additive, atten); color.rgb = scaleSoftClipFragLinear(color.rgb); - -#ifdef WATER_FOG - vec4 temp = applyWaterFogView(pos, vec4(color, 0.0)); - color = temp.rgb; -#endif + color.rgb = srgb_to_linear(color.rgb); vec3 npos = normalize(-pos.xyz); vec3 light = vec3(0, 0, 0); -#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w ); +#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, spec, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w ); LIGHT_LOOP(1) LIGHT_LOOP(2) @@ -364,17 +400,25 @@ void main() LIGHT_LOOP(6) LIGHT_LOOP(7) + light *= 1.0-emissive; color += light; - float al = diffcol.a*vertex_color.a; + glare *= 1.0-emissive; + glare = min(glare, 1.0); + float al = max(diffcol.a, glare) * vertex_color.a; + +#ifdef WATER_FOG + vec4 temp = applyWaterFogView(pos, vec4(color, 0.0)); + color = temp.rgb; +#endif frag_color = vec4(color, al); -#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer +#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl - frag_data[0] = final_color; // gbuffer is sRGB for legacy materials - frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent. - frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) + frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials + frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. + frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) #endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl index d9cbae45a6..8229ecbbb7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl @@ -37,7 +37,6 @@ uniform sampler2D diffuseRect; uniform sampler2D specularRect; uniform sampler2D normalMap; uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl -uniform sampler2D noiseMap; uniform sampler2D lightFunc; uniform sampler2D depthMap; @@ -126,8 +125,7 @@ void main() diffuse = srgb_to_linear(diffuse); spec.rgb = srgb_to_linear(spec.rgb); - float noise = texture2D(noiseMap, tc).b; - float lit = nl * dist_atten * noise; + float lit = nl * dist_atten; final_color = color.rgb*lit*diffuse; diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 8b1d41776f..a6a2543915 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -80,7 +80,7 @@ bool isAbove(vec3 pos, vec4 plane) return (dot(plane.xyz, pos) + plane.w) > 0; } -int max_priority = 0; +bool sample_automatic = true; // return true if probe at index i influences position pos bool shouldSampleProbe(int i, vec3 pos) @@ -95,24 +95,24 @@ bool shouldSampleProbe(int i, vec3 pos) return false; } - max_priority = max(max_priority, -refIndex[i].w); + sample_automatic = false; } else { - if (refSphere[i].w > 0.0) // zero is special indicator to always sample this probe + if (refIndex[i].w == 0 && !sample_automatic) { - vec3 delta = pos.xyz - refSphere[i].xyz; - float d = dot(delta, delta); - float r2 = refSphere[i].w; - r2 *= r2; - - if (d > r2) - { //outside bounding sphere - return false; - } + return false; } - max_priority = max(max_priority, refIndex[i].w); + vec3 delta = pos.xyz - refSphere[i].xyz; + float d = dot(delta, delta); + float r2 = refSphere[i].w; + r2 *= r2; + + if (d > r2) + { // outside bounding sphere + return false; + } } return true; @@ -120,7 +120,6 @@ bool shouldSampleProbe(int i, vec3 pos) // call before sampleRef // populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT -// overall algorithm -- void preProbeSample(vec3 pos) { // TODO: make some sort of structure that reduces the number of distance checks @@ -210,7 +209,7 @@ void preProbeSample(vec3 pos) } } - if (max_priority <= 1) + if (sample_automatic) { // probe at index 0 is a special probe for smoothing out automatic probes probeIndex[probeInfluences++] = 0; } @@ -342,7 +341,7 @@ return texCUBE(envMap, ReflDirectionWS); // d - distance to nearest wall in clip space vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d) { - // Intersection with OBB convertto unit box space + // Intersection with OBB convert to unit box space // Transform in local unit parallax cube space (scaled and rotated) mat4 clipToLocal = refBox[i]; @@ -431,18 +430,24 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col) // origin - center of sphere probe // r - radius of probe influence volume // min_da - minimum angular attenuation coefficient -float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da) +// i - index of probe in refSphere +// dw - distance weight +float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da, int i, out float dw) { float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) vec3 delta = pos.xyz - origin; float d2 = max(length(delta), 0.001); + float r2 = r1; //r1 * r1; //float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001); float atten = 1.0 - max(d2 - r2, 0.0) / max((r - r2), 0.001); + float w = 1.0 / d2; + + dw = w * atten * max(r, 1.0)*4; atten *= max(dot(normalize(-delta), dir), min_da); - float w = 1.0 / d2; + w *= atten; return w; @@ -451,48 +456,43 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da) // Tap a reflection probe // pos - position of pixel // dir - pixel normal -// vi - return value of intersection point with influence volume -// wi - return value of approximate world space position of sampled pixel -// lod - which mip to bias towards (lower is higher res, sharper reflections) +// w - weight of sample (distance and angular attenuation) +// dw - weight of sample (distance only) +// lod - which mip to sample (lower is higher res, sharper reflections) // c - center of probe // r2 - radius of probe squared // i - index of probe -vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float lod, vec3 c, int i) +vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, int i) { - //lod = max(lod, 1); // parallax adjustment - vec3 v; if (refIndex[i].w < 0) - { + { // box probe float d = 0; v = boxIntersect(pos, dir, i, d); w = max(d, 0.001); } else - { - float r = refSphere[i].w; // radius of sphere volume - float rr = r * r; // radius squared + { // sphere probe + float r = refSphere[i].w; + + float rr = r * r; v = sphereIntersect(pos, dir, c, - refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres + refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres rr); - w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25); + w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25, i, dw); } - vi = v; - v -= c; vec3 d = normalize(v); v = env_mat * v; - vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod); - - wi = d * ret.a * 256.0+c; + vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y; return ret.rgb; } @@ -500,10 +500,10 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float // Tap an irradiance map // pos - position of pixel // dir - pixel normal -// c - center of probe -// r2 - radius of probe squared +// w - weight of sample (distance and angular attenuation) +// dw - weight of sample (distance only) // i - index of probe -vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i) +vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int i) { // parallax adjustment vec3 v; @@ -516,14 +516,15 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i) else { float r = refSphere[i].w; // radius of sphere volume - float p = float(abs(refIndex[i].w)); // priority - float rr = r * r; // radius squred + + // pad sphere for manual probe extending into automatic probe space + float rr = r * r; v = sphereIntersect(pos, dir, c, - refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres + refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres rr); - w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001); + w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001, i, dw); } v -= c; @@ -533,106 +534,129 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i) } } -vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect) +vec3 sampleProbes(vec3 pos, vec3 dir, float lod) { - float wsum = 0.0; - vec3 col = vec3(0,0,0); - float vd2 = dot(pos,pos); // view distance squared + float wsum[2]; + wsum[0] = 0; + wsum[1] = 0; + + float dwsum[2]; + dwsum[0] = 0; + dwsum[1] = 0; + + vec3 col[2]; + col[0] = vec3(0); + col[1] = vec3(0); for (int idx = 0; idx < probeInfluences; ++idx) { int i = probeIndex[idx]; - if (abs(refIndex[i].w) < max_priority) + int p = clamp(abs(refIndex[i].w), 0, 1); + + if (p == 0 && !sample_automatic) { continue; } - float w; - vec3 vi, wi; + float w = 0; + float dw = 0; vec3 refcol; { - if (errorCorrect && refIndex[i].w >= 0) - { // error correction is on and this probe is a sphere - //take a sample to get depth value, then error correct - refcol = tapRefMap(pos, dir, w, vi, wi, abs(lod + 2), refSphere[i].xyz, i); - - //adjust lookup by distance result - float d = length(vi - wi); - vi += dir * d; - - vi -= refSphere[i].xyz; + refcol = tapRefMap(pos, dir, w, dw, lod, refSphere[i].xyz, i); - vi = env_mat * vi; - - refcol = textureLod(reflectionProbes, vec4(vi, refIndex[i].x), lod).rgb; - - // weight by vector correctness - vec3 pi = normalize(wi - pos); - w *= max(dot(pi, dir), 0.1); - //w = pow(w, 32.0); - } - else - { - refcol = tapRefMap(pos, dir, w, vi, wi, lod, refSphere[i].xyz, i); - } - - col += refcol.rgb*w; - - wsum += w; + col[p] += refcol.rgb*w; + wsum[p] += w; + dwsum[p] += dw; } } - if (wsum > 0.0) + // mix automatic and manual probes + if (sample_automatic && wsum[0] > 0.0) + { // some automatic probes were sampled + col[0] *= 1.0/wsum[0]; + if (wsum[1] > 0.0) + { //some manual probes were sampled, mix between the two + col[1] *= 1.0/wsum[1]; + col[1] = mix(col[0], col[1], min(dwsum[1], 1.0)); + col[0] = vec3(0); + } + } + else if (wsum[1] > 0.0) { - col *= 1.0/wsum; + // manual probes were sampled but no automatic probes were + col[1] *= 1.0/wsum[1]; + col[0] = vec3(0); } - return col; + return col[1]+col[0]; } vec3 sampleProbeAmbient(vec3 pos, vec3 dir) { // modified copy/paste of sampleProbes follows, will likely diverge from sampleProbes further // as irradiance map mixing is tuned independently of radiance map mixing - float wsum = 0.0; - vec3 col = vec3(0,0,0); - float vd2 = dot(pos,pos); // view distance squared + float wsum[2]; + wsum[0] = 0; + wsum[1] = 0; + + float dwsum[2]; + dwsum[0] = 0; + dwsum[1] = 0; - float minweight = 1.0; + vec3 col[2]; + col[0] = vec3(0); + col[1] = vec3(0); for (int idx = 0; idx < probeInfluences; ++idx) { int i = probeIndex[idx]; - if (abs(refIndex[i].w) < max_priority) + int p = clamp(abs(refIndex[i].w), 0, 1); + + if (p == 0 && !sample_automatic) { continue; } { - float w; - vec3 refcol = tapIrradianceMap(pos, dir, w, refSphere[i].xyz, i); + float w = 0; + float dw = 0; + + vec3 refcol = tapIrradianceMap(pos, dir, w, dw, refSphere[i].xyz, i); - col += refcol*w; - - wsum += w; + col[p] += refcol*w; + wsum[p] += w; + dwsum[p] += dw; } } - if (wsum > 0.0) + // mix automatic and manual probes + if (sample_automatic && wsum[0] > 0.0) + { // some automatic probes were sampled + col[0] *= 1.0/wsum[0]; + if (wsum[1] > 0.0) + { //some manual probes were sampled, mix between the two + col[1] *= 1.0/wsum[1]; + col[1] = mix(col[0], col[1], min(dwsum[1], 1.0)); + col[0] = vec3(0); + } + } + else if (wsum[1] > 0.0) { - col *= 1.0/wsum; + // manual probes were sampled but no automatic probes were + col[1] *= 1.0/wsum[1]; + col[0] = vec3(0); } - - return col; + + return col[1]+col[0]; } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect) + vec2 tc, vec3 pos, vec3 norm, float glossiness) { // TODO - don't hard code lods - float reflection_lods = max_probe_lod; + float reflection_lods = max_probe_lod-1; preProbeSample(pos); vec3 refnormpersp = reflect(pos.xyz, norm.xyz); @@ -640,13 +664,12 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, ambenv = sampleProbeAmbient(pos, norm); float lod = (1.0-glossiness)*reflection_lods; - glossenv = sampleProbes(pos, normalize(refnormpersp), lod, errorCorrect); + glossenv = sampleProbes(pos, normalize(refnormpersp), lod); #if defined(SSR) if (cube_snapshot != 1 && glossiness >= 0.9) { vec4 ssr = vec4(0); - //float w = tapScreenSpaceReflection(errorCorrect ? 1 : 4, tc, pos, norm, ssr, sceneMap); float w = tapScreenSpaceReflection(1, tc, pos, norm, ssr, sceneMap); glossenv = mix(glossenv, ssr.rgb, w); @@ -654,11 +677,20 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, #endif } +void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness) +{ + sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness); + + // fudge factor to get PBR water at a similar luminance ot legacy water + glossenv *= 0.25; +} + void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) { vec3 origin = vec3(0,0,0); - bool manual_probe = abs(refIndex[i].w) > 2; + bool manual_probe = abs(refIndex[i].w) > 0; if (manual_probe) { @@ -694,18 +726,9 @@ vec4 sampleReflectionProbesDebug(vec3 pos) return col; } -void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, - vec2 tc, vec3 pos, vec3 norm, float glossiness) -{ - sampleReflectionProbes(ambenv, glossenv, - tc, pos, norm, glossiness, false); -} - - void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity) { - // TODO - don't hard code lods float reflection_lods = max_probe_lod; preProbeSample(pos); @@ -716,12 +739,12 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout if (glossiness > 0.0) { float lod = (1.0-glossiness)*reflection_lods; - glossenv = sampleProbes(pos, normalize(refnormpersp), lod, false); + glossenv = sampleProbes(pos, normalize(refnormpersp), lod); } if (envIntensity > 0.0) { - legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, false); + legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0); } #if defined(SSR) diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 8d48e6f596..dfd1d47b3e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -85,6 +85,8 @@ float getDepth(vec2 pos_screen); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); +uniform vec4 waterPlane; + #ifdef WATER_FOG vec4 applyWaterFogViewLinear(vec3 pos, vec4 color); #endif @@ -153,6 +155,24 @@ void main() calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten); + vec3 sunlit_linear = srgb_to_linear(sunlit); + vec3 amblit_linear = amblit; + + bool do_atmospherics = false; + +#ifndef WATER_FOG + // when above water, mask off atmospherics below water + if (dot(pos.xyz, waterPlane.xyz) + waterPlane.w > 0.0) + { + do_atmospherics = true; + } +#else + do_atmospherics = true; +#endif + + vec3 irradiance = vec3(0); + vec3 radiance = vec3(0); + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { vec3 orm = texture2D(specularRect, tc).rgb; @@ -161,23 +181,32 @@ void main() float ao = orm.r * ambocc; vec3 colorEmissive = texture2D(emissiveRect, tc).rgb; - // PBR IBL float gloss = 1.0 - perceptualRoughness; - vec3 irradiance = vec3(0); - vec3 radiance = vec3(0); + sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss); // Take maximium of legacy ambient vs irradiance sample as irradiance // NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here - irradiance = max(amblit,irradiance); + irradiance = max(amblit_linear,irradiance); vec3 diffuseColor; vec3 specularColor; calcDiffuseSpecular(baseColor.rgb, metallic, diffuseColor, specularColor); vec3 v = -normalize(pos.xyz); - color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + color = vec3(1,0,1); + color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + + + if (do_atmospherics) + { + color = linear_to_srgb(color); + color = atmosFragLightingLinear(color, additive, atten); + color = srgb_to_linear(color); + } + + } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -199,12 +228,12 @@ void main() sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity); // use sky settings ambient or irradiance map sample, whichever is brighter - irradiance = max(amblit, irradiance); + irradiance = max(amblit_linear, irradiance); // apply lambertian IBL only (see pbrIbl) color.rgb = irradiance * ambocc; - vec3 sun_contrib = min(da, scol) * sunlit; + vec3 sun_contrib = min(da, scol) * sunlit_linear; color.rgb += sun_contrib; color.rgb *= baseColor.rgb; @@ -230,9 +259,16 @@ void main() applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity); } - color = mix(atmosFragLightingLinear(color, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), baseColor.a); - color = scaleSoftClipFragLinear(color); - } + + if (do_atmospherics) + { + color = linear_to_srgb(color); + color = atmosFragLightingLinear(color, additive, atten); + color = srgb_to_linear(color); + } + } + + #ifdef WATER_FOG vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); |