added indirection cube map for shadowmapping and revised filtering modes
authoreihrul <eihrul@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 30 Sep 2009 06:00:37 +0000 (06:00 +0000)
committereihrul <eihrul@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 30 Sep 2009 06:00:37 +0000 (06:00 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9255 d7cf8633-e32d-0410-b094-e92efae38249

gl_rmain.c
gl_textures.c
glquake.h
r_shadow.c
r_textures.h
render.h

index f98be95..473635b 100644 (file)
@@ -449,9 +449,14 @@ static const char *builtinshaderstring =
 "// written by Forest 'LordHavoc' Hale\n"
 "#ifdef USESHADOWMAPRECT\n"
 "#extension GL_ARB_texture_rectangle : enable\n"
-"#endif\n"
-"#ifdef USESHADOWMAPCUBE\n"
-"#extension GL_EXT_gpu_shader4 : enable\n"
+"# ifdef HASTEXTUREGATHER\n"
+"#   extension GL_ARB_texture_gather : enable\n"
+"# else\n"
+"#   ifdef HASTEXTURE4\n"
+"#     extension GL_AMD_texture_texture4 : enable\n"
+"#     define textureGather texture4\n"
+"#   endif\n"
+"# endif\n"
 "#endif\n"
 "\n"
 "// common definitions between vertex shader and fragment shader:\n"
@@ -459,7 +464,7 @@ static const char *builtinshaderstring =
 "//#ifdef __GLSL_CG_DATA_TYPES\n"
 "//# define myhalf half\n"
 "//# define myhalf2 half2\n"
-"//# define myhalf3 half3\n"
+"//# define myhalf3half3\n"
 "//# define myhalf4 half4\n"
 "//#else\n"
 "# define myhalf float\n"
@@ -554,7 +559,7 @@ static const char *builtinshaderstring =
 "      //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
 "      myhalf 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" // TODO: test this on ATI
+"      gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
 "#endif\n"
 "\n"
 "#ifdef USEGAMMARAMPS\n"
@@ -761,32 +766,15 @@ static const char *builtinshaderstring =
 "uniform samplerCube Texture_Cube;\n"
 "\n"
 "#define showshadowmap 0\n"
-"#define useshadowsamplerrect 0\n"
-"#define useshadowsampler2d 0\n"
-"#define useshadowsamplercube 1\n"
 "\n"
 "#ifdef USESHADOWMAPRECT\n"
-"# if useshadowsamplerrect\n"
+"# ifdef USESHADOWSAMPLER\n"
 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
 "# else\n"
 "uniform sampler2DRect Texture_ShadowMapRect;\n"
 "# endif\n"
-"#endif\n"
 "\n"
-"#ifdef USESHADOWMAP2D\n"
-"# if useshadowsampler2d\n"
-"uniform sampler2DShadow Texture_ShadowMap2D;\n"
-"# else\n"
-"uniform sampler2D Texture_ShadowMap2D;\n"
-"# endif\n"
-"#endif\n"
-"\n"
-"#ifdef USESHADOWMAPCUBE\n"
-"# if useshadowsamplercube\n"
-"uniform samplerCubeShadow Texture_ShadowMapCube;\n"
-"# else\n"
-"uniform samplerCube Texture_ShadowMapCube;\n"
-"# endif\n"
+"uniform samplerCube Texture_CubeProjection;\n"
 "#endif\n"
 "\n"
 "uniform myhalf3 LightColor;\n"
@@ -884,59 +872,51 @@ static const char *builtinshaderstring =
 "}\n"
 "#endif // USEOFFSETMAPPING\n"
 "\n"
-"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
-"//float ShadowMap_TextureSize = 1024.0;\n"
-"//float ShadowMap_BorderSize = 6.0;\n"
-"//float ShadowMap_NearClip = 0.0001;\n"
-"//float ShadowMap_FarClip = 1.0;\n"
-"//float ShadowMap_Bias = ShadowMap_NearClip * 64.0 / ShadowMap_TextureSize;\n"
-"//vec2 ShadowMap_TextureScale = vec2(0.5, 0.25);\n"
-"//vec4 ShadowMap_Parameters = vec3(1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, 1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, -(ShadowMap_FarClip + ShadowMap_NearClip) / (ShadowMap_FarClip - ShadowMap_NearClip), -2.0 * ShadowMap_NearClip * ShadowMap_FarClip / (ShadowMap_FarClip - ShadowMap_NearClip));\n"
-"uniform float ShadowMap_Bias;\n"
-"uniform vec2 ShadowMap_TextureScale;\n"
+"#ifdef USESHADOWMAPRECT \n"
+"uniform vec4 ShadowMap_TextureScale;\n"
+"#if 0\n"
 "uniform vec4 ShadowMap_Parameters;\n"
 "#endif\n"
 "\n"
-"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
 "vec3 GetShadowMapTC2D(vec3 dir)\n"
 "{\n"
 "      vec3 adir = abs(dir);\n"
-"      vec3 tc;\n"
-"      vec3 offset;\n"
-"# if 1\n"
-"      float d;\n"
+"# if 0\n"
+"      vec2 tc;\n"
+"      vec2 offset;\n"
+"      float ma;\n"
 "      if (adir.x > adir.y)\n"
 "      {\n"
 "              if (adir.x > adir.z)\n"
 "              {\n"
-"                      d = 0.5 / adir.x;\n"
+"                      ma = adir.x;\n"
 "                      if (dir.x >= 0.0)\n"
 "                      {\n"
 "                              // +X\n"
-"                              tc = vec3(-dir.z, -dir.y, -dir.x);\n"
-"                              offset = vec3(0.5, 0.5, 0.5);\n"
+"                              tc = vec2(-dir.z, -dir.y);\n"
+"                              offset = vec2(0.5, 0.5);\n"
 "                      }\n"
 "                      else\n"
 "                      {\n"
 "                              // -X\n"
-"                              tc = vec3( dir.z, -dir.y,  dir.x);\n"
-"                              offset = vec3(1.5, 0.5, 0.5);\n"
+"                              tc = vec2( dir.z, -dir.y);\n"
+"                              offset = vec2(1.5, 0.5);\n"
 "                      }\n"
 "              }\n"
 "              else\n"
 "              {\n"
-"                      d = 0.5 / adir.z;\n"
+"            ma = adir.z;\n"
 "                      if (dir.z >= 0.0)\n"
 "                      {\n"
 "                              // +Z\n"
-"                              tc = vec3( dir.x, -dir.y, -dir.z);\n"
-"                              offset = vec3(0.5, 2.5, 0.5);\n"
+"                              tc = vec2( dir.x, -dir.y);\n"
+"                              offset = vec2(0.5, 2.5);\n"
 "                      }\n"
 "                      else\n"
 "                      {\n"
 "                              // -Z\n"
-"                              tc = vec3(-dir.x, -dir.y,  dir.z);\n"
-"                              offset = vec3(1.5, 2.5, 0.5);\n"
+"                              tc = vec2(-dir.x, -dir.y);\n"
+"                              offset = vec2(1.5, 2.5);\n"
 "                      }\n"
 "              }\n"
 "      }\n"
@@ -944,69 +924,45 @@ static const char *builtinshaderstring =
 "      {\n"
 "              if (adir.y > adir.z)\n"
 "              {\n"
-"                      d = 0.5 / adir.y;\n"
+"            ma = adir.y;\n"
 "                      if (dir.y >= 0.0)\n"
 "                      {\n"
 "                              // +Y\n"
-"                              tc = vec3( dir.x,  dir.z, -dir.y);\n"
-"                              offset = vec3(0.5, 1.5, 0.5);\n"
+"                              tc = vec2( dir.x,  dir.z);\n"
+"                              offset = vec2(0.5, 1.5);\n"
 "                      }\n"
 "                      else\n"
 "                      {\n"
 "                              // -Y\n"
-"                              tc = vec3( dir.x, -dir.z, dir.y);\n"
-"                              offset = vec3(1.5, 1.5, 0.5);\n"
+"                              tc = vec2( dir.x, -dir.z);\n"
+"                              offset = vec2(1.5, 1.5);\n"
 "                      }\n"
 "              }\n"
 "              else\n"
 "              {\n"
-"                      d = 0.5 / adir.z;\n"
+"            ma = adir.z;\n"
 "                      if (dir.z >= 0.0)\n"
 "                      {\n"
 "                              // +Z\n"
-"                              tc = vec3(dir.x, -dir.y, -dir.z);\n"
-"                              offset = vec3(0.5, 2.5, 0.5);\n"
+"                              tc = vec2(dir.x, -dir.y);\n"
+"                              offset = vec2(0.5, 2.5);\n"
 "                      }\n"
 "                      else\n"
 "                      {\n"
 "                              // -Z\n"
-"                              tc = vec3(-dir.x, -dir.y, dir.z);\n"
-"                              offset = vec3(1.5, 2.5, 0.5);\n"
+"                              tc = vec2(-dir.x, -dir.y);\n"
+"                              offset = vec2(1.5, 2.5);\n"
 "                      }\n"
 "              }\n"
 "      }\n"
-"      tc = tc * ShadowMap_Parameters.xyz * d + offset;\n"
-"      tc.xy *= ShadowMap_TextureScale;\n"
-"      tc.z += ShadowMap_Parameters.w * d - ShadowMap_Bias * d;\n"
-"# else\n"
-"      // experimental method by eihrul, needs overhaul\n"
-"      vec3 ma = vec3(0.0, 0.0, 1.0);\n"
-"      if (adir.x > adir.y)\n"
-"      {\n"
-"              if (adir.x > adir.z)\n"
-"                      ma = vec3(1.0, 0.0, 0.0);\n"
-"      }\n"
-"      else if (adir.y > adir.z)\n"
-"              ma = vec3(0.0, 1.0, 0.0);\n"
 "\n"
-"      tc.xy = dir.xy - ma.xy*(dir.xy - dir.z);\n"
-"      tc.xy = (tc.xy/dot(ma, dir))*0.5 + 0.5;\n"
-"      tc.z = dot(ma, adir);\n"
-"      tc.xy = (tc.xy * tcscale + offset) * vec2(0.5, 0.25);\n"
+"      return vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
+"# else\n"
+"    return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_TextureScale.xy, ShadowMap_TextureScale.z + ShadowMap_TextureScale.w / max(max(adir.x, adir.y), adir.z));\n"
 "# endif\n"
-"      return tc;\n"
 "}\n"
 "\n"
-"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
-"\n"
-"#ifdef USESHADOWMAPCUBE\n"
-"vec4 GetShadowMapTCCube(vec3 dir)\n"
-"{\n"
-"      vec3 adir = abs(dir);\n"
-"      float sidedist = max(adir.x, max(adir.y, adir.z));\n"
-"      return vec4(dir, 0.5 - 0.5 * (ShadowMap_Parameters.z - (-ShadowMap_Bias + ShadowMap_Parameters.w) / sidedist));\n"
-"}\n"
-"#endif\n"
+"#endif // USESHADOWMAPRECT\n"
 "\n"
 "#if !showshadowmap\n"
 "# ifdef USESHADOWMAPRECT\n"
@@ -1014,43 +970,80 @@ static const char *builtinshaderstring =
 "{\n"
 "      vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
 "      float f;\n"
-"#  if useshadowsamplerrect\n"
-"      f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).a;\n"
-"#  else\n"
-"      f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
-"#  endif\n"
-"      return f;\n"
-"}\n"
-"# endif\n"
+"#  ifdef USESHADOWSAMPLER\n"
+"\n"
+"#    ifdef USESHADOWMAPPCF\n"
+"      f = dot(vec4(0.25),\n"
+"                      vec4(shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-0.4,  1.0, 0.0)).r,\n"
+"                               shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-1.0, -0.4, 0.0)).r,\n"
+"                               shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 0.4, -1.0, 0.0)).r,\n"
+"                               shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 1.0,  0.4, 0.0)).r));\n"
+"#    else\n"
+"    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
+"#    endif\n"
 "\n"
-"# ifdef USESHADOWMAP2D\n"
-"float ShadowMapCompare(vec3 dir)\n"
-"{\n"
-"      vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
-"      float f;\n"
-"#  if useshadowsampler2d\n"
-"      f = shadow2D(Texture_ShadowMap2D, shadowmaptc).a;\n"
 "#  else\n"
-"      f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
-"#  endif\n"
-"      return f;\n"
-"}\n"
-"# endif\n"
 "\n"
-"# ifdef USESHADOWMAPCUBE\n"
-"float ShadowMapCompare(vec3 dir)\n"
-"{\n"
-"      // apply depth texture cubemap as light filter\n"
-"      vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
-"      float f;\n"
-"#  if useshadowsamplercube\n"
-"      f = shadowCube(Texture_ShadowMapCube, shadowmaptc).a;\n"
-"#  else\n"
-"      f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
+"#    ifdef USESHADOWMAPPCF\n"
+"#      if defined(HASTEXTUREGATHER) || defined(HASTEXTURE4)\n"
+"    vec2 offset = fract(shadowmaptc.xy - 0.5);\n"
+"    vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0))),\n"
+"         group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0))),\n"
+"         group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0,  1.0))),\n"
+"         group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0,  1.0))),\n"
+"         cols = vec4(group1.ab, group2.ab) + vec4(group3.rg, group4.rg) +\n"
+"                mix(vec4(group1.rg, group2.rg), vec4(group3.ab, group4.ab), offset.y);\n"
+"    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"#      elif 1\n"
+"    vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
+"    vec4 row1 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, -1.0)).r)),\n"
+"         row2 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0,  0.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0,  0.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0,  0.0)).r)),\n"
+"         row3 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0,  1.0)).r)),\n"
+"         row4 = step(shadowmaptc.z,\n"
+"                    vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0,  2.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0,  2.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0,  2.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0,  2.0)).r)),\n"
+"         cols = row2 + row3 + mix(row1, row4, offset.y);\n"
+"    f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
+"#      else\n"
+"    vec2 offset = fract(shadowmaptc.xy);\n"
+"    vec3 row1 = step(shadowmaptc.z,\n"
+"                    vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, -1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0)).r)),\n"
+"         row2 = step(shadowmaptc.z,\n"
+"                    vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0,  0.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0,  0.0)).r)),\n"
+"         row3 = step(shadowmaptc.z,\n"
+"                    vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0,  1.0)).r,\n"
+"                         texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0,  1.0)).r)),\n"
+"         cols = row2 + mix(row1, row3, offset.y);\n"
+"    f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
+"#      endif\n"
+"#    else\n"
+"    f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
+"#    endif\n"
+"\n"
 "#  endif\n"
 "      return f;\n"
 "}\n"
 "# endif\n"
+"\n"
 "#endif\n"
 "\n"
 "\n"
@@ -1189,7 +1182,7 @@ static const char *builtinshaderstring =
 "#  endif\n"
 "# endif\n"
 "\n"
-"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
+"#ifdef USESHADOWMAPRECT\n"
 "#if !showshadowmap\n"
 "      color.rgb *= ShadowMapCompare(CubeVector);\n"
 "#endif\n"
@@ -1358,28 +1351,12 @@ static const char *builtinshaderstring =
 "\n"
 "#if showshadowmap\n"
 "# ifdef USESHADOWMAPRECT\n"
-"#  if useshadowsamplerrect\n"
+"#  ifdef USESHADOWSAMPLER\n"
 "      gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
 "#  else\n"
 "      gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
 "#  endif\n"
 "# endif\n"
-"\n"
-"# ifdef USESHADOWMAP2D\n"
-"#  if useshadowsampler2d\n"
-"      gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
-"#  else\n"
-"      gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
-"#  endif\n"
-"# endif\n"
-"\n"
-"# ifdef USESHADOWMAPCUBE\n"
-"#  if useshadowsamplercube\n"
-"      gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
-"#  else\n"
-"      gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
-"#  endif\n"
-"# endif\n"
 "#endif\n"
 "}\n"
 "#endif // !MODE_REFRACTION\n"
@@ -1429,8 +1406,8 @@ typedef enum shaderpermutation_e
        SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
        SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
        SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
-       SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
-       SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
+       SHADERPERMUTATION_SHADOWMAPPCF = 1<<12, //< (lightsource) use percentage closer filtering on shadowmap test results
+       SHADERPERMUTATION_SHADOWSAMPLER = 1<<13, //< (lightsource) use hardware shadowmap test
        SHADERPERMUTATION_LIMIT = 1<<14, ///< size of permutations array
        SHADERPERMUTATION_COUNT = 14 ///< size of shaderpermutationinfo array
 }
@@ -1451,8 +1428,8 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
        {"#define USEOFFSETMAPPING\n", " offsetmapping"},
        {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
        {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
-       {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
-       {"#define USESHADOWMAP2D\n", " shadowmap2d"},
+       {"#define USESHADOWMAPPCF\n", " shadowmappcf"},
+       {"#define USESHADOWSAMPLER\n", " shadowsampler"},
 };
 
 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
@@ -1521,8 +1498,7 @@ typedef struct r_glsl_permutation_s
        int loc_Texture_Refraction;
        int loc_Texture_Reflection;
        int loc_Texture_ShadowMapRect;
-       int loc_Texture_ShadowMapCube;
-       int loc_Texture_ShadowMap2D;
+       int loc_Texture_CubeProjection;
        int loc_FogColor;
        int loc_LightPosition;
        int loc_EyePosition;
@@ -1557,7 +1533,6 @@ typedef struct r_glsl_permutation_s
        int loc_ClientTime;
        int loc_PixelSize;
        int loc_Saturation;
-       int loc_ShadowMap_Bias;
        int loc_ShadowMap_TextureScale;
        int loc_ShadowMap_Parameters;
 }
@@ -1688,8 +1663,7 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio
                p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
                p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
                p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
-               p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
-               p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
+               p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");  
                p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
                p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
                p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
@@ -1724,7 +1698,6 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio
                p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
                p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
                p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
-               p->loc_ShadowMap_Bias             = qglGetUniformLocationARB(p->program, "ShadowMap_Bias");
                p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
                p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
                // initialize the samplers to refer to the texture units we use
@@ -1749,8 +1722,7 @@ static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutatio
                if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
                if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
                if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
-               if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
-               if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
+               if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
                CHECKGLERROR
                if (developer.integer)
                        Con_Printf("GLSL shader %s compiled.\n", permutationname);
@@ -1908,12 +1880,11 @@ void R_SetupShowDepthShader(void)
 extern rtexture_t *r_shadow_attenuationgradienttexture;
 extern rtexture_t *r_shadow_attenuation2dtexture;
 extern rtexture_t *r_shadow_attenuation3dtexture;
-extern qboolean r_shadow_usingshadowmaprect;
-extern qboolean r_shadow_usingshadowmapcube;
-extern qboolean r_shadow_usingshadowmap2d;
 extern float r_shadow_shadowmap_bias;
-extern float r_shadow_shadowmap_texturescale[2];
+extern float r_shadow_shadowmap_texturescale[4];
 extern float r_shadow_shadowmap_parameters[4];
+extern int r_shadow_shadowmode;
+extern int r_shadow_shadowmapfilter;
 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
 {
        // select a permutation of the lighting shader appropriate to this
@@ -1953,12 +1924,14 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                        permutation |= SHADERPERMUTATION_FOG;
                if (rsurface.texture->colormapping)
                        permutation |= SHADERPERMUTATION_COLORMAPPING;
-               if (r_shadow_usingshadowmaprect)
+               if (r_shadow_shadowmode)
                        permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
-               if (r_shadow_usingshadowmapcube)
-                       permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
-               if (r_shadow_usingshadowmap2d)
-                       permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+               if (r_shadow_shadowmapfilter == 3)
+                       permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
+               else if (r_shadow_shadowmapfilter == 2)
+                       permutation |= SHADERPERMUTATION_SHADOWMAPPCF | SHADERPERMUTATION_SHADOWSAMPLER;
+               else if (r_shadow_shadowmapfilter == 1)
+                       permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
        }
        else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
        {
@@ -2082,8 +2055,7 @@ void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, f
                // additive passes are only darkened by fog, not tinted
                if (r_glsl_permutation->loc_FogColor >= 0)
                        qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
-               if (r_glsl_permutation->loc_ShadowMap_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_ShadowMap_Bias, r_shadow_shadowmap_bias);
-               if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
+               if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1], r_shadow_shadowmap_texturescale[2], r_shadow_shadowmap_texturescale[3]);
                if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
        }
        else
index ad082d1..3cd9df6 100644 (file)
@@ -61,6 +61,7 @@ static textypeinfo_t textype_bgra_alpha             = {TEXTYPE_BGRA   , 4, 4, 4.
 static textypeinfo_t textype_bgra_compress          = {TEXTYPE_BGRA   , 4, 4, 0.5f, GL_BGRA   , GL_COMPRESSED_RGB_ARB, GL_UNSIGNED_BYTE};
 static textypeinfo_t textype_bgra_alpha_compress    = {TEXTYPE_BGRA   , 4, 4, 1.0f, GL_BGRA   , GL_COMPRESSED_RGBA_ARB, GL_UNSIGNED_BYTE};
 static textypeinfo_t textype_shadowmap              = {TEXTYPE_SHADOWMAP,4,4, 4.0f, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24_ARB, GL_UNSIGNED_INT};
+static textypeinfo_t textype_projection             = {TEXTYPE_PROJECTION,4,4,4.0f, GL_LUMINANCE_ALPHA, GL_LUMINANCE16_ALPHA16, GL_UNSIGNED_SHORT};
 
 typedef enum gltexturetype_e
 {
@@ -218,6 +219,8 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
                                return &textype_bgra;
                        case TEXTYPE_SHADOWMAP:
                                return &textype_shadowmap;
+                       case TEXTYPE_PROJECTION:
+                               return &textype_projection;
                        default:
                                Host_Error("R_GetTexTypeInfo: unknown texture format");
                                return NULL;
@@ -782,15 +785,17 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet
 
        if (textype == TEXTYPE_SHADOWMAP)
        {
-#if 1
-               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
-               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
-               qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);CHECKGLERROR
-#else
-               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
-               qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_ALWAYS);CHECKGLERROR
+               if (flags & TEXF_COMPARE)
+               {
+                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
+                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
+               }
+               else
+               {
+                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
+                       qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_ALWAYS);CHECKGLERROR
+               }
                qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);CHECKGLERROR
-#endif
        }
 
        CHECKGLERROR
@@ -1059,6 +1064,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden
                }
                break;
        case TEXTYPE_SHADOWMAP:
+       case TEXTYPE_PROJECTION:
                break;
        default:
                Host_Error("R_LoadTexture: unknown texture type");
@@ -1126,24 +1132,43 @@ rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *ident
        return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
 }
 
-rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height)
-{
-       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_FORCENEAREST | TEXF_CLAMP, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
-}
-
-rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width)
+rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
+       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
 }
 
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height)
+rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier, int size, int border)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_ALWAYSPRECACHE | TEXF_FORCENEAREST | TEXF_CLAMP, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
-}
-
-rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier)
-{
-       return R_SetupTexture(rtexturepool, identifier, 2, 2, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, TEXTYPE_BGRA, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
+    // maps to a 2x3 texture rectangle with normalized coordinates (must be scaled by size after lookup)
+    // +-
+    // XX
+    // YY
+    // ZZ
+    rtexture_t *projection;
+       unsigned short *data, *texel;
+       unsigned int sizebits = 0, stepbits = 0, res, i, j, k;
+       while ((1 << sizebits) < size) sizebits++;
+       while ((1 << stepbits) <= border) stepbits++;
+    stepbits = min(stepbits, sizebits);
+       res = size>>stepbits;
+       stepbits += 16 - sizebits - 1;
+       data = (unsigned short *)Mem_Alloc(texturemempool, 2*sizeof(unsigned short)*res*res*6);
+       texel = data;
+       for (i = 0;i < 6;i++) 
+       {
+               unsigned int x = (i&1)<<16, y = (i>>1)<<16;
+               for (j = 0;j < res;j++)
+               {
+                       for (k = 0;k < res;k++)
+                       {
+                               *texel++ = (x + ((2*k + 1)<<stepbits))/2;
+                               *texel++ = (y + ((2*j + 1)<<stepbits))/3;
+                       }
+               }
+       }
+       projection = R_SetupTexture(rtexturepool, identifier, res, res, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, TEXTYPE_PROJECTION, GLTEXTURETYPE_CUBEMAP, (unsigned char *)data, NULL);
+       Mem_Free(data);
+    return projection;
 }
 
 int R_TextureHasAlpha(rtexture_t *rt)
index c865060..fb7a833 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -949,6 +949,10 @@ extern void (GLAPIENTRY *qglGetQueryObjectuivARB)(GLuint qid, GLenum pname, GLui
 // GL_EXT_bgra
 #define GL_BGRA                                        0x80E1
 
+// GL_EXT_texture
+#define GL_LUMINANCE_ALPHA                0x190A
+#define GL_LUMINANCE16_ALPHA16            0x8048
+
 #define DEBUGGL
 
 #ifdef DEBUGGL
index 65a54f7..d992a76 100644 (file)
@@ -168,19 +168,15 @@ r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
-qboolean r_shadow_usingshadowmaprect;
-qboolean r_shadow_usingshadowmap2d;
-qboolean r_shadow_usingshadowmapcube;
-float r_shadow_shadowmap_bias;
-float r_shadow_shadowmap_texturescale[2];
+float r_shadow_shadowmap_texturescale[4];
 float r_shadow_shadowmap_parameters[4];
 int r_shadow_drawbuffer;
 int r_shadow_readbuffer;
 GLuint r_shadow_fborectangle;
-GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS][6];
-GLuint r_shadow_fbo2d;
 int r_shadow_shadowmode;
 int r_shadow_shadowmapmaxsize;
+int r_shadow_shadowmapfilter;
+int r_shadow_shadowmapborder;
 int r_shadow_lightscissor[4];
 
 int maxshadowtriangles;
@@ -220,9 +216,7 @@ rtexture_t *r_shadow_attenuation2dtexture;
 rtexture_t *r_shadow_attenuation3dtexture;
 rtexture_t *r_shadow_lightcorona;
 rtexture_t *r_shadow_shadowmaprectangletexture;
-rtexture_t *r_shadow_shadowmap2dtexture;
-rtexture_t *r_shadow_shadowmapcubeprojectiontexture;
-rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
+rtexture_t *r_shadow_shadowmapcubeprojectiontexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
 int r_shadow_shadowmapsize; // changes for each light based on distance
 int r_shadow_shadowmaplod; // changes for each light based on distance
 
@@ -263,10 +257,10 @@ cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization
 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "0", "shadowmap filter modes: 0 = no filtering, 1 = bilinear, 2 = bilinear small blur (fast), 3 = bilinear large blur (slow)"};
 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
-cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "1024", "shadowmap size limit"};
+cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
 cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
 cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
-cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "6", "shadowmap size bias for filtering"};
+cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
 cvar_t r_shadow_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
@@ -341,6 +335,8 @@ void R_Shadow_FreeShadowMaps(void)
 
        r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
        r_shadow_shadowmode = r_shadow_shadowmapping.integer;
+    r_shadow_shadowmapfilter = r_shadow_shadowmapping_filterquality.integer;
+    r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
        r_shadow_shadowmaplod = -1;
 
        CHECKGLERROR
@@ -349,33 +345,14 @@ void R_Shadow_FreeShadowMaps(void)
        r_shadow_fborectangle = 0;
        CHECKGLERROR
 
-       if (r_shadow_fbo2d)
-               qglDeleteFramebuffersEXT(1, &r_shadow_fbo2d);
-       r_shadow_fbo2d = 0;
-       CHECKGLERROR
-
-       for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-               if (r_shadow_fbocubeside[i][0])
-                       qglDeleteFramebuffersEXT(6, r_shadow_fbocubeside[i]);
-       memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
-       CHECKGLERROR
-
        if (r_shadow_shadowmaprectangletexture)
                R_FreeTexture(r_shadow_shadowmaprectangletexture);
        r_shadow_shadowmaprectangletexture = NULL;
 
-       if (r_shadow_shadowmap2dtexture)
-               R_FreeTexture(r_shadow_shadowmap2dtexture);
-       r_shadow_shadowmap2dtexture = NULL;
-
-       if (r_shadow_shadowmapcubeprojectiontexture)
-               R_FreeTexture(r_shadow_shadowmapcubeprojectiontexture);
-       r_shadow_shadowmapcubeprojectiontexture = NULL;
-
-       for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
-               if (r_shadow_shadowmapcubetexture[i])
-                       R_FreeTexture(r_shadow_shadowmapcubetexture[i]);
-       memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
+    for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
+        if (r_shadow_shadowmapcubeprojectiontexture[i])
+            R_FreeTexture(r_shadow_shadowmapcubeprojectiontexture[i]);
+    memset(r_shadow_shadowmapcubeprojectiontexture, 0, sizeof(r_shadow_shadowmapcubeprojectiontexture));
 
        CHECKGLERROR
 }
@@ -387,16 +364,14 @@ void r_shadow_start(void)
        r_shadow_attenuationgradienttexture = NULL;
        r_shadow_attenuation2dtexture = NULL;
        r_shadow_attenuation3dtexture = NULL;
+       r_shadow_shadowmode = 0;
        r_shadow_shadowmaprectangletexture = NULL;
-       memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
-       r_shadow_shadowmapcubeprojectiontexture = NULL;
-       r_shadow_shadowmap2dtexture = NULL;
+    memset(r_shadow_shadowmapcubeprojectiontexture, 0, sizeof(r_shadow_shadowmapcubeprojectiontexture));
        r_shadow_shadowmapmaxsize = 0;
        r_shadow_shadowmapsize = 0;
        r_shadow_shadowmaplod = 0;
+    r_shadow_shadowmapfilter = 0;
        r_shadow_fborectangle = 0;
-       memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
-       r_shadow_fbo2d = 0;
 
        R_Shadow_FreeShadowMaps();
 
@@ -1402,9 +1377,6 @@ void R_Shadow_RenderMode_Reset(void)
        GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        R_SetupGenericShader(false);
-       r_shadow_usingshadowmaprect = false;
-       r_shadow_usingshadowmapcube = false;
-       r_shadow_usingshadowmap2d = false;
        CHECKGLERROR
 }
 
@@ -1467,141 +1439,59 @@ void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
 
 void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
 {
-       int i;
        int status;
        int maxsize;
-       float nearclip, farclip;
+       float nearclip, farclip, bias;
        r_viewport_t viewport;
        CHECKGLERROR
-       maxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
+       maxsize = r_shadow_shadowmapmaxsize;
        nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
        farclip = 1.0f;
-       r_shadow_shadowmap_bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
-       r_shadow_shadowmap_parameters[0] = 1.0f - r_shadow_shadowmapping_bordersize.value / size;
-       r_shadow_shadowmap_parameters[1] = 1.0f - r_shadow_shadowmapping_bordersize.value / size;
-       r_shadow_shadowmap_parameters[2] = -(farclip + nearclip) / (farclip - nearclip);
-       r_shadow_shadowmap_parameters[3] = -2.0f * nearclip * farclip / (farclip - nearclip);
-       if (r_shadow_shadowmapping.integer == 1)
-       {
-               // complex unrolled cube approach (more flexible)
-               //if (!r_shadow_shadowmapcubeprojectiontexture)
-               //      r_shadow_shadowmapcubeprojectiontexture = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection");
-               if (!r_shadow_shadowmap2dtexture)
-               {
-#if 1
-                       r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*4);
-                       qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
-                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
-#endif
-               }
-               CHECKGLERROR
-               R_Shadow_RenderMode_Reset();
-               if (r_shadow_shadowmap2dtexture)
-               {
-                       // render depth into the fbo, do not render color at all
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-                       R_SetupDepthOrShadowShader();
-               }
-               else
-               {
-                       R_SetupShowDepthShader();
-                       qglClearColor(1,1,1,1);CHECKGLERROR
-               }
-               R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapping_bordersize.integer, nearclip, farclip, NULL);
-               r_shadow_shadowmap_texturescale[0] = (float)size / R_TextureWidth(r_shadow_shadowmap2dtexture);
-               r_shadow_shadowmap_texturescale[1] = (float)size / R_TextureHeight(r_shadow_shadowmap2dtexture);
-               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
-       }
-       else if (r_shadow_shadowmapping.integer == 2)
+       bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
+       // complex unrolled cube approach (more flexible)
+       if (!r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod])
+               r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod] = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection", size, r_shadow_shadowmapborder);
+       if (!r_shadow_shadowmaprectangletexture)
        {
-               // complex unrolled cube approach (more flexible)
-               //if (!r_shadow_shadowmapcubeprojectiontexture)
-               //      r_shadow_shadowmapcubeprojectiontexture = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection");
-               if (!r_shadow_shadowmaprectangletexture)
-               {
 #if 1
-                       r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*4);
-                       qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
-                       qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
+               r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapfilter == 1 || r_shadow_shadowmapfilter == 2);
+               qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
+               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
 #endif
-               }
-               CHECKGLERROR
-               R_Shadow_RenderMode_Reset();
-               if (r_shadow_shadowmaprectangletexture)
-               {
-                       // render depth into the fbo, do not render color at all
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-                       R_SetupDepthOrShadowShader();
-               }
-               else
-               {
-                       R_SetupShowDepthShader();
-                       qglClearColor(1,1,1,1);CHECKGLERROR
-               }
-               R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapping_bordersize.integer, nearclip, farclip, NULL);
-               r_shadow_shadowmap_texturescale[0] = size;
-               r_shadow_shadowmap_texturescale[1] = size;
-               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
        }
-       else if (r_shadow_shadowmapping.integer == 3)
+       CHECKGLERROR
+       R_Shadow_RenderMode_Reset();
+       if (r_shadow_shadowmaprectangletexture)
        {
-               // simple cube approach
-               if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
+               // render depth into the fbo, do not render color at all
+               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
+               qglDrawBuffer(GL_NONE);CHECKGLERROR
+               qglReadBuffer(GL_NONE);CHECKGLERROR
+               status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
+               if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
                {
-#if 1
-                       r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", bound(1, maxsize >> r_shadow_shadowmaplod, 2048));
-                       qglGenFramebuffersEXT(6, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
-                       for (i = 0;i < 6;i++)
-                       {
-                               qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][i]);CHECKGLERROR
-                               qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
-                       }
-#endif
+                       Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
+                       Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
                }
-               CHECKGLERROR
-               R_Shadow_RenderMode_Reset();
-               if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
-               {
-                       // render depth into the fbo, do not render color at all
-                       qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][side]);CHECKGLERROR
-                       qglDrawBuffer(GL_NONE);CHECKGLERROR
-                       qglReadBuffer(GL_NONE);CHECKGLERROR
-                       status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
-                       if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
-                       {
-                               Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
-                               Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
-                       }
-                       R_SetupDepthOrShadowShader();
-               }
-               else
-               {
-                       R_SetupShowDepthShader();
-                       qglClearColor(1,1,1,1);CHECKGLERROR
-               }
-               R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
-               r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
-               r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
-               r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
+               R_SetupDepthOrShadowShader();
        }
+       else
+       {
+               R_SetupShowDepthShader();
+               qglClearColor(1,1,1,1);CHECKGLERROR
+       }
+       R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+       r_shadow_shadowmap_texturescale[0] = 2*size;
+       r_shadow_shadowmap_texturescale[1] = 3*size;
+       r_shadow_shadowmap_texturescale[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
+       r_shadow_shadowmap_texturescale[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
+       // compat for ALU cubemap calcs
+    r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+       r_shadow_shadowmap_parameters[1] = size;
+       r_shadow_shadowmap_parameters[2] = r_shadow_shadowmap_texturescale[2];
+       r_shadow_shadowmap_parameters[3] = r_shadow_shadowmap_texturescale[3];
+       r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
        CHECKGLERROR
        R_SetViewport(&viewport);
        GL_PolygonOffset(0, 0);
@@ -1641,24 +1531,10 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb
                CHECKGLERROR
                if (shadowmapping)
                {
-                       if (r_shadow_shadowmapping.integer == 1)
-                       {
-                               r_shadow_usingshadowmap2d = true;
-                               R_Mesh_TexBind(GL20TU_SHADOWMAP2D, R_GetTexture(r_shadow_shadowmap2dtexture));
-                               CHECKGLERROR
-                       }
-                       else if (r_shadow_shadowmapping.integer == 2)
-                       {
-                               r_shadow_usingshadowmaprect = true;
-                               R_Mesh_TexBindRectangle(GL20TU_SHADOWMAPRECT, R_GetTexture(r_shadow_shadowmaprectangletexture));
-                               CHECKGLERROR
-                       }
-                       else if (r_shadow_shadowmapping.integer == 3)
-                       {
-                               r_shadow_usingshadowmapcube = true;
-                               R_Mesh_TexBindCubeMap(GL20TU_SHADOWMAPCUBE, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
-                               CHECKGLERROR
-                       }
+                       R_Mesh_TexBindRectangle(GL20TU_SHADOWMAPRECT, R_GetTexture(r_shadow_shadowmaprectangletexture));
+                       CHECKGLERROR
+                       R_Mesh_TexBindCubeMap(GL20TU_CUBEPROJECTION, R_GetTexture(r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod]));
+                       CHECKGLERROR
                }
        }
        else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_VERTEX)
@@ -3684,7 +3560,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
        lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapping_maxsize.integer);
 
-       if (castshadows && r_shadow_shadowmapping.integer >= 1 && r_shadow_shadowmapping.integer <= 3 && r_glsl.integer && gl_support_fragment_shader)
+       if (castshadows && r_shadow_shadowmode && r_glsl.integer && gl_support_fragment_shader)
        {
                int side;
                int size;
@@ -3694,10 +3570,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                        if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
                                r_shadow_shadowmaplod = i;
 
-               size = lodlinear;
-               if (r_shadow_shadowmapping.integer == 3)
-                       size = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) >> r_shadow_shadowmaplod;
-               size = bound(1, size, 2048);
+               size = bound(1, r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod, 2048);
 
                //Con_Printf("distance %f lodlinear %i (lod %i) size %i\n", distance, lodlinear, r_shadow_shadowmaplod, size);
 
@@ -3726,22 +3599,6 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                        R_Shadow_RenderMode_ShadowMap(side, false, size);
                        for (i = 0;i < numshadowentities_noselfshadow;i++)
                                R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
-#if 0
-                       if (r_shadow_shadowmapping.integer == 1)
-                       {
-                               int w = R_TextureWidth(r_shadow_shadowmap2dtexture);
-                               int h = R_TextureHeight(r_shadow_shadowmap2dtexture);
-                               static int once = true;
-                               if (once)
-                               {
-                                       unsigned char *blah = Z_Malloc(w*h*4);
-                                       qglReadPixels(0, 0, w, h, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, blah);CHECKGLERROR
-                                       FS_WriteFile("testshadowmap.bin", blah, w*h*4);
-                                       Z_Free(blah);
-                               }
-                               once = false;
-                       }
-#endif
                }
 
                // render lighting using the depth texture as shadowmap
@@ -3817,7 +3674,7 @@ void R_ShadowVolumeLighting(qboolean visible)
        dlight_t *light;
        size_t range;
 
-       if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || r_shadow_shadowmode != r_shadow_shadowmapping.integer)
+       if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || r_shadow_shadowmode != r_shadow_shadowmapping.integer || r_shadow_shadowmapfilter != r_shadow_shadowmapping_filterquality.integer || r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
                R_Shadow_FreeShadowMaps();
 
        if (r_editlights.integer)
index e2f5d5a..be1f097 100644 (file)
 #define TEXF_COMPRESS 0x00000200
 // use this flag to block R_PurgeTexture from freeing a texture
 #define TEXF_PERSISTENT 0x00000400
+// indicates texture should use GL_COMPARE_R_TO_TEXTURE mode
+#define TEXF_COMPARE 0x00000800
 // used for checking if textures mismatch
-#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_CLAMP | TEXF_FORCENEAREST | TEXF_FORCELINEAR | TEXF_PICMIP | TEXF_COMPRESS)
+#define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_CLAMP | TEXF_FORCENEAREST | TEXF_FORCELINEAR | TEXF_PICMIP | TEXF_COMPRESS | TEXF_COMPARE)
 
 typedef enum textype_e
 {
@@ -35,6 +37,8 @@ typedef enum textype_e
        TEXTYPE_BGRA,
        // 32bit S8D24 (24bit depth, 8bit stencil unused)
        TEXTYPE_SHADOWMAP,
+       // 32bit L16A16
+       TEXTYPE_PROJECTION
 }
 textype_t;
 
@@ -79,10 +83,8 @@ rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, const char *identifier
 rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette);
 rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette);
 rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, const unsigned int *palette);
-rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height);
-rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width);
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height);
-rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier);
+rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter);
+rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier, int size, int border);
 
 // free a texture
 void R_FreeTexture(rtexture_t *rt);
index b893fff..9f8923a 100644 (file)
--- a/render.h
+++ b/render.h
@@ -409,8 +409,7 @@ typedef enum gl20_texunit_e
        GL20TU_ATTENUATION = 9,
        GL20TU_CUBE = 10,
        GL20TU_SHADOWMAPRECT = 11,
-       GL20TU_SHADOWMAPCUBE = 11,
-       GL20TU_SHADOWMAP2D = 11,
+    GL20TU_CUBEPROJECTION = 12
 }
 gl20_texunit;