"# ifdef GL_EXT_gpu_shader4\n"
"# extension GL_EXT_gpu_shader4 : enable\n"
"# endif\n"
-"# ifdef HASTEXTUREGATHER\n"
+"# ifdef GL_ARB_texture_gather\n"
"# extension GL_ARB_texture_gather : enable\n"
+"# define USETEXTUREGATHER\n"
"# else\n"
-"# ifdef HASTEXTURE4\n"
+"# ifdef GL_AMD_texture_texture4\n"
"# extension GL_AMD_texture_texture4 : enable\n"
+"# define USETEXTUREGATHER\n"
"# define textureGather texture4\n"
"# endif\n"
"# endif\n"
"# endif\n"
"#endif\n"
"\n"
-"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
+"#ifdef USESHADOWMAPVSDCT\n"
"uniform samplerCube Texture_CubeProjection;\n"
"#endif\n"
"\n"
"vec3 GetShadowMapTC2D(vec3 dir)\n"
"{\n"
" vec3 adir = abs(dir);\n"
-"# if 0\n"
+"# ifndef USESHADOWMAPVSDCT\n"
"# ifdef USESHADOWMAPRECT\n"
"# define cubedir(dx, dy, ox, oy) { tc = vec2(dx, dy); offset = vec2(ox, oy); }\n"
"# else\n"
"# endif\n"
"# else\n"
"# ifdef USESHADOWMAPPCF\n"
-"# if defined(HASTEXTUREGATHER) || defined(HASTEXTURE4)\n"
-" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale.zw, offset = fract(center - 0.5);\n"
+"# ifdef USETEXTUREGATHER\n"
+" vec2 center = shadowmaptc.xy*ShadowMap_TextureScale.zw - 0.5, offset = fract(center);\n"
" vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2(-1.0, -1.0))*ShadowMap_TextureScale.xy)),\n"
" group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2( 1.0, -1.0))*ShadowMap_TextureScale.xy)),\n"
" group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2(-1.0, 1.0))*ShadowMap_TextureScale.xy)),\n"
" group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2( 1.0, 1.0))*ShadowMap_TextureScale.xy)),\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"
+" cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
+" mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
" f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
"# else\n"
"# ifdef GL_EXT_gpu_shader4\n"
SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
SHADERPERMUTATION_SHADOWSAMPLER = 1<<15, //< (lightsource) use hardware shadowmap test
- SHADERPERMUTATION_LIMIT = 1<<16, ///< size of permutations array
- SHADERPERMUTATION_COUNT = 16 ///< size of shaderpermutationinfo array
+ SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<16, //< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
+ SHADERPERMUTATION_LIMIT = 1<<17, ///< size of permutations array
+ SHADERPERMUTATION_COUNT = 17 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
{"#define USESHADOWMAP2D\n", " shadowmap2d"},
{"#define USESHADOWMAPPCF\n", " shadowmappcf"},
{"#define USESHADOWSAMPLER\n", " shadowsampler"},
+ {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
};
/// this enum is multiplied by SHADERPERMUTATION_MODEBASE
extern qboolean r_shadow_usingshadowmap2d;
extern float r_shadow_shadowmap_texturescale[4];
extern float r_shadow_shadowmap_parameters[4];
-extern int r_shadow_shadowmode;
+extern int r_shadow_shadowmapvsdct;
extern int r_shadow_shadowmapfilter;
void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
{
permutation |= SHADERPERMUTATION_FOG;
if (rsurface.texture->colormapping)
permutation |= SHADERPERMUTATION_COLORMAPPING;
- if (r_shadow_usingshadowmaprect)
- 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;
+ if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
+ {
+ if (r_shadow_usingshadowmaprect)
+ permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
+ if (r_shadow_usingshadowmap2d)
+ permutation |= SHADERPERMUTATION_SHADOWMAP2D;
+ if (r_shadow_usingshadowmapcube)
+ permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
+ else if(r_shadow_shadowmapvsdct)
+ permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
+
+ 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)
{
GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS][6];
GLuint r_shadow_fbo2d;
int r_shadow_shadowmode;
+int r_shadow_shadowmapvsdct;
int r_shadow_shadowmapmaxsize;
int r_shadow_shadowmapfilter;
int r_shadow_shadowmapborder;
cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
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_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
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", "512", "shadowmap size limit"};
cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
r_shadow_shadowmode = r_shadow_shadowmapping.integer;
+ r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer;
r_shadow_shadowmapfilter = r_shadow_shadowmapping_filterquality.integer;
r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
r_shadow_shadowmaplod = -1;
r_shadow_shadowmapmaxsize = 0;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmaplod = 0;
+ r_shadow_shadowmapvsdct = 0;
r_shadow_shadowmapfilter = 0;
r_shadow_fborectangle = 0;
r_shadow_fbo2d = 0;
Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
Cvar_RegisterVariable(&r_shadow_scissor);
Cvar_RegisterVariable(&r_shadow_shadowmapping);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
if (r_shadow_shadowmode == 1)
{
// complex unrolled cube approach (more flexible)
- if (!r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod])
+ if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod])
r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod] = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection", 2, 4, size, r_shadow_shadowmapborder);
if (!r_shadow_shadowmap2dtexture)
{
else if (r_shadow_shadowmode == 2)
{
// complex unrolled cube approach (more flexible)
- if (!r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod])
+ if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod])
r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod] = R_LoadTextureCubeProjection(r_shadow_texturepool, "shadowmapcubeprojection", 2, 3, size, r_shadow_shadowmapborder);
if (!r_shadow_shadowmaprectangletexture)
{
CHECKGLERROR
}
- if (r_shadow_usingshadowmap2d || r_shadow_usingshadowmaprect)
+ if (r_shadow_shadowmapvsdct && (r_shadow_usingshadowmap2d || r_shadow_usingshadowmaprect))
{
R_Mesh_TexBindCubeMap(GL20TU_CUBEPROJECTION, R_GetTexture(r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod]));
CHECKGLERROR
if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
r_shadow_shadowmaplod = i;
- size = bound(1, r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod, 2048);
+ size = r_shadow_shadowmapvsdct || r_shadow_shadowmode ? r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod : lodlinear;
+ size = bound(1, size, 2048);
//Con_Printf("distance %f lodlinear %i (lod %i) size %i\n", distance, lodlinear, r_shadow_shadowmaplod, size);
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 || r_shadow_shadowmapfilter != r_shadow_shadowmapping_filterquality.integer || r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
+ if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) || r_shadow_shadowmode != r_shadow_shadowmapping.integer || r_shadow_shadowmapvsdct != r_shadow_shadowmapping_vsdct.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)