From eb3206fb93187efdef3dce389862ed31be516963 Mon Sep 17 00:00:00 2001
From: Tofu Linden <tofu.linden@lindenlab.com>
Date: Mon, 22 Mar 2010 16:10:34 +0000
Subject: screen-space reflections mk4.  generally subtle.  very cheap.

---
 .../shaders/class1/deferred/softenLightF.glsl      | 47 +++++++++++++++++----
 .../shaders/class2/deferred/softenLightF.glsl      | 48 ++++++++++++++++++----
 .../shaders/class3/deferred/softenLightF.glsl      | 48 ++++++++++++++++++----
 3 files changed, 119 insertions(+), 24 deletions(-)

diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 9cf60aad48..7d57eaa13d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -56,9 +56,8 @@ vec3 vary_AtmosAttenuation;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec4 getPosition(vec2 pos_screen)
-{ //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
@@ -69,6 +68,12 @@ vec4 getPosition(vec2 pos_screen)
 	return pos;
 }
 
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	return getPosition_d(pos_screen, depth);
+}
+
 vec3 getPositionEye()
 {
 	return vary_PositionEye;
@@ -252,7 +257,8 @@ vec3 scaleSoftClip(vec3 light)
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
-	vec3 pos = getPosition(tc).xyz;
+	float depth = texture2DRect(depthMap, tc.xy).a;
+	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
 	//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
 	
@@ -272,11 +278,36 @@ void main()
 	
 	col *= diffuse.rgb;
 	
-	if (spec.a > 0.0)
+	if (spec.a > 0.0) // specular reflection
 	{
-		vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
-		float sa = dot(ref, vary_light.xyz);
-		col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+		// the old infinite-sky shiny reflection
+		//
+		vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz));
+		float sa = dot(refnorm, vary_light.xyz);
+		vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+		// screen-space cheap fakey reflection map
+		//
+		// first figure out where we'll make our 2D guess from
+		vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
+		// get attributes from the 2D guess point
+		float refdepth = texture2DRect(depthMap, ref2d).a;
+		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
+		vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb;
+		vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0);
+		// figure out how appropriate our guess actually was
+		float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
+		// darken reflections from points which face away from the reflected ray - our guess was a back-face
+		//refapprop *= step(dot(refnorm, refn), 0.0);
+		refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
+		// get appropriate light strength for guess-point
+		float reflit = max(dot(refn, vary_light.xyz), 0.0);
+		// apply sun color to guess-point, dampen according to inappropriateness of guess
+		vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop;
+		vec3 ssshiny = (refprod * spec.a);
+
+		// add the two types of shiny together
+		col += (ssshiny + dumbshiny) * spec.rgb;
 	}
 	
 	col = atmosLighting(col);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 589a292751..c5530c5f59 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -55,9 +55,8 @@ vec3 vary_AmblitColor;
 vec3 vary_AdditiveColor;
 vec3 vary_AtmosAttenuation;
 
-vec4 getPosition(vec2 pos_screen)
-{ //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
@@ -68,6 +67,12 @@ vec4 getPosition(vec2 pos_screen)
 	return pos;
 }
 
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	return getPosition_d(pos_screen, depth);
+}
+
 vec3 getPositionEye()
 {
 	return vary_PositionEye;
@@ -251,7 +256,8 @@ vec3 scaleSoftClip(vec3 light)
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
-	vec3 pos = getPosition(tc).xyz;
+	float depth = texture2DRect(depthMap, tc.xy).a;
+	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
 	//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
 	
@@ -271,11 +277,37 @@ void main()
 	
 	col *= diffuse.rgb;
 	
-	if (spec.a > 0.0)
+	if (spec.a > 0.0) // specular reflection
 	{
-		vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
-		float sa = dot(ref, vary_light.xyz);
-		col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+		// the old infinite-sky shiny reflection
+		//
+		vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz));
+		float sa = dot(refnorm, vary_light.xyz);
+		vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+		// screen-space cheap fakey reflection map
+		//
+		// first figure out where we'll make our 2D guess from
+		vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
+		// get attributes from the 2D guess point
+		float refdepth = texture2DRect(depthMap, ref2d).a;
+		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
+		vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb;
+		float refshad = texture2DRect(lightMap, ref2d).r;
+		vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0);
+		// figure out how appropriate our guess actually was
+		float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
+		// darken reflections from points which face away from the reflected ray - our guess was a back-face
+		//refapprop *= step(dot(refnorm, refn), 0.0);
+		refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
+		// get appropriate light strength for guess-point
+		float reflit = min(max(dot(refn, vary_light.xyz), 0.0), refshad);
+		// apply sun color to guess-point, dampen according to inappropriateness of guess
+		vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop;
+		vec3 ssshiny = (refprod * spec.a);
+
+		// add the two types of shiny together
+		col += (ssshiny + dumbshiny) * spec.rgb;
 	}
 	
 	col = atmosLighting(col);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 96a083b522..265fb437ec 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -56,9 +56,8 @@ vec3 vary_AdditiveColor;
 vec3 vary_AtmosAttenuation;
 uniform float gi_ambiance;
 
-vec4 getPosition(vec2 pos_screen)
-{ //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
 	vec2 sc = pos_screen.xy*2.0;
 	sc /= screen_res;
 	sc -= vec2(1.0,1.0);
@@ -69,6 +68,12 @@ vec4 getPosition(vec2 pos_screen)
 	return pos;
 }
 
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	return getPosition_d(pos_screen, depth);
+}
+
 vec3 getPositionEye()
 {
 	return vary_PositionEye;
@@ -252,7 +257,8 @@ vec3 scaleSoftClip(vec3 light)
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
-	vec3 pos = getPosition(tc).xyz;
+	float depth = texture2DRect(depthMap, tc.xy).a;
+	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
 	//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
 	
@@ -274,11 +280,37 @@ void main()
 	
 	col *= diffuse.rgb;
 	
-	if (spec.a > 0.0)
+	if (spec.a > 0.0) // specular reflection
 	{
-		vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
-		float sa = dot(ref, vary_light.xyz);
-		col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+		// the old infinite-sky shiny reflection
+		//
+		vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz));
+		float sa = dot(refnorm, vary_light.xyz);
+		vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+		// screen-space cheap fakey reflection map
+		//
+		// first figure out where we'll make our 2D guess from
+		vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
+		// get attributes from the 2D guess point
+		float refdepth = texture2DRect(depthMap, ref2d).a;
+		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
+		vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb;
+		float refshad = texture2DRect(lightMap, ref2d).r;
+		vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0);
+		// figure out how appropriate our guess actually was
+		float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
+		// darken reflections from points which face away from the reflected ray - our guess was a back-face
+		//refapprop *= step(dot(refnorm, refn), 0.0);
+		refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
+		// get appropriate light strength for guess-point
+		float reflit = min(max(dot(refn, vary_light.xyz), 0.0), refshad);
+		// apply sun color to guess-point, dampen according to inappropriateness of guess
+		vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop;
+		vec3 ssshiny = (refprod * spec.a);
+
+		// add the two types of shiny together
+		col += (ssshiny + dumbshiny) * spec.rgb;
 	}
 	
 	col = atmosLighting(col);
-- 
cgit v1.2.3