From 60735ece67a401288eb8f3cf957f726f9011b964 Mon Sep 17 00:00:00 2001 From: vortex Date: Wed, 13 Oct 2010 20:57:26 +0000 Subject: [PATCH] add r_glsl_saturation_redcompensate optional effect to r_glsl_saturate (only works when saturate is below 1), will produce desaturation with red channel compensated. Tweaked water shader parms, added slight water animation by counter-scrolling 2 water normalmap layers in shader. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10529 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 111 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 32 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index fef8f77c..42758cf9 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -189,6 +189,7 @@ cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspectiv cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"}; cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"}; +cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"}; cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"}; @@ -749,8 +750,16 @@ static const char *builtinshaderstring = "#ifdef USESATURATION\n" " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n" " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n" -" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n" -" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" +" // 'vampire sight' effect, wheres red is compensated\n" +" #ifdef SATURATION_REDCOMPENSATE\n" +" float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n" +" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" +" gl_FragColor.r += rboost;\n" +" #else\n" +" // normal desaturation\n" +" //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n" +" gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" +" #endif\n" "#endif\n" "\n" "#ifdef USEGAMMARAMPS\n" @@ -933,6 +942,7 @@ static const char *builtinshaderstring = "uniform vec4 ReflectColor;\n" "uniform float ReflectFactor;\n" "uniform float ReflectOffset;\n" +"uniform float ClientTime;\n" "\n" "void main(void)\n" "{\n" @@ -940,24 +950,28 @@ static const char *builtinshaderstring = " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(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" -" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n" +" // slight water animation via 2 layer scrolling (todo: tweak)\n" +" vec3 normal = texture2D(Texture_Normal, TexCoord + vec2(0.08, 0.08)*ClientTime*0.5).rgb - vec3(1.0);\n" +" normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime)*0.75).rgb;\n" +" vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\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(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n" -" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n" -" f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n" -" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n" +" float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n" +" f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n" +" f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n" +" f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n" +" ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n" +" float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n" +" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n" +" f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n" +" f *= min(1.0, length(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" " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n" +" gl_FragColor.a = f1 + 0.5;\n" "}\n" "#endif\n" "#else // !MODE_WATER\n" @@ -1991,8 +2005,16 @@ const char *builtincgshaderstring = "#ifdef USESATURATION\n" " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n" " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n" -" //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n" -" gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n" +" // 'vampire sight' effect, wheres red is compensated\n" +" #ifdef SATURATION_REDCOMPENSATE\n" +" float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n" +" gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n" +" gl_FragColor.r += r;\n" +" #else\n" +" // normal desaturation\n" +" //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n" +" gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n" +" #endif\n" "#endif\n" "\n" "#ifdef USEGAMMARAMPS\n" @@ -3552,6 +3574,21 @@ r_glsl_permutation_t; #define SHADERPERMUTATION_HASHSIZE 256 +// this called both on R_GLSL_CompileShader and R_HLSL_CacheShader +// this function adds more "#define" to supply static parms, could be used by game-specific code part +int vertstrings_count = 0; +int geomstrings_count = 0; +int fragstrings_count = 0; +const char *vertstrings_list[64+3]; +const char *geomstrings_list[64+3]; +const char *fragstrings_list[64+3]; +void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation) +{ + if (mode == SHADERMODE_POSTPROCESS && (permutation & SHADERPERMUTATION_SATURATION)) + if (r_glsl_saturation_redcompensate.integer) + fragstrings_list[fragstrings_count++] = "#define SATURATION_REDCOMPENSATE\n"; +} + /// information about each possible shader permutation r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE]; /// currently selected permutation @@ -3617,13 +3654,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode { int i; shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode; - int vertstrings_count = 0; - int geomstrings_count = 0; - int fragstrings_count = 0; char *vertexstring, *geometrystring, *fragmentstring; - const char *vertstrings_list[32+3]; - const char *geomstrings_list[32+3]; - const char *fragstrings_list[32+3]; char permutationname[256]; if (p->compiled) @@ -3640,6 +3671,9 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode // the first pretext is which type of shader to compile as // (later these will all be bound together as a program object) + vertstrings_count = 0; + geomstrings_count = 0; + fragstrings_count = 0; vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n"; geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n"; fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n"; @@ -3669,6 +3703,9 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode } } + // add static parms + R_CompileShader_AddStaticParms(mode, permutation); + // now append the shader text itself vertstrings_list[vertstrings_count++] = vertexstring; geomstrings_list[geomstrings_count++] = geometrystring; @@ -4039,15 +4076,12 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un { int i; shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode; - int vertstrings_count = 0, vertstring_length = 0; - int geomstrings_count = 0, geomstring_length = 0; - int fragstrings_count = 0, fragstring_length = 0; + int vertstring_length = 0; + int geomstring_length = 0; + int fragstring_length = 0; char *t; char *vertexstring, *geometrystring, *fragmentstring; char *vertstring, *geomstring, *fragstring; - const char *vertstrings_list[32+3]; - const char *geomstrings_list[32+3]; - const char *fragstrings_list[32+3]; char permutationname[256]; char cachename[256]; CGprofile vertexProfile; @@ -4070,6 +4104,9 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un // the first pretext is which type of shader to compile as // (later these will all be bound together as a program object) + vertstrings_count = 0; + geomstrings_count = 0; + fragstrings_count = 0; vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n"; geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n"; fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n"; @@ -4101,6 +4138,9 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un } } + // add static parms + R_CompileShader_AddStaticParms(mode, permutation); + // replace spaces in the cachename with _ characters for (i = 0;cachename[i];i++) if (cachename[i] == ' ') @@ -4659,15 +4699,12 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode { int i; shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode; - int vertstrings_count = 0, vertstring_length = 0; - int geomstrings_count = 0, geomstring_length = 0; - int fragstrings_count = 0, fragstring_length = 0; + int vertstring_length = 0; + int geomstring_length = 0; + int fragstring_length = 0; char *t; char *vertexstring, *geometrystring, *fragmentstring; char *vertstring, *geomstring, *fragstring; - const char *vertstrings_list[32+3]; - const char *geomstrings_list[32+3]; - const char *fragstrings_list[32+3]; char permutationname[256]; char cachename[256]; @@ -4687,12 +4724,18 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode strlcat(cachename, "hlsl/", sizeof(cachename)); // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler + vertstrings_count = 0; + geomstrings_count = 0; + fragstrings_count = 0; vertstrings_list[vertstrings_count++] = "#define HLSL\n"; geomstrings_list[geomstrings_count++] = "#define HLSL\n"; fragstrings_list[fragstrings_count++] = "#define HLSL\n"; // the first pretext is which type of shader to compile as // (later these will all be bound together as a program object) + vertstrings_count = 0; + geomstrings_count = 0; + fragstrings_count = 0; vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n"; geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n"; fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n"; @@ -4724,6 +4767,9 @@ static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode } } + // add static parms + R_CompileShader_AddStaticParms(mode, permutation); + // replace spaces in the cachename with _ characters for (i = 0;cachename[i];i++) if (cachename[i] == ' ') @@ -7307,6 +7353,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&gl_lightmaps); Cvar_RegisterVariable(&r_test); Cvar_RegisterVariable(&r_glsl_saturation); + Cvar_RegisterVariable(&r_glsl_saturation_redcompensate); Cvar_RegisterVariable(&r_framedatasize); if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE) Cvar_SetValue("r_fullbrights", 0); -- 2.39.2