Implement exponential vertex fog.

Change-Id: I731bb641e00ba9ac880fdb9f721af24906b4850f
Reviewed-on: https://swiftshader-review.googlesource.com/3802
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Shader/VertexPipeline.cpp b/src/Shader/VertexPipeline.cpp
index 9116e2e..e9d8216 100644
--- a/src/Shader/VertexPipeline.cpp
+++ b/src/Shader/VertexPipeline.cpp
@@ -172,6 +172,8 @@
 		r.o[Pos].z = position.z;
 		r.o[Pos].w = position.w;
 
+		Vector4f vertexPosition = transformBlend(r, r.v[Position], Pointer<Byte>(r.data + OFFSET(DrawData,ff.cameraTransformT)), true);
+
 		if(state.vertexNormalActive)
 		{
 			normal = transformBlend(r, r.v[Normal], Pointer<Byte>(r.data + OFFSET(DrawData,ff.normalTransformT)), false);
@@ -239,8 +241,6 @@
 			diffuseSum.z = Float4(0.0f);
 			diffuseSum.w = Float4(0.0f);
 
-			Vector4f vertexPosition = transformBlend(r, r.v[Position], Pointer<Byte>(r.data + OFFSET(DrawData,ff.cameraTransformT)), true);
-
 			for(int i = 0; i < 8; i++)
 			{
 				if(!(state.vertexLightActive & (1 << i)))
@@ -488,6 +488,17 @@
 
 		if(state.fogActive)
 		{
+			Float4 f;
+
+			if(!state.rangeFogActive)
+			{
+				f = Abs(vertexPosition.z);
+			}
+			else
+			{
+				f = Sqrt(dot3(vertexPosition, vertexPosition));   // FIXME: f = length(vertexPosition);
+			}
+
 			switch(state.vertexFogMode)
 			{
 			case FOG_NONE:
@@ -501,25 +512,13 @@
 				}
 				break;
 			case FOG_LINEAR:
+				r.o[Fog].x = f * *Pointer<Float4>(r.data + OFFSET(DrawData,fog.scale)) + *Pointer<Float4>(r.data + OFFSET(DrawData,fog.offset));
+				break;
 			case FOG_EXP:
+				r.o[Fog].x = exponential2(f * *Pointer<Float4>(r.data + OFFSET(DrawData,fog.densityE)), true);
+				break;
 			case FOG_EXP2:
-				if(!state.rangeFogActive)
-				{
-					r.o[Fog].x = r.o[Pos].z;
-				}
-				else
-				{
-					Vector4f pos;
-
-					pos.x = r.o[Pos].x;
-					pos.y = r.o[Pos].y;
-					pos.z = r.o[Pos].z;
-					pos.w = r.o[Pos].w;
-
-					r.o[Fog].x = Sqrt(dot3(pos, pos));   // FIXME: oFog = length(o[Pos]);
-				}
-
-				r.o[Fog].x = r.o[Fog].x * *Pointer<Float4>(r.data + OFFSET(DrawData,fog.scale)) + *Pointer<Float4>(r.data + OFFSET(DrawData,fog.offset));
+				r.o[Fog].x = exponential2((f * f) * *Pointer<Float4>(r.data + OFFSET(DrawData,fog.density2E)), true);
 				break;
 			default:
 				ASSERT(false);