summaryrefslogtreecommitdiff
path: root/indra/newview/app_settings
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2022-05-16 17:21:08 +0000
committerDave Parks <davep@lindenlab.com>2022-05-16 17:21:08 +0000
commit3400e5fd302c0d9dea6386c4d5bf38876f2cc287 (patch)
treee791863ef5dabe1a6fb6cba59771607912362ab7 /indra/newview/app_settings
parent6c1fdac9df52ff920860066905a08db748ab0d95 (diff)
SL-17284 Reflection probe tuning and optimization take 1
Diffstat (limited to 'indra/newview/app_settings')
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl75
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl274
5 files changed, 336 insertions, 67 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 20b708fe99..284b779be3 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10269,6 +10269,17 @@
<integer>2</integer>
</map>
+ <key>RenderReflectionProbeDrawDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Camera far clip to use when updating reflection probes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>64</real>
+ </map>
<key>RenderReflectionRes</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
index 23adbded5e..73c125bbdc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
@@ -29,8 +29,6 @@ uniform sampler2DRect depthMap;
uniform float ssao_radius;
uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -83,14 +81,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
{
float ret = 1.0;
vec3 pos_world = pos.xyz;
- vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
+
float angle_hidden = 0.0;
float points = 0;
- float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
-
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+ vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
@@ -105,14 +103,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
//(k should vary inversely with # of samples, but this is taken care of later)
float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
- angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
+ angle_hidden = angle_hidden + funky_val * min(1.0/dist2, 1.0);
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
points = points + diffz_val;
}
-
- angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
+
+ angle_hidden = min(angle_hidden/points, 1.0);
float points_val = (points > 0.0) ? 1.0 : 0.0;
ret = (1.0 - (points_val * angle_hidden));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 596d0274af..fa3634f3b6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -69,36 +69,47 @@ void main()
tc_mod *= 2.0;
tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
- for (int i = 1; i < 4; i++)
+ // TODO: move this to kern instead of building kernel per pixel
+ vec3 k[7];
+ k[0] = kern[0];
+ k[2] = kern[1];
+ k[4] = kern[2];
+ k[6] = kern[3];
+
+ 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 + kern[i].z*dlt;
+ vec2 samptc = tc + k[i].z*dlt*2.0;
vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
{
- col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
+ col += texture2DRect(lightMap, samptc)*k[i].xyxx;
+ defined_weight += k[i].xy;
}
}
- for (int i = 1; i < 4; i++)
+ for (int i = 1; i < 7; i++)
{
- vec2 samptc = tc - kern[i].z*dlt;
+ vec2 samptc = tc - k[i].z*dlt*2.0;
vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
{
- col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
+ col += texture2DRect(lightMap, samptc)*k[i].xyxx;
+ defined_weight += k[i].xy;
}
}
col /= defined_weight.xyxx;
- col.y *= col.y;
+ //col.y *= max(col.y, 0.75);
frag_color = col;
diff --git a/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
new file mode 100644
index 0000000000..ea687aab4f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
@@ -0,0 +1,75 @@
+/**
+ * @file reflectionmipF.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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect screenMap;
+
+VARYING vec2 vary_texcoord0;
+
+void main()
+{
+ float w[9];
+
+ float c = 1.0/16.0; //corner weight
+ float e = 1.0/8.0; //edge weight
+ float m = 1.0/4.0; //middle weight
+
+ //float wsum = c*4+e*4+m;
+
+ w[0] = c; w[1] = e; w[2] = c;
+ w[3] = e; w[4] = m; w[5] = e;
+ w[6] = c; w[7] = e; w[8] = c;
+
+ vec2 tc[9];
+
+ float ed = 1;
+ float cd = 1;
+
+
+ tc[0] = vec2(-cd, cd); tc[1] = vec2(0, ed); tc[2] = vec2(cd, cd);
+ tc[3] = vec2(-ed, 0); tc[4] = vec2(0, 0); tc[5] = vec2(ed, 0);
+ tc[6] = vec2(-cd, -cd); tc[7] = vec2(0, -ed); tc[8] = vec2(cd, -1);
+
+ vec3 color = vec3(0,0,0);
+
+ for (int i = 0; i < 9; ++i)
+ {
+ color += texture2DRect(screenMap, vary_texcoord0.xy+tc[i]).rgb * w[i];
+ //color += texture2DRect(screenMap, vary_texcoord0.xy+tc[i]*2.0).rgb * w[i]*0.5;
+ }
+
+ //color /= wsum;
+
+ frag_color = vec4(color, 1.0);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 5bb64e18a7..3a1287e910 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -26,9 +26,10 @@
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_shader_texture_lod : enable
-/*[EXTRA_CODE_HERE]*/
+#define FLT_MAX 3.402823466e+38
-#define REFMAP_COUNT 8
+#define REFMAP_COUNT 256
+#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
@@ -42,12 +43,26 @@ uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
uniform sampler2DRect depthMap;
uniform samplerCube environmentMap;
-uniform samplerCube reflectionMap[REFMAP_COUNT];
+uniform samplerCubeArray reflectionProbes;
uniform sampler2D lightFunc;
-uniform int refmapCount;
-
-uniform vec3 refOrigin[REFMAP_COUNT];
+layout (std140, binding = 1) uniform ReflectionProbes
+{
+ // list of sphere based reflection probes sorted by distance to camera (closest first)
+ vec4 refSphere[REFMAP_COUNT];
+ // index of cube map in reflectionProbes for a corresponding reflection probe
+ // e.g. cube map channel of refSphere[2] is stored in refIndex[2]
+ // refIndex.x - cubemap channel in reflectionProbes
+ // refIndex.y - index in refNeighbor of neighbor list (index is ivec4 index, not int index)
+ // refIndex.z - number of neighbors
+ ivec4 refIndex[REFMAP_COUNT];
+
+ // neighbor list data (refSphere indices, not cubemap array layer)
+ ivec4 refNeighbor[1024];
+
+ // number of reflection probes present in refSphere
+ int refmapCount;
+};
uniform float blur_size;
uniform float blur_fidelity;
@@ -80,7 +95,116 @@ vec3 srgb_to_linear(vec3 c);
vec4 applyWaterFogView(vec3 pos, vec4 color);
#endif
+// list of probeIndexes shader will actually use after "getRefIndex" is called
+// (stores refIndex/refSphere indices, NOT rerflectionProbes layer)
+int probeIndex[REF_SAMPLE_COUNT];
+
+// number of probes stored in probeIndex
+int probeInfluences = 0;
+
+
+// return true if probe at index i influences position pos
+bool shouldSampleProbe(int i, vec3 pos)
+{
+ vec3 delta = pos.xyz - refSphere[i].xyz;
+ float d = dot(delta, delta);
+ float r2 = refSphere[i].w;
+ r2 *= r2;
+ return d < r2;
+}
+
+// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT
+// overall algorithm --
+void getRefIndex(vec3 pos)
+{
+ // TODO: make some sort of structure that reduces the number of distance checks
+ for (int i = 0; i < refmapCount; ++i)
+ {
+ // found an influencing probe
+ if (shouldSampleProbe(i, pos))
+ {
+ probeIndex[probeInfluences] = i;
+ ++probeInfluences;
+
+ int neighborIdx = refIndex[i].y;
+ if (neighborIdx != -1)
+ {
+ int neighborCount = min(refIndex[i].z, REF_SAMPLE_COUNT-1);
+
+ int count = 0;
+ while (count < neighborCount)
+ {
+ // check up to REF_SAMPLE_COUNT-1 neighbors (neighborIdx is ivec4 index)
+
+ int idx = refNeighbor[neighborIdx].x;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ idx = refNeighbor[neighborIdx].y;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ idx = refNeighbor[neighborIdx].z;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ idx = refNeighbor[neighborIdx].w;
+ if (shouldSampleProbe(idx, pos))
+ {
+ probeIndex[probeInfluences++] = idx;
+ if (probeInfluences == REF_SAMPLE_COUNT)
+ {
+ return;
+ }
+ }
+ count++;
+ if (count == neighborCount)
+ {
+ return;
+ }
+
+ ++neighborIdx;
+ }
+
+ return;
+ }
+ }
+ }
+}
// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection
@@ -120,13 +244,10 @@ bool intersect(const Ray &ray) const
} */
// adapted -- assume that origin is inside sphere, return distance from origin to edge of sphere
-float sphereIntersect(vec3 origin, vec3 dir, vec4 sph )
+float sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2)
{
float t0, t1; // solutions for t if the ray intersects
- vec3 center = sph.xyz;
- float radius2 = sph.w * sph.w;
-
vec3 L = center - origin;
float tca = dot(L,dir);
@@ -139,33 +260,78 @@ float sphereIntersect(vec3 origin, vec3 dir, vec4 sph )
return t1;
}
+// Tap a sphere based reflection probe
+// pos - position of pixel
+// dir - pixel normal
+// lod - which mip to bias towards (lower is higher res, sharper reflections)
+// c - center of probe
+// r2 - radius of probe squared
+// i - index of probe
+// vi - point at which reflection vector struck the influence volume, in clip space
+vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i, out vec3 vi)
+{
+ //lod = max(lod, 1);
+// parallax adjustment
+ float d = sphereIntersect(pos, dir, c, r2);
+
+ {
+ vec3 v = pos + dir * d;
+ vi = v;
+ v -= c.xyz;
+ v = env_mat * v;
+
+ float min_lod = textureQueryLod(reflectionProbes,v).y; // lower is higher res
+ return textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), max(min_lod, lod)).rgb;
+ //return texture(reflectionProbes, vec4(v.xyz, refIndex[i].x)).rgb;
+ }
+}
+
vec3 sampleRefMap(vec3 pos, vec3 dir, float lod)
{
float wsum = 0.0;
-
vec3 col = vec3(0,0,0);
+ float vd2 = dot(pos,pos); // view distance squared
- for (int i = 0; i < refmapCount; ++i)
- //int i = 0;
+ for (int idx = 0; idx < probeInfluences; ++idx)
{
- float r = 16.0;
- vec3 delta = pos.xyz-refOrigin[i].xyz;
- if (length(delta) < r)
+ int i = probeIndex[idx];
+ float r = refSphere[i].w; // radius of sphere volume
+ float rr = r*r; // radius squred
+ float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down)
+ vec3 delta = pos.xyz-refSphere[i].xyz;
+ float d2 = dot(delta,delta);
+ float r2 = r1*r1;
+
{
- float w = 1.0/max(dot(delta, delta), r);
- w *= w;
- w *= w;
+ vec3 vi;
+ vec3 refcol = tapRefMap(pos, dir, lod, refSphere[i].xyz, rr, i, vi);
+
+ float w = 1.0/d2;
- // parallax adjustment
- float d = sphereIntersect(pos, dir, vec4(refOrigin[i].xyz, r));
+ float atten = 1.0-max(d2-r2, 0.0)/(rr-r2);
+ w *= atten;
- {
- vec3 v = pos + dir * d;
- v -= refOrigin[i].xyz;
- v = env_mat * v;
+ col += refcol*w;
+
+ wsum += w;
+ }
+ }
- float min_lod = textureQueryLod(reflectionMap[i],v).y; // lower is higher res
- col += textureLod(reflectionMap[i], v, max(min_lod, lod)).rgb*w;
+ if (probeInfluences <= 1)
+ { //edge-of-scene probe or no probe influence, mix in with embiggened version of probes closest to camera
+ for (int idx = 0; idx < 8; ++idx)
+ {
+ int i = idx;
+ vec3 delta = pos.xyz-refSphere[i].xyz;
+ float d2 = dot(delta,delta);
+
+ {
+ vec3 vi;
+ vec3 refcol = tapRefMap(pos, dir, lod, refSphere[i].xyz, d2, i, vi);
+
+ float w = 1.0/d2;
+ w *= w;
+ col += refcol*w;
wsum += w;
}
}
@@ -175,13 +341,6 @@ vec3 sampleRefMap(vec3 pos, vec3 dir, float lod)
{
col *= 1.0/wsum;
}
- else
- {
- // this pixel not covered by a probe, fallback to "full scene" environment map
- vec3 v = env_mat * dir;
- float min_lod = textureQueryLod(environmentMap, v).y; // lower is higher res
- col = textureLod(environmentMap, v, max(min_lod, lod)).rgb;
- }
return col;
}
@@ -202,13 +361,26 @@ vec3 sampleAmbient(vec3 pos, vec3 dir, float lod)
col *= 0.333333;
- return col*0.6; // fudge darker
+ return col*0.8; // fudge darker
}
+// brighten a color so that at least one component is 1
+vec3 brighten(vec3 c)
+{
+ float m = max(max(c.r, c.g), c.b);
+
+ if (m == 0)
+ {
+ return vec3(1,1,1);
+ }
+
+ return c * 1.0/m;
+}
+
void main()
{
- float reflection_lods = 11; // TODO -- base this on resolution of reflection map instead of hard coding
+ float reflection_lods = 8; // TODO -- base this on resolution of reflection map instead of hard coding
vec2 tc = vary_fragcoord.xy;
float depth = texture2DRect(depthMap, tc.xy).r;
@@ -238,14 +410,16 @@ void main()
vec3 amblit;
vec3 additive;
vec3 atten;
+
+ getRefIndex(pos.xyz);
+
calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
//vec3 amb_vec = env_mat * norm.xyz;
- vec3 ambenv = sampleAmbient(pos.xyz, norm.xyz, reflection_lods-1);
- amblit = mix(ambenv, amblit, amblit);
- color.rgb = amblit;
-
+ vec3 ambenv = sampleAmbient(pos.xyz, norm.xyz, reflection_lods);
+ amblit = max(ambenv, amblit);
+ color.rgb = amblit*ambocc;
//float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
//ambient *= 0.5;
@@ -255,6 +429,7 @@ void main()
vec3 sun_contrib = min(da, scol) * sunlit;
color.rgb += sun_contrib;
+ color.rgb = min(color.rgb, vec3(1,1,1));
color.rgb *= diffuse.rgb;
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
@@ -274,26 +449,23 @@ void main()
float lod = (1.0-spec.a)*reflection_lods;
vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), lod);
- reflected_color *= 0.5; // fudge darker, not sure where there's a multiply by two and it's late
+ reflected_color *= 0.35; // fudge darker
float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz);
- fresnel += spec.a;
- fresnel *= fresnel;
- //fresnel *= spec.a;
+ float minf = spec.a * 0.1;
+ fresnel = fresnel * (1.0-minf) + minf;
reflected_color *= spec.rgb*min(fresnel, 1.0);
- //reflected_color = srgb_to_linear(reflected_color);
- vec3 mixer = clamp(color.rgb + vec3(1,1,1) - spec.rgb, vec3(0,0,0), vec3(1,1,1));
- color.rgb = mix(reflected_color, color, mixer);
+ color.rgb += reflected_color;
}
color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
if (envIntensity > 0.0)
{ // add environmentmap
- vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), 0.0);
+ vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), 0.0)*0.5; //fudge darker
float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz);
fresnel *= fresnel;
- fresnel = fresnel * 0.95 + 0.05;
- reflected_color *= fresnel;
+ fresnel = min(fresnel+envIntensity, 1.0);
+ reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb);
color = mix(color.rgb, reflected_color, envIntensity);
}
@@ -311,5 +483,7 @@ void main()
// convert to linear as fullscreen lights need to sum in linear colorspace
// and will be gamma (re)corrected downstream...
+ //color = vec3(ambocc);
+ //color = ambenv;
frag_color.rgb = srgb_to_linear(color.rgb);
}