diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 843789ae1..fbb456eed 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1177,6 +1177,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("depth_cutoff");
mReservedUniforms.push_back("norm_cutoff");
mReservedUniforms.push_back("shadow_target_width");
+ mReservedUniforms.push_back("downsampled_depth_scale");
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1);
@@ -1195,6 +1196,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("dof_height");
mReservedUniforms.push_back("depthMap");
+ mReservedUniforms.push_back("depthMapDownsampled");
mReservedUniforms.push_back("shadowMap0");
mReservedUniforms.push_back("shadowMap1");
mReservedUniforms.push_back("shadowMap2");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index c13485b71..7dccf47b1 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -136,6 +136,7 @@ public:
DEFERRED_DEPTH_CUTOFF,
DEFERRED_NORM_CUTOFF,
DEFERRED_SHADOW_TARGET_WIDTH,
+ DEFERRED_DOWNSAMPLED_DEPTH_SCALE,
FXAA_TC_SCALE,
FXAA_RCP_SCREEN_RES,
@@ -152,6 +153,7 @@ public:
DOF_HEIGHT,
DEFERRED_DEPTH,
+ DEFERRED_DOWNSAMPLED_DEPTH,
DEFERRED_SHADOW0,
DEFERRED_SHADOW1,
DEFERRED_SHADOW2,
diff --git a/indra/newview/app_settings/settings_sh.xml b/indra/newview/app_settings/settings_sh.xml
index 998c3ff37..5fb2c4826 100644
--- a/indra/newview/app_settings/settings_sh.xml
+++ b/indra/newview/app_settings/settings_sh.xml
@@ -229,5 +229,16 @@
Value
1
+ SHRenderSSAOResolutionScale
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl
new file mode 100644
index 000000000..64c4e41cf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl
@@ -0,0 +1,140 @@
+/**
+ * @file sunLightF.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$
+ */
+
+//#extension GL_ARB_texture_rectangle : enable
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+VARYING vec2 vary_fragcoord;
+
+uniform sampler2DRect depthMapDownsampled;
+uniform sampler2DRect normalMap;
+uniform sampler2D noiseMap;
+
+uniform vec2 screen_res;
+uniform mat4 inv_proj;
+
+uniform float downsampled_depth_scale;
+
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+
+vec3 decode_normal (vec2 enc)
+{
+ vec2 fenc = enc*4-2;
+ float f = dot(fenc,fenc);
+ float g = sqrt(1-f/4);
+ vec3 n;
+ n.xy = fenc*g;
+ n.z = 1-f/2;
+ return n;
+}
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMapDownsampled, pos_screen.xy*downsampled_depth_scale).r;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec2 getKern(int i)
+{
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * (0.125*0.125*.9+.1);
+ kern[1] = vec2(1.0, 0.0) * (0.250*0.250*.9+.1);
+ kern[2] = vec2(0.0, 1.0) * (0.375*0.375*.9+.1);
+ kern[3] = vec2(0.0, -1.0) * (0.500*0.500*.9+.1);
+ kern[4] = vec2(0.7071, 0.7071) * (0.625*0.625*.9+.1);
+ kern[5] = vec2(-0.7071, -0.7071) * (0.750*0.750*.9+.1);
+ kern[6] = vec2(-0.7071, 0.7071) * (0.875*0.875*.9+.1);
+ kern[7] = vec2(0.7071, -0.7071) * (1.000*1.000*.9+.1);
+
+ return kern[i];
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm)
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+
+ // We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
+ float points = 1.0;
+ float angle_hidden = 0.0;
+
+ // use a kernel scale that diminishes with distance.
+ // a scale of less than 32 is just wasting good samples, though.
+ float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
+
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
+
+ vec3 diff = samppos_world - pos.xyz;
+
+ if (diff.z < ssao_factor && diff.z != 0.0)
+ {
+ float dist = length(diff);
+ float angrel = max(0.0, dot(norm.xyz, diff/dist));
+ float distrel = 1.0/(1.0+dist*dist);
+ float samplehidden = min(angrel, distrel);
+
+ angle_hidden += (samplehidden);
+ points += 1.0;
+ }
+ }
+
+ angle_hidden /= points;
+ float rtn = (1.0 - angle_hidden);
+ return (rtn * rtn) * (rtn * rtn); //Pow2 to increase darkness to match previous behavior.
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+
+ //try doing an unproject here
+
+ vec4 pos = getPosition(pos_screen);
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+ norm = decode_normal(norm.xy);
+
+ frag_color = vec4(calcAmbientOcclusion(pos,norm),0,0,0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 35362cabb..b1cacf8b0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -51,7 +51,6 @@ uniform float max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform mat3 env_mat;
-uniform mat3 ssao_effect_mat;
uniform vec3 sun_dir;
@@ -312,7 +311,7 @@ void setAtmosAttenuation(vec3 v)
vary_AtmosAttenuation = v;
}
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+void calcAtmospherics(vec3 inPositionEye) {
vec3 P = inPositionEye;
setPositionEye(P);
@@ -373,16 +372,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//increase ambient when there are more clouds
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
- /* decrease value and saturation (that in HSV, not HSL) for occluded areas
- * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
- * // The following line of code performs the equivalent of:
- * float ambAlpha = tmpAmbient.a;
- * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
- * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
- * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
- */
- tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
@@ -568,7 +557,7 @@ void main()
vec3 norm = vary_norm;
- calcAtmospherics(pos.xyz, 1.0);
+ calcAtmospherics(pos.xyz);
vec2 abnormal = encode_normal(norm.xyz);
norm.xyz = decode_normal(abnormal.xy);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 369a014fb..80c0c6e7b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -38,7 +38,7 @@ uniform sampler2DRect lightMap;
uniform float dist_factor;
uniform float blur_size;
uniform vec2 delta;
-uniform vec3 kern[4];
+//uniform vec3 kern[4];
uniform float kern_scale;
VARYING vec2 vary_fragcoord;
@@ -46,8 +46,14 @@ VARYING vec2 vary_fragcoord;
uniform mat4 inv_proj;
uniform vec2 screen_res;
-vec3 getKern(int i)
+vec2 getKern(int i)
{
+ vec2 kern[4];
+
+ kern[0] = vec2(0.3989422804,0.1994711402);
+ kern[1] = vec2(0.2419707245,0.1760326634);
+ kern[2] = vec2(0.0539909665,0.1209853623);
+ kern[3] = vec2(0.0044318484,0.0647587978);
return kern[i];
}
@@ -102,33 +108,37 @@ void main()
// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5
float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard
- tc += ( (tc_mod - 0.5) * getKern(1).z * dlt * 0.5 );
+ tc += ( (tc_mod - 0.5) * dlt * 0.5 );
for (int i = 1; i < 4; i++)
{
- vec2 samptc = (tc + getKern(i).z * dlt);
- vec3 samppos = getPosition(samptc).xyz;
+ vec2 samptc = (tc + i * dlt);
+ 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)*getKern(i).xyxx;
- defined_weight += getKern(i).xy;
+ vec4 weight = getKern(i).xyxx;
+ col += texture2DRect(lightMap, samptc)*weight;
+ defined_weight += weight.xy;
}
}
for (int i = 1; i < 4; i++)
{
- vec2 samptc = (tc - getKern(i).z * dlt);
- vec3 samppos = getPosition(samptc).xyz;
+ vec2 samptc = (tc - i * dlt);
+ 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)*getKern(i).xyxx;
- defined_weight += getKern(i).xy;
+ vec4 weight = getKern(i).xyxx;
+ col += texture2DRect(lightMap, samptc)*weight;
+ defined_weight += weight.xy;
}
}
col /= defined_weight.xyxx;
- col.y *= col.y; // delinearize SSAO effect post-blur
+ //col.y *= col.y; // delinearize SSAO effect post-blur // Singu note: Performed pre-blur as to remove blur requirement
frag_color = col;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl b/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl
new file mode 100644
index 000000000..9b6355fb9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/downsampleDepthNearestF.glsl
@@ -0,0 +1,41 @@
+/**
+ * @file sunLightF.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$
+ */
+
+//#extension GL_ARB_texture_rectangle : enable
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect depthMap;
+
+VARYING vec2 vary_fragcoord;
+
+void main()
+{
+ gl_FragDepth = texture2DRect(depthMap, vary_fragcoord.xy).r;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index d7abc457d..c1d0ee266 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -134,7 +134,6 @@ uniform float max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform mat3 env_mat;
-uniform mat3 ssao_effect_mat;
uniform vec3 sun_dir;
@@ -335,7 +334,7 @@ void setAtmosAttenuation(vec3 v)
vary_AtmosAttenuation = v;
}
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+void calcAtmospherics(vec3 inPositionEye) {
vec3 P = inPositionEye;
setPositionEye(P);
@@ -396,16 +395,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//increase ambient when there are more clouds
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
- /* decrease value and saturation (that in HSV, not HSL) for occluded areas
- * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
- * // The following line of code performs the equivalent of:
- * float ambAlpha = tmpAmbient.a;
- * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
- * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
- * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
- */
- tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
@@ -677,7 +666,7 @@ void main()
vec3 col = vec3(0.0f,0.0f,0.0f);
float bloom = 0.0;
- calcAtmospherics(pos.xyz, 1.0);
+ calcAtmospherics(pos.xyz);
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 7e149fae8..a0e5958eb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -64,7 +64,6 @@ uniform vec4 glow;
uniform float global_gamma;
uniform float scene_light_strength;
uniform mat3 env_mat;
-uniform float ssao_effect;
uniform vec3 sun_dir;
VARYING vec2 vary_fragcoord;
@@ -238,7 +237,7 @@ vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
}
#endif
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+void calcAtmospherics(vec3 inPositionEye) {
vec3 P = inPositionEye;
setPositionEye(P);
@@ -305,9 +304,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
- // decrease value for occluded areas
- tmpAmbient = vec4(mix(ssao_effect * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
//brightness of surface both sunlight and ambient
setSunlitColor(vec3(sunlight * .5));
setAmblitColor(vec3(tmpAmbient * .25));
@@ -408,7 +404,7 @@ void main()
float final_da = max(0.0,da);
final_da = min(final_da, 1.0f);
final_da = pow(final_da, 1.0/1.3);
- calcAtmospherics(pos.xyz, 1.0);
+ calcAtmospherics(pos.xyz);
col = atmosAmbient(vec3(0));
float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index a1ae08bb6..a0e1af439 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -31,120 +31,19 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
-//class 1 -- no shadow, SSAO only
-
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform sampler2D noiseMap;
-
-
-// Inputs
-uniform float ssao_radius;
-uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
-
VARYING vec2 vary_fragcoord;
-uniform mat4 inv_proj;
+uniform sampler2DRect depthMapDownsampled;
+uniform sampler2DRect depthMap;
+
+uniform sampler2DRect diffuseRect;
+uniform float downsampled_depth_scale;
uniform vec2 screen_res;
-vec2 encode_normal(vec3 n)
-{
- float f = sqrt(8 * n.z + 8);
- return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
- vec2 fenc = enc*4-2;
- float f = dot(fenc,fenc);
- float g = sqrt(1-f/4);
- vec3 n;
- n.xy = fenc*g;
- n.z = 1-f/2;
- return n;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
- float depth = texture2DRect(depthMap, pos_screen.xy).r;
- vec2 sc = pos_screen.xy*2.0;
- sc /= screen_res;
- sc -= vec2(1.0,1.0);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
-
-//calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm)
-{
- vec2 kern[8];
- // exponentially (^2) distant occlusion samples spread around origin
- kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
- kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
- kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
- kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
- kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
- kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
- kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
- kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
-
- vec2 pos_screen = vary_fragcoord.xy;
- vec3 pos_world = pos.xyz;
- vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
-
- // We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
- float points = 1.0;
- float angle_hidden = 0.0;
-
- // use a kernel scale that diminishes with distance.
- // a scale of less than 32 is just wasting good samples, though.
- float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
-
- // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
- for (int i = 0; i < 8; i++)
- {
- vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
- vec3 samppos_world = getPosition(samppos_screen).xyz;
-
- vec3 diff = samppos_world - pos.xyz;
-
- if (diff.z < ssao_factor && diff.z != 0.0)
- {
- float dist = length(diff);
- float angrel = max(0.0, dot(norm.xyz, diff/dist));
- float distrel = 1.0/(1.0+dist*dist);
- float samplehidden = min(angrel, distrel);
-
- angle_hidden += (samplehidden);
- points += 1.0;
- }
- }
-
- angle_hidden /= points;
-
- float rtn = (1.0 - angle_hidden);
-
- return (rtn * rtn);
-}
-
void main()
-{
- vec2 pos_screen = vary_fragcoord.xy;
-
- //try doing an unproject here
-
- vec4 pos = getPosition(pos_screen);
-
- vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
- norm = decode_normal(norm.xy);
-
+{
frag_color[0] = 1.0;
- frag_color[1] = calcAmbientOcclusion(pos, norm);
- frag_color[2] = 1.0;
+ frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord.xy*downsampled_depth_scale).r;
+ frag_color[2] = 1.0;
frag_color[3] = 1.0;
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index 2be812200..9b3b9ed5a 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -32,6 +32,7 @@ out vec4 frag_color;
//class 2 -- shadows and SSAO
+uniform sampler2DRect diffuseRect;
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
uniform sampler2DShadow shadowMap0;
@@ -40,16 +41,12 @@ uniform sampler2DShadow shadowMap2;
uniform sampler2DShadow shadowMap3;
uniform sampler2DShadow shadowMap4;
uniform sampler2DShadow shadowMap5;
-uniform sampler2D noiseMap;
+//uniform sampler2D noiseMap;
// Inputs
uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
-uniform float ssao_radius;
-uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
VARYING vec2 vary_fragcoord;
@@ -66,6 +63,8 @@ uniform float shadow_offset;
uniform float spot_shadow_bias;
uniform float spot_shadow_offset;
+uniform float downsampled_depth_scale;
+
vec2 encode_normal(vec3 n)
{
float f = sqrt(8 * n.z + 8);
@@ -96,61 +95,6 @@ vec4 getPosition(vec2 pos_screen)
return pos;
}
-vec2 getKern(int i)
-{
- vec2 kern[8];
- // exponentially (^2) distant occlusion samples spread around origin
- kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
- kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
- kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
- kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
- kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
- kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
- kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
- kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
-
- return kern[i];
-}
-
-//calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm)
-{
- vec2 pos_screen = vary_fragcoord.xy;
- vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
-
- // We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
- float points = 1.0;
- float angle_hidden = 0.0;
-
- // use a kernel scale that diminishes with distance.
- // a scale of less than 32 is just wasting good samples, though.
- float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
-
- // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
- for (int i = 0; i < 8; i++)
- {
- vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
- vec3 samppos_world = getPosition(samppos_screen).xyz;
-
- vec3 diff = samppos_world - pos.xyz;
-
- if (diff.z < ssao_factor && diff.z != 0.0)
- {
- float dist = length(diff);
- float angrel = max(0.0, dot(norm.xyz, diff/dist));
- float distrel = 1.0/(1.0+dist*dist);
- float samplehidden = min(angrel, distrel);
-
- angle_hidden += (samplehidden);
- points += 1.0;
- }
- }
-
- angle_hidden /= points;
- float rtn = (1.0 - angle_hidden);
- return (rtn * rtn);
-}
-
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
{
stc.xyz /= stc.w;
@@ -301,7 +245,7 @@ void main()
}
frag_color[0] = shadow;
- frag_color[1] = calcAmbientOcclusion(pos, norm);
+ frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord*downsampled_depth_scale);
spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 3e2dc4308..0a2a7f1c0 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -221,7 +221,7 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass )
LLFastTimer t(FTM_RENDER_ALPHA);
LLRenderPass::endRenderPass(pass);
- if(gPipeline.canUseWindLightShaders())
+ if(mVertexShaderLevel > 0) //Singu Note: Unbind if shaders are enabled at all, not just windlight atmospherics..
{
LLGLSLShader::bindNoShader();
}
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 23e407d40..c8f2d4c9a 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -693,6 +693,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2));
gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("SHRenderSSAOResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2));
gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 6df2a4f28..93b4e6b5a 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -206,6 +206,8 @@ LLGLSLShader gDeferredLightProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShaderArray gDeferredMultiLightProgram[16];
LLGLSLShader gDeferredSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
LLGLSLShader gDeferredMultiSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
+LLGLSLShader gDeferredSSAOProgram(LLViewerShaderMgr::SHADER_DEFERRED);
+LLGLSLShader gDeferredDownsampleDepthNearestProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredSunProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED);
@@ -1336,6 +1338,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredSunProgram.createShader(NULL, NULL);
}
+ if(gSavedSettings.getBOOL("RenderDeferredSSAO"))
+ {
+ if (success)
+ {
+ gDeferredSSAOProgram.mName = "Deferred Ambient Occlusion Shader";
+ gDeferredSSAOProgram.mShaderFiles.clear();
+ gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/SSAOF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSSAOProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredSSAOProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredDownsampleDepthNearestProgram.mName = "Deferred Nearest Downsample Depth Shader";
+ gDeferredDownsampleDepthNearestProgram.mShaderFiles.clear();
+ gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/downsampleDepthNearestF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDownsampleDepthNearestProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredDownsampleDepthNearestProgram.createShader(NULL, NULL);
+ }
+ }
+
if (success)
{
gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 320c25828..99374c31a 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -313,6 +313,8 @@ extern LLGLSLShaderArray gDeferredMultiLig
extern LLGLSLShader gDeferredSpotLightProgram;
extern LLGLSLShader gDeferredMultiSpotLightProgram;
extern LLGLSLShader gDeferredSunProgram;
+extern LLGLSLShader gDeferredSSAOProgram;
+extern LLGLSLShader gDeferredDownsampleDepthNearestProgram;
extern LLGLSLShader gDeferredBlurLightProgram;
extern LLGLSLShader gDeferredAvatarProgram;
extern LLGLSLShader gDeferredSoftenProgram;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e6aec53bb..7d2095334 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -207,11 +207,11 @@ LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
-static LLStaticHashedString sTint("tint");
-static LLStaticHashedString sAmbiance("ambiance");
-static LLStaticHashedString sAlphaScale("alpha_scale");
+//static LLStaticHashedString sTint("tint");
+//static LLStaticHashedString sAmbiance("ambiance");
+//static LLStaticHashedString sAlphaScale("alpha_scale");
static LLStaticHashedString sNormMat("norm_mat");
-static LLStaticHashedString sOffset("offset");
+//static LLStaticHashedString sOffset("offset");
static LLStaticHashedString sScreenRes("screenRes");
static LLStaticHashedString sDelta("delta");
static LLStaticHashedString sDistFactor("dist_factor");
@@ -796,12 +796,15 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
mSampleBuffer.release();
mScreen.release();
+ mDeferredDownsampledDepth.release();
+
if (LLPipeline::sRenderDeferred)
{
- S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
- BOOL ssao = gSavedSettings.getBOOL("RenderDeferredSSAO");
- BOOL RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
+ static const LLCachedControl shadow_detail("RenderShadowDetail",0);
+ static const LLCachedControl ssao ("RenderDeferredSSAO",false);
+ static const LLCachedControl RenderDepthOfField("RenderDepthOfField",false);
static const LLCachedControl RenderShadowResolutionScale("RenderShadowResolutionScale",1.0f);
+ static const LLCachedControl RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
const U32 occlusion_divisor = 3;
@@ -835,6 +838,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
{ //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ if(ssao)
+ {
+ F32 scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
+ if( scale < 1.f && !mDeferredDownsampledDepth.allocate(llceil(F32(resX)*scale), llceil(F32(resY)*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE) ) return false;
+ }
}
else
{
@@ -901,6 +909,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
mScreen.release();
mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
mDeferredDepth.release();
+ mDeferredDownsampledDepth.release();
mOcclusionDepth.release();
if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
@@ -1022,6 +1031,7 @@ void LLPipeline::releaseScreenBuffers()
mPhysicsDisplay.release();
mDeferredScreen.release();
mDeferredDepth.release();
+ mDeferredDownsampledDepth.release();
mDeferredLight.release();
mOcclusionDepth.release();
@@ -7648,6 +7658,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
static const LLCachedControl RenderSpotShadowBias("RenderSpotShadowBias",0.f);
static const LLCachedControl RenderEdgeDepthCutoff("RenderEdgeDepthCutoff",.01f);
static const LLCachedControl RenderEdgeNormCutoff("RenderEdgeNormCutoff",.25f);
+ static const LLCachedControl RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
if (noise_map == 0xFFFFFFFF)
{
@@ -7677,10 +7688,21 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+ S32 channel2 = shader.enableTexture(LLShaderMgr::DEFERRED_DOWNSAMPLED_DEPTH, mDeferredDepth.getUsage());
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
- if (channel > -1)
+ if (channel > -1 || channel2 >= -1)
{
- gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+ if(channel > -1)
+ gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+ if(channel2 > -1)
+ {
+ F32 scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
+ if(scale < 1.f)
+ gGL.getTexUnit(channel2)->bind(&mDeferredDownsampledDepth, TRUE);
+ else
+ gGL.getTexUnit(channel2)->bind(&mDeferredDepth, TRUE); //Bind full res depth instead, as downsampling is disabled if scale == 1.f
+ }
+
//gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
@@ -7774,21 +7796,24 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
stop_glerror();
- F32 mat[16*6];
- for (U32 i = 0; i < 16; i++)
+ if(shader.getUniformLocation(LLShaderMgr::DEFERRED_SHADOW_MATRIX) >= 0)
{
- mat[i] = mSunShadowMatrix[0].m[i];
- mat[i+16] = mSunShadowMatrix[1].m[i];
- mat[i+32] = mSunShadowMatrix[2].m[i];
- mat[i+48] = mSunShadowMatrix[3].m[i];
- mat[i+64] = mSunShadowMatrix[4].m[i];
- mat[i+80] = mSunShadowMatrix[5].m[i];
+ F32 mat[16*6];
+ for (U32 i = 0; i < 16; i++)
+ {
+ mat[i] = mSunShadowMatrix[0].m[i];
+ mat[i+16] = mSunShadowMatrix[1].m[i];
+ mat[i+32] = mSunShadowMatrix[2].m[i];
+ mat[i+48] = mSunShadowMatrix[3].m[i];
+ mat[i+64] = mSunShadowMatrix[4].m[i];
+ mat[i+80] = mSunShadowMatrix[5].m[i];
+ }
+
+ shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
+
+ stop_glerror();
}
- shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
-
- stop_glerror();
-
channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
if (channel > -1)
{
@@ -7844,6 +7869,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
}
+
+ shader.uniform1f(LLShaderMgr::DEFERRED_DOWNSAMPLED_DEPTH_SCALE, llclamp(RenderSSAOResolutionScale.get(),.01f,1.f));
}
static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
@@ -7867,6 +7894,7 @@ void LLPipeline::renderDeferredLighting()
static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0);
static const LLCachedControl RenderDeferredSSAO("RenderDeferredSSAO",false);
+ static const LLCachedControl RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
static const LLCachedControl RenderShadowDetail("RenderShadowDetail",0);
static const LLCachedControl RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
static const LLCachedControl RenderShadowBlurSize("RenderShadowBlurSize",1.4f);
@@ -7933,6 +7961,54 @@ void LLPipeline::renderDeferredLighting()
gGL.pushMatrix();
gGL.loadIdentity();
+ if (RenderDeferredSSAO)
+ {
+ F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
+
+ LLGLDisable blend(GL_BLEND);
+
+ //Downsample with fullscreen quad. GL_NEAREST
+ if(ssao_scale < 1.f)
+ {
+ mDeferredDownsampledDepth.bindTarget();
+ mDeferredDownsampledDepth.clear(GL_DEPTH_BUFFER_BIT);
+ bindDeferredShader(gDeferredDownsampleDepthNearestProgram, 0);
+ gDeferredDownsampleDepthNearestProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ mDeferredDownsampledDepth.flush();
+ unbindDeferredShader(gDeferredDownsampleDepthNearestProgram);
+ }
+
+ //Run SSAO
+ {
+ mScreen.bindTarget();
+ glClearColor(1,1,1,1);
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
+ bindDeferredShader(gDeferredSSAOProgram, 0);
+ if(ssao_scale < 1.f)
+ {
+ glViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight());
+ gDeferredSSAOProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
+ }
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ mScreen.flush();
+ unbindDeferredShader(gDeferredSSAOProgram);
+ }
+ }
+
if (RenderDeferredSSAO || RenderShadowDetail > 0)
{
mDeferredLight.bindTarget();
@@ -7944,7 +8020,7 @@ void LLPipeline::renderDeferredLighting()
mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
glClearColor(0,0,0,0);
- glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+ /*glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
const U32 slice = 32;
F32 offset[slice*3];
@@ -7978,8 +8054,18 @@ void LLPipeline::renderDeferredLighting()
}
}
- gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
+ gDeferredSunProgram.uniform3fv(sOffset, slice, offset);*/
+
gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
+
+ //Enable bilinear filtering, as the screen tex resolution may not match current framebuffer resolution. Eg, half-res SSAO
+ // diffuse map should only be found if the sun shader is the SSAO variant.
+ S32 channel = gDeferredSunProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0,channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
{
LLGLDisable blend(GL_BLEND);
@@ -7988,6 +8074,11 @@ void LLPipeline::renderDeferredLighting()
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
stop_glerror();
}
+
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
unbindDeferredShader(gDeferredSunProgram);
}
@@ -8106,6 +8197,9 @@ void LLPipeline::renderDeferredLighting()
gPipeline.pushRenderTypeMask();
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+#if ENABLE_CLASSIC_CLOUDS
+ LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS,
+#endif
LLPipeline::RENDER_TYPE_WL_CLOUDS,
LLPipeline::RENDER_TYPE_WL_SKY,
LLPipeline::END_RENDER_TYPES);
@@ -8500,6 +8594,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
static const LLCachedControl RenderFSAASamples("RenderFSAASamples",0);
static const LLCachedControl RenderDeferredSSAO("RenderDeferredSSAO",false);
+ static const LLCachedControl RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
static const LLCachedControl RenderShadowDetail("RenderShadowDetail",0);
static const LLCachedControl RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
static const LLCachedControl RenderShadowBlurSize("RenderShadowBlurSize",1.4f);
@@ -8560,6 +8655,54 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
gGL.pushMatrix();
gGL.loadIdentity();
+ if (RenderDeferredSSAO)
+ {
+ F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
+
+ LLGLDisable blend(GL_BLEND);
+
+ //Downsample with fullscreen quad. GL_NEAREST
+ if(ssao_scale < 1.f)
+ {
+ mDeferredDownsampledDepth.bindTarget();
+ mDeferredDownsampledDepth.clear(GL_DEPTH_BUFFER_BIT);
+ bindDeferredShader(gDeferredDownsampleDepthNearestProgram, 0);
+ gDeferredDownsampleDepthNearestProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ mDeferredDownsampledDepth.flush();
+ unbindDeferredShader(gDeferredDownsampleDepthNearestProgram);
+ }
+
+ //Run SSAO
+ {
+ mScreen.bindTarget();
+ glClearColor(1,1,1,1);
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
+ bindDeferredShader(gDeferredSSAOProgram, 0);
+ if(ssao_scale < 1.f)
+ {
+ glViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight());
+ gDeferredSSAOProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
+ }
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ mScreen.flush();
+ unbindDeferredShader(gDeferredSSAOProgram);
+ }
+ }
+
if (RenderDeferredSSAO || RenderShadowDetail > 0)
{
mDeferredLight.bindTarget();
@@ -8571,7 +8714,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
glClearColor(0,0,0,0);
- glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+ /*glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
const U32 slice = 32;
F32 offset[slice*3];
@@ -8590,9 +8733,18 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
}
}
- gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset);
+ gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset);*/
gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
+ //Enable bilinear filtering, as the screen tex resolution may not match current framebuffer resolution. Eg, half-res SSAO
+ // diffuse map should only be found if the sun shader is the SSAO variant.
+ S32 channel = gDeferredSunProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0,channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
{
LLGLDisable blend(GL_BLEND);
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
@@ -8600,6 +8752,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
stop_glerror();
}
+
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
unbindDeferredShader(gDeferredSunProgram);
}
@@ -8656,7 +8813,10 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
gPipeline.pushRenderTypeMask();
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+#if ENABLE_CLASSIC_CLOUDS
LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS,
+#endif
+ LLPipeline::RENDER_TYPE_WL_CLOUDS,
LLPipeline::RENDER_TYPE_WL_SKY,
LLPipeline::END_RENDER_TYPES);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 453512d80..6a7d7479d 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -615,6 +615,7 @@ public:
LLRenderTarget mFXAABuffer;
LLRenderTarget mEdgeMap;
LLRenderTarget mDeferredDepth;
+ LLRenderTarget mDeferredDownsampledDepth;
LLRenderTarget mOcclusionDepth;
LLRenderTarget mDeferredLight;
LLMultisampleBuffer mSampleBuffer;