From 940bca8ebc03d963d8384f07b4bea7c5484691a3 Mon Sep 17 00:00:00 2001
From: Tofu Linden <tofu.linden@lindenlab.com>
Date: Sun, 9 May 2010 15:02:10 +0100
Subject: [PATCH] Rejig deferred normal-map packing a little, to double its
 accuracy for free.

---
 .../app_settings/shaders/class1/deferred/avatarF.glsl |  3 ++-
 .../shaders/class1/deferred/blurLightF.glsl           |  3 ++-
 .../app_settings/shaders/class1/deferred/bumpF.glsl   |  3 ++-
 .../shaders/class1/deferred/diffuseF.glsl             |  3 ++-
 .../app_settings/shaders/class1/deferred/giF.glsl     |  3 ++-
 .../shaders/class1/deferred/multiPointLightF.glsl     |  3 ++-
 .../shaders/class1/deferred/pointLightF.glsl          |  3 ++-
 .../app_settings/shaders/class1/deferred/postgiF.glsl |  9 +++++----
 .../shaders/class1/deferred/softenLightF.glsl         |  6 ++++--
 .../shaders/class1/deferred/spotLightF.glsl           |  3 ++-
 .../shaders/class1/deferred/sunLightSSAOF.glsl        |  3 ++-
 .../shaders/class1/deferred/terrainF.glsl             |  3 ++-
 .../app_settings/shaders/class1/deferred/treeF.glsl   |  3 ++-
 .../app_settings/shaders/class1/deferred/waterF.glsl  |  2 +-
 .../shaders/class2/deferred/blurLightF.glsl           |  3 ++-
 .../app_settings/shaders/class2/deferred/edgeF.glsl   | 11 ++++++++---
 .../shaders/class2/deferred/multiSpotLightF.glsl      |  3 ++-
 .../shaders/class2/deferred/softenLightF.glsl         |  7 +++++--
 .../shaders/class2/deferred/spotLightF.glsl           |  3 ++-
 .../shaders/class2/deferred/sunLightF.glsl            |  3 ++-
 .../shaders/class2/deferred/sunLightSSAOF.glsl        |  3 ++-
 .../shaders/class3/deferred/giDownsampleF.glsl        | 10 ++++++----
 .../app_settings/shaders/class3/deferred/giF.glsl     |  3 ++-
 .../shaders/class3/deferred/softenLightF.glsl         |  7 +++++--
 .../app_settings/shaders/class3/deferred/treeF.glsl   |  3 ++-
 25 files changed, 70 insertions(+), 36 deletions(-)

diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 75df3889418..afbe08a5794 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -20,6 +20,7 @@ void main()
 	
 	gl_FragData[0] = vec4(diff.rgb, 0.0);
 	gl_FragData[1] = vec4(0,0,0,0);
-	gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+	vec3 nvn = normalize(vary_normal);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 0fad5b4b50b..d1c5d7cb195 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -37,7 +37,8 @@ vec4 getPosition(vec2 pos_screen)
 
 void main() 
 {
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	vec3 pos = getPosition(vary_fragcoord.xy).xyz;
 	vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index 6e38caf5ef8..2197744a372 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -24,5 +24,6 @@ void main()
 	gl_FragData[0] = vec4(col, 0.0);
 	gl_FragData[1] = gl_Color.aaaa; // spec
 	//gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested
-	gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0);
+	vec3 nvn = normalize(tnorm);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 112103956da..3803119cda3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -15,5 +15,6 @@ void main()
 	gl_FragData[0] = vec4(col, 0.0);
 	gl_FragData[1] = gl_Color.aaaa; // spec
 	//gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested
-	gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+	vec3 nvn = normalize(vary_normal);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
index b351eec6e54..d4b153c4af9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
@@ -159,7 +159,8 @@ void main()
 {
 	vec2 pos_screen = vary_fragcoord.xy;
 	vec4 pos = getPosition(pos_screen);
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	
 	gl_FragData[0].xyz = giAmbient(pos, norm);
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 797b9e9f3bf..e1715eb4f98 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -53,7 +53,8 @@ void main()
 		discard;
 	}
 	
-	vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0);
+	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	vec4 spec = texture2DRect(specularRect, frag.xy);
 	vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
 	float noise = texture2D(noiseMap, frag.xy/128.0).b;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 78256e20cc6..3aecbc5f23c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -55,7 +55,8 @@ void main()
 		discard;
 	}
 	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	float da = dot(norm, lv);
 	if (da < 0.0)
 	{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
index 9612aee4059..bd554c2d84c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -38,10 +38,10 @@ vec4 getPosition(vec2 pos_screen)
 
 void main() 
 {
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	vec3 pos = getPosition(vary_fragcoord.xy).xyz;
 	
-	
 	vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
 	vec2 dlt = kern_scale * delta/(1.0+norm.xy*norm.xy);
 	dlt /= max(-pos.z*dist_factor, 1.0);
@@ -51,9 +51,10 @@ void main()
 	for (int i = 0; i < kern_length; i++)
 	{
 		vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
-	    vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0;
+		vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz;
+		sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm
 	    
-	    float d = dot(norm.xyz, sampNorm);
+		float d = dot(norm.xyz, sampNorm);
 		
 		if (d > 0.8)
 		{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index ef614918260..bef91e735dc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -259,7 +259,8 @@ void main()
 	vec2 tc = vary_fragcoord.xy;
 	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 norm = texture2DRect(normalMap, tc).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
 	
 	float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
@@ -310,7 +311,8 @@ void main()
 				     texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
 		float refdepth = texture2DRect(depthMap, ref2d).a;
 		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
-		vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0);
+		vec3 refn = texture2DRect(normalMap, ref2d).rgb;
+		refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm
 		// 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
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index f320dbb4001..1b95b253c35 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -68,7 +68,8 @@ void main()
 		discard;
 	}
 	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	
 	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 7450817ea7a..cdbed4b7917 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -114,7 +114,8 @@ void main()
 	
 	vec4 pos = getPosition(pos_screen);
 	
-    vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 		
 	gl_FragColor[0] = 1.0;
 	gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 3cccfb72020..fa0a60c98d9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -29,6 +29,7 @@ void main()
 	
 	gl_FragData[0] = vec4(outColor.rgb, 0.0);
 	gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2);
-	gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+	vec3 nvn = normalize(vary_normal);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index 258acee08c1..5b33ea5bfe2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -14,5 +14,6 @@ void main()
 	vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
 	gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
 	gl_FragData[1] = vec4(0,0,0,0);
-	gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+	vec3 nvn = normalize(vary_normal);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index ceb7e0fb56e..361ae8dc843 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -137,5 +137,5 @@ void main()
 	
 	gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse
 	gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
-	gl_FragData[2] = vec4(screenspacewavef*0.5+0.5, screenspacewavef.z*0.5); // normal, displace
+	gl_FragData[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
index 0fad5b4b50b..d1c5d7cb195 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
@@ -37,7 +37,8 @@ vec4 getPosition(vec2 pos_screen)
 
 void main() 
 {
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	vec3 pos = getPosition(vary_fragcoord.xy).xyz;
 	vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
 	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
index 02beddd43b3..e32e9f4b326 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
@@ -31,7 +31,8 @@ float getDepth(vec2 pos_screen)
 
 void main() 
 {
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	float depth = getDepth(vary_fragcoord.xy);
 	
 	vec2 tc = vary_fragcoord.xy;
@@ -46,8 +47,12 @@ void main()
 	de = step(depth_cutoff, de);
 	
 	vec2 ne;
-	ne.x = dot(texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb*2.0-1.0, norm);
-	ne.y = dot(texture2DRect(normalMap, tc+vec2(sc,sc)).rgb*2.0-1.0, norm);
+	vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb;
+	nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm
+	ne.x = dot(nexnorm, norm);
+	vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb;
+	neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm
+	ne.y = dot(neynorm, norm);
 	
 	ne = 1.0-ne;
 	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 5308e5bb1e1..22ffb58c635 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -129,7 +129,8 @@ void main()
 		shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
 	}
 	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	
 	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index bc84720b86b..fd6ae2b9608 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -258,7 +258,8 @@ void main()
 	vec2 tc = vary_fragcoord.xy;
 	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 norm = texture2DRect(normalMap, tc).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
 	
 	float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
@@ -310,7 +311,9 @@ void main()
 		float refdepth = texture2DRect(depthMap, ref2d).a;
 		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
 		float refshad = texture2DRect(lightMap, ref2d).r;
-		vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0);
+		vec3 refn = texture2DRect(normalMap, ref2d).rgb;
+		refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
+		refn = normalize(refn);
 		// 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
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index eeaecc157ff..8a90199b7ca 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -82,7 +82,8 @@ void main()
 		discard;
 	}
 	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	
 	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index 46db3c990cf..195a20e9dde 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -104,8 +104,9 @@ void main()
 	vec4 pos = getPosition(pos_screen);
 	
 	vec4 nmap4 = texture2DRect(normalMap, pos_screen);
+	nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
 	float displace = nmap4.w;
-	vec3 norm = nmap4.xyz*2.0-1.0;
+	vec3 norm = nmap4.xyz;
 	
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index a0dfc96f14e..4e33a1af450 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -164,8 +164,9 @@ void main()
 	vec4 pos = getPosition(pos_screen);
 	
 	vec4 nmap4 = texture2DRect(normalMap, pos_screen);
+	nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
 	float displace = nmap4.w;
-	vec3 norm = nmap4.xyz*2.0-1.0;
+	vec3 norm = nmap4.xyz;
 	
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
index 7325825d6d4..66606233cdf 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
@@ -44,7 +44,8 @@ float getDepth(vec2 pos_screen)
 
 void main() 
 {
-	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	float depth = getDepth(vary_fragcoord.xy);
 		
 	vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
@@ -56,9 +57,10 @@ void main()
 	for (int i = 0; i < kern_length; i++)
 	{
 		vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
-	    vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0;
-	    
-	   float d = dot(norm.xyz, sampNorm);
+		vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz;
+		sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm
+		
+		float d = dot(norm.xyz, sampNorm);
 		
 		if (d > 0.5)
 		{
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
index 939710cb563..1b8354dbd10 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
@@ -178,7 +178,8 @@ void main()
 	
 	float rad = gi_range*0.5;
 	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	float dist = max(length(pos.xyz)-rad, 0.0);
 	
 	float da = clamp(1.0-dist/rad, 0.0, 1.0);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 5298079af79..c88edd0a60b 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -259,7 +259,8 @@ void main()
 	vec2 tc = vary_fragcoord.xy;
 	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 norm = texture2DRect(normalMap, tc).xyz;
+	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
 	//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
 	
 	float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
@@ -314,7 +315,9 @@ void main()
 		float refdepth = texture2DRect(depthMap, ref2d).a;
 		vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
 		float refshad = texture2DRect(lightMap, ref2d).r;
-		vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0);
+		vec3 refn = texture2DRect(normalMap, ref2d).rgb;
+		refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
+		refn = normalize(refn);
 		// 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
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
index 258acee08c1..5b33ea5bfe2 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
@@ -14,5 +14,6 @@ void main()
 	vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
 	gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
 	gl_FragData[1] = vec4(0,0,0,0);
-	gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+	vec3 nvn = normalize(vary_normal);
+	gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
 }
-- 
GitLab