cvar_t r_water_scissormode = {CVAR_CLIENT, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
cvar_t r_water_lowquality = {CVAR_CLIENT, "r_water_lowquality", "0", "special option to accelerate water rendering: 1 disables all dynamic lights, 2 disables particles too"};
cvar_t r_water_hideplayer = {CVAR_CLIENT | CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
+cvar_t r_water_clipplayerinreflection = {CVAR_CLIENT | CVAR_SAVE, "r_water_clipplayerinreflection", "-1", "if set to -1 the player will not be clipped in the reflection view, else it will be clipped at the given value"};
cvar_t r_lerpsprites = {CVAR_CLIENT | CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
cvar_t r_lerpmodels = {CVAR_CLIENT | CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
int loc_DeferredMod_Specular;
int loc_DistortScaleRefractReflect;
int loc_EyePosition;
+ int loc_EyeDirection;
int loc_FogColor;
int loc_FogHeightFade;
int loc_FogPlane;
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");
if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->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 (t->pantstexture)
Cvar_RegisterVariable(&r_water_scissormode);
Cvar_RegisterVariable(&r_water_lowquality);
Cvar_RegisterVariable(&r_water_hideplayer);
+ Cvar_RegisterVariable(&r_water_clipplayerinreflection);
Cvar_RegisterVariable(&r_lerpsprites);
Cvar_RegisterVariable(&r_lerpmodels);
static void R_View_Update(void)
{
- R_Main_ResizeViewCache();
- R_View_SetFrustum(NULL);
- R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
- R_View_UpdateEntityVisible();
+ R_View_UpdateWithScissor(NULL);
}
float viewscalefpsadjusted = 1.0f;
r_waterstate_waterplane_t *p;
vec3_t visorigin;
r_rendertarget_t *rt;
+ float dotProduct, normalLength, planeDist;
originalview = r_refdef.view;
r_refdef.view.clipplane = p->plane;
// reflected view origin may be in solid, so don't cull with it
r_refdef.view.usevieworiginculling = false;
+
+ dotProduct = DotProduct(p->plane.normal, r_refdef.view.origin);
+ normalLength = VectorLength(p->plane.normal);
+ 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;
memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
}
- r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
+ r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer) || (abs(planeDist) < r_water_clipplayerinreflection.value);
R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
GL_ScissorTest(false);
R_ClearScreen(r_refdef.fogenabled);
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;
+ dotProduct = DotProduct(p->plane.normal, r_refdef.view.origin);
+ normalLength = VectorLength(p->plane.normal);
+ 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)
{
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 = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
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;
"\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",
"\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",
" 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",