cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
+cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading"};
+cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred)"};
cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
+ SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
+ SHADERSTATICPARM_CELOUTLINE = 12, ///< celoutline (depth buffer analysis to produce outlines)
};
-#define SHADERSTATICPARMS_COUNT 11
+#define SHADERSTATICPARMS_COUNT 13
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
else if (r_shadow_shadowmappcf)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
+ else if (r_celshading.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
+ else if (r_celoutlines.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINE);
return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
}
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
}
/// information about each possible shader permutation
Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
+ Cvar_RegisterVariable(&r_celshading);
+ Cvar_RegisterVariable(&r_celoutlines);
Cvar_RegisterVariable(&r_water);
Cvar_RegisterVariable(&r_water_resolutionmultiplier);
r_shadow_prepass_width = vid.width;
r_shadow_prepass_height = vid.height;
r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
- r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER32F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
"// written by Forest 'LordHavoc' Hale\n"
"// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
"\n"
+"#ifdef USECELSHADING\n"
+"# define SHADEDIFFUSE myhalf diffuse = cast_myhalf(min(max(float(dot(surfacenormal, lightnormal)) * 2.0, 0.0), 1.0));\n"
+"# ifdef USEEXACTSPECULARMATH\n"
+"# define SHADESPECULAR(specpow) myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), eyenormal))*-1.0, 0.0)), 1.0 + specpow);specular = max(0.0, specular * 10.0 - 9.0);\n"
+"# else\n"
+"# define SHADESPECULAR(specpow) myhalf3 specularnormal = normalize(lightnormal + eyenormal);myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + specpow);specular = max(0.0, specular * 10.0 - 9.0);\n"
+"# endif\n"
+"#else\n"
+"# define SHADEDIFFUSE myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"# ifdef USEEXACTSPECULARMATH\n"
+"# define SHADESPECULAR(specpow) myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), eyenormal))*-1.0, 0.0)), 1.0 + specpow);\n"
+"# else\n"
+"# define SHADESPECULAR(specpow) myhalf3 specularnormal = normalize(lightnormal + eyenormal);myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + specpow);\n"
+"# endif\n"
+"#endif\n"
+"\n"
"#ifdef GLSL130\n"
"precision highp float;\n"
"# ifdef VERTEX_SHADER\n"
"uniform sampler2D Texture_ScreenNormalMap;\n"
"#endif\n"
"#ifdef USEDEFERREDLIGHTMAP\n"
+"#ifdef USECELOUTLINES\n"
+"uniform sampler2D Texture_ScreenNormalMap;\n"
+"#endif\n"
"uniform sampler2D Texture_ScreenDiffuse;\n"
"uniform sampler2D Texture_ScreenSpecular;\n"
"#endif\n"
" // surfacenormal = pixel normal in viewspace\n"
" // LightVector = pixel to light in viewspace\n"
" // CubeVector = pixel in lightspace\n"
-" // eyevector = pixel to view in viewspace\n"
+" // eyenormal = pixel to view direction in viewspace\n"
" vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
" myhalf fade = cast_myhalf(dp_texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
"#ifdef USEDIFFUSE\n"
" // calculate diffuse shading\n"
" myhalf3 lightnormal = cast_myhalf3(normalize(LightPosition - position));\n"
-" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"SHADEDIFFUSE\n"
"#endif\n"
"#ifdef USESPECULAR\n"
" // calculate directional shading\n"
-" vec3 eyevector = position * -1.0;\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), 1.0 + SpecularPower * normalmap.a);\n"
-"# else\n"
-" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(eyevector)));\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * normalmap.a);\n"
-"# endif\n"
+" myhalf3 eyenormal = -normalize(cast_myhalf3(position));\n"
+"SHADESPECULAR(SpecularPower * normalmap.a)\n"
"#endif\n"
"\n"
"#if defined(USESHADOWMAP2D)\n"
" diffusetex += cast_myhalf3(offsetMappedTexture2D(Texture_ReflectMask)) * cast_myhalf3(dp_textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
"#endif\n"
"\n"
+"#ifdef USESPECULAR\n"
+" myhalf3 eyenormal = normalize(cast_myhalf3(EyeVectorFogDepth.xyz));\n"
+"#endif\n"
+"\n"
"\n"
"\n"
"\n"
" // light source\n"
"#ifdef USEDIFFUSE\n"
" myhalf3 lightnormal = cast_myhalf3(normalize(LightVector));\n"
-" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"SHADEDIFFUSE\n"
" color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
"#ifdef USESPECULAR\n"
-"#ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"#else\n"
-" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"#endif\n"
+"SHADESPECULAR(SpecularPower * glosstex.a)\n"
" color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
"#endif\n"
"#else\n"
"\n"
"#ifdef SHADING\n"
"# ifdef USEDIFFUSE\n"
-" myhalf diffuse = cast_myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
+"SHADEDIFFUSE\n"
"# ifdef USESPECULAR\n"
-"# ifdef USEEXACTSPECULARMATH\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVectorFogDepth.xyz)))*-1.0, 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"# else\n"
-" myhalf3 specularnormal = normalize(lightnormal + cast_myhalf3(normalize(EyeVectorFogDepth.xyz)));\n"
-" myhalf specular = pow(cast_myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), 1.0 + SpecularPower * glosstex.a);\n"
-"# endif\n"
+"SHADESPECULAR(SpecularPower * glosstex.a)\n"
" color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
"# else\n"
" color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
"#endif\n"
"#endif\n"
"\n"
+"#ifdef USECELOUTLINES\n"
+"# ifdef USEDEFERREDLIGHTMAP\n"
+"// vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
+" vec4 ScreenTexCoordStep = vec4(PixelToScreenTexCoord.x, 0.0, 0.0, PixelToScreenTexCoord.y);\n"
+" vec4 DepthNeighbors;\n"
+" float DepthCenter = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord).b;\n"
+" DepthNeighbors.x = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord - ScreenTexCoordStep.xy).b;\n"
+" DepthNeighbors.y = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + ScreenTexCoordStep.xy).b;\n"
+" DepthNeighbors.z = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord + ScreenTexCoordStep.zw).b;\n"
+" DepthNeighbors.w = dp_texture2D(Texture_ScreenNormalMap, ScreenTexCoord - ScreenTexCoordStep.zw).b;\n"
+" float DepthAverage = dot(DepthNeighbors, vec4(0.25, 0.25, 0.25, 0.25));\n"
+" float DepthDelta = abs(dot(DepthNeighbors.xy, vec2(-1.0, 1.0))) + abs(dot(DepthNeighbors.zw, vec2(-1.0, 1.0)));\n"
+"// color.rgb = vec3(1.0, 1.0, 1.0);\n"
+" color.rgb *= max(0.25, 1.0 - max(0.0, abs(DepthCenter - DepthAverage) - 0.07 * DepthDelta) / (0.03 + 0.03 * DepthDelta));\n"
+"// color.rgb *= step(abs(DepthCenter - DepthAverage), 0.2 * DepthDelta);\n"
+"# endif\n"
+"#endif\n"
+"\n"
"#ifdef USEFOG\n"
" color.rgb = FogVertex(color);\n"
"#endif\n"