From 2092eecc230e384896903a054ce1fbd22195df4a Mon Sep 17 00:00:00 2001
From: Christopher Bock <bockchristopher@live.de>
Date: Wed, 9 Mar 2016 21:04:04 +0100
Subject: [PATCH] * Refactored the R_View_Update function * Added a new uniform
 to shaders the EyeDirection * Reworked the water shader

---
 gl_rmain.c    | 32 +++++++++++++++++++++++++++-----
 render.h      |  2 ++
 shader_glsl.h | 47 ++++++++++++++++++++++++++---------------------
 3 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/gl_rmain.c b/gl_rmain.c
index 6f003803..b9b4e60b 100644
--- a/gl_rmain.c
+++ b/gl_rmain.c
@@ -825,6 +825,7 @@ typedef struct r_glsl_permutation_s
 	int loc_DeferredMod_Specular;
 	int loc_DistortScaleRefractReflect;
 	int loc_EyePosition;
+	int loc_EyeDirection;
 	int loc_FogColor;
 	int loc_FogHeightFade;
 	int loc_FogPlane;
@@ -1245,6 +1246,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode
 		p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
 		p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
 		p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
+		p->loc_EyeDirection               = qglGetUniformLocation(p->program, "EyeDirection");
 		p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
 		p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
 		p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
@@ -2843,6 +2845,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting,
 		if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
 		if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
 		if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
+		if (r_glsl_permutation->loc_EyeDirection >= 0) qglUniform3f(r_glsl_permutation->loc_EyeDirection, rsurface.localviewdirection[0], rsurface.localviewdirection[1], rsurface.localviewdirection[2]);
 		if (r_glsl_permutation->loc_Color_Pants >= 0)
 		{
 			if (rsurface.texture->pantstexture)
@@ -5636,11 +5639,7 @@ static void R_View_UpdateWithScissor(const int *myscissor)
 
 static void R_View_Update(void)
 {
-	R_Main_ResizeViewCache();
-	R_View_SetFrustum(NULL);
-	R_View_WorldVisibility(r_refdef.view.useclipplane);
-	R_View_UpdateEntityVisible();
-	R_View_UpdateEntityLighting();
+	R_View_UpdateWithScissor(NULL);
 }
 
 float viewscalefpsadjusted = 1.0f;
@@ -6179,6 +6178,17 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t
 			// update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
 			Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
 			r_refdef.view.clipplane = p->plane;
+
+			float dotProduct = DotProduct(p->plane.normal, r_refdef.view.origin);
+			float normalLength = VectorLength(p->plane.normal);
+			float planeDist = dotProduct/normalLength - p->plane.dist;
+			if(planeDist > 100)
+				r_refdef.view.clipplane.dist += 100.0;
+			else if(planeDist < -100)
+				r_refdef.view.clipplane.dist -= 100.0;
+			else
+				r_refdef.view.clipplane.dist += 0.95*planeDist;
+
 			// reverse the cullface settings for this render
 			r_refdef.view.cullface_front = GL_FRONT;
 			r_refdef.view.cullface_back = GL_BACK;
@@ -6225,6 +6235,15 @@ static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t
 			r_refdef.view.clipplane = p->plane;
 			VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
 			r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
+			float dotProduct = DotProduct(p->plane.normal, r_refdef.view.origin);
+			float normalLength = VectorLength(p->plane.normal);
+			float planeDist = dotProduct/normalLength - p->plane.dist;
+			if(planeDist > 100)
+				r_refdef.view.clipplane.dist -= 100.0;
+			else if(planeDist < -100)
+				r_refdef.view.clipplane.dist += 100.0;
+			else
+				r_refdef.view.clipplane.dist -= 0.95*planeDist;
 
 			if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
 			{
@@ -8471,6 +8490,7 @@ void RSurf_ActiveWorldEntity(void)
 	rsurface.inversematrixscale = 1;
 	R_EntityMatrix(&identitymatrix);
 	VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
+	VectorCopy(r_refdef.view.forward, rsurface.localviewdirection);
 	Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
 	rsurface.fograngerecip = r_refdef.fograngerecip;
 	rsurface.fogheightfade = r_refdef.fogheightfade;
@@ -8600,6 +8620,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q
 	rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
 	R_EntityMatrix(&rsurface.matrix);
 	Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
+	Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.forward, rsurface.localviewdirection);
 	Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
 	rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
 	rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
@@ -8850,6 +8871,7 @@ void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inve
 	rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
 	R_EntityMatrix(&rsurface.matrix);
 	Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
+	Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.forward, rsurface.localviewdirection);
 	Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
 	rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
 	rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
diff --git a/render.h b/render.h
index b91bde74..0ae68e8b 100644
--- a/render.h
+++ b/render.h
@@ -415,6 +415,8 @@ typedef struct rsurfacestate_s
 	float glowmod[3];
 	// view location in model space
 	vec3_t localvieworigin;
+	// view directoion in model space
+	vec3_t localviewdirection;
 	// polygon offset data for submodels
 	float basepolygonfactor;
 	float basepolygonoffset;
diff --git a/shader_glsl.h b/shader_glsl.h
index 1f5803c0..4b59e252 100644
--- a/shader_glsl.h
+++ b/shader_glsl.h
@@ -630,6 +630,7 @@
 "\n",
 "#ifdef FRAGMENT_SHADER\n",
 "uniform sampler2D Texture_Normal;\n",
+"uniform vec3 EyeDirection;\n",
 "uniform sampler2D Texture_Refraction;\n",
 "uniform sampler2D Texture_Reflection;\n",
 "\n",
@@ -647,10 +648,9 @@
 "\n",
 "void main(void)\n",
 "{\n",
+"   // correctly shift and scale the texture coordinates\n",
 "	vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n",
-"	//vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(dp_texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n",
 "	vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n",
-"	//SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n",
 "	// slight water animation via 2 layer scrolling (todo: tweak)\n",
 "#ifdef USEALPHAGENVERTEX\n",
 "	vec4 distort = DistortScaleRefractReflect * VertexColor.a;\n",
@@ -663,30 +663,35 @@
 "	float reflectfactor = ReflectFactor;\n",
 "	vec4 refractcolor = RefractColor;\n",
 "#endif\n",
-"	#ifdef USENORMALMAPSCROLLBLEND\n",
-"		vec3 normal = dp_texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n",
-"		normal += dp_texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n",
-"		vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * distort;\n",
-"	#else\n",
-"		vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(dp_texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * distort;\n",
-"	#endif\n",
+//"	#ifdef USENORMALMAPSCROLLBLEND\n",
+//"		vec3 normal = dp_texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n",
+//"		normal += dp_texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n",
+//"		vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * distort;\n",
+//"	#else\n",
+//"		vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(dp_texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * distort;\n",
+//"	#endif\n",
 "	// FIXME temporary hack to detect the case that the reflection\n",
 "	// gets blackened at edges due to leaving the area that contains actual\n",
 "	// content.\n",
 "	// Remove this 'ack once we have a better way to stop this thing from\n",
 "	// 'appening.\n",
-"	float f  = min(1.0, length(dp_texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n",
-"	f       *= min(1.0, length(dp_texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n",
-"	f       *= min(1.0, length(dp_texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n",
-"	f       *= min(1.0, length(dp_texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n",
-"	ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n",
-"	f  = min(1.0, length(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n",
-"	f *= min(1.0, length(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n",
-"	f *= min(1.0, length(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n",
-"	f *= min(1.0, length(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n",
-"	ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n",
-"	float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * reflectfactor + reflectoffset;\n",
-"	dp_FragColor = mix(vec4(dp_texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * refractcolor, vec4(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n",
+"   vec4 ScreenTexCoord = SafeScreenTexCoord;\n",
+"   vec3 normal = normalize(vec3(dp_texture2D(Texture_Normal, TexCoord.xy))) - vec3(0.5, 0.5, 0.5);\n",
+"   normal = normalize(normal);\n",
+"   vec3 refrNorm = normal * vec3(0.05, 0.05, 1.0);\n",
+"   vec3 reflNorm = normal * vec3(0.02, 0.02, 1.0);\n",
+"	vec4 refl = vec4(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw + reflNorm.xy).rgb, 1.0);\n",
+"	vec4 refr = vec4(dp_texture2D(Texture_Refraction, ScreenTexCoord.zw + refrNorm.xy).rgb, 1.0);\n",
+"	vec4 reflN = vec4(dp_texture2D(Texture_Reflection, ScreenTexCoord.zw - reflNorm.xy).rgb, 1.0);\n",
+"	vec4 refrN = vec4(dp_texture2D(Texture_Refraction, ScreenTexCoord.zw - refrNorm.xy).rgb, 1.0);\n",
+"	float f  = min(1.0, length(refl.rgb) / 0.0002);\n",
+"	refl = mix(reflN, refl, f);\n",
+"	f  = min(1.0, length(refr.rgb) / 0.0002);\n",
+"	refr = mix(refrN, refr, f);\n",
+"   float dotProduct = abs(dot(EyeDirection, reflNorm));\n",
+"	float Fresnel = 0.02f+max(0, 0.97f*pow((1-dotProduct),5));\n",
+"   Fresnel = clamp(Fresnel, 0.2, 0.8);\n"
+"	dp_FragColor = mix(refr, refl, Fresnel);\n",
 "}\n",
 "#endif\n",
 "#else // !MODE_WATER\n",
-- 
2.39.5