float cubeviewmatrix[6][16] =
{
- {
- 0, 0,-1, 0,
- 0,-1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 0, 1,
- },
- {
- 0, 0, 1, 0,
- 0,-1, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 1,
- },
- {
- 1, 0, 0, 0,
- 0, 0,-1, 0,
- 0, 1, 0, 0,
- 0, 0, 0, 1,
- },
- {
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0,-1, 0, 0,
- 0, 0, 0, 1,
- },
- {
- 1, 0, 0, 0,
- 0,-1, 0, 0,
- 0, 0,-1, 0,
- 0, 0, 0, 1,
- },
- {
- -1, 0, 0, 0,
- 0,-1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
- },
+ // standard cubemap projections
+ { // +X
+ 0, 0,-1, 0,
+ 0,-1, 0, 0,
+ -1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -X
+ 0, 0, 1, 0,
+ 0,-1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Y
+ 1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Y
+ 1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0,-1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Z
+ 1, 0, 0, 0,
+ 0,-1, 0, 0,
+ 0, 0,-1, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Z
+ -1, 0, 0, 0,
+ 0,-1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+ },
+};
+float rectviewmatrix[6][16] =
+{
+ // sign-preserving cubemap projections
+ { // +X
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -X
+ 0, 0, 1, 0,
+ 0, 1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Y
+ 1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Y
+ 1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Z
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0,-1, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Z
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+ },
};
void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
v->m[11] = -1;
v->m[14] = -2 * nearclip * farclip / (farclip - nearclip);
- Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
+ Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
Matrix4x4_FromArrayDoubleGL(&v->projectmatrix, v->m);
" float ma;\n"
" if (adir.x > adir.y)\n"
" {\n"
-" if (adir.x > adir.z)\n"
+" if (adir.x > adir.z) // X\n"
" {\n"
" ma = adir.x;\n"
-" if (dir.x >= 0.0) { tc = vec2(-dir.z, -dir.y); offset = vec2(0.5, 0.5); } // +X\n"
-" else { tc = vec2( dir.z, -dir.y); offset = vec2(1.5, 0.5); } // -X\n"
+" tc = dir.zy;\n"
+" offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
" }\n"
-" else\n"
+" else // Z\n"
" {\n"
" ma = adir.z;\n"
-" if (dir.z >= 0.0) { tc = vec2( dir.x, -dir.y); offset = vec2(0.5, 2.5); } // +Z\n"
-" else { tc = vec2(-dir.x, -dir.y); offset = vec2(1.5, 2.5); } // -Z\n"
+" tc = dir.xy;\n"
+" offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
" }\n"
" }\n"
" else\n"
" {\n"
-" if (adir.y > adir.z)\n"
+" if (adir.y > adir.z) // Y\n"
" {\n"
" ma = adir.y;\n"
-" if (dir.y >= 0.0) { tc = vec2( dir.x, dir.z); offset = vec2(0.5, 1.5); } // +Y\n"
-" else { tc = vec2( dir.x, -dir.z); offset = vec2(1.5, 1.5); } // -Y\n"
+" tc = dir.xz;\n"
+" offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
" }\n"
-" else\n"
+" else // Z\n"
" {\n"
" ma = adir.z;\n"
-" if (dir.z >= 0.0) { tc = vec2( dir.x, -dir.y); offset = vec2(0.5, 2.5); } // +Z\n"
-" else { tc = vec2(-dir.x, -dir.y); offset = vec2(1.5, 2.5); } // -Z\n"
+" tc = dir.xy;\n"
+" offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
" }\n"
" }\n"
"\n"
-" vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
+" vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
+" stc.xy += offset * ShadowMap_Parameters.y;\n"
+" stc.z += ShadowMap_Parameters.z;\n"
+"# ifndef USESHADOWMAPRECT\n"
" stc.xy *= ShadowMap_TextureScale.xy;\n"
+"# endif\n"
" return stc;\n"
"# else\n"
-" return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_Parameters.xy, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
+" vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
+" float ma = max(max(adir.x, adir.y), adir.z);\n"
+" vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
+" stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
+" stc.z += ShadowMap_Parameters.z;\n"
+"# ifndef USESHADOWMAPRECT\n"
+" stc.xy *= ShadowMap_TextureScale.xy;\n"
+"# endif\n"
+" return stc;\n"
"# endif\n"
"}\n"
"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
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
{
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;
}
break;
case TEXTYPE_SHADOWMAP:
- case TEXTYPE_PROJECTION:
break;
default:
Host_Error("R_LoadTexture: unknown texture type");
return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, TEXF_ALWAYSPRECACHE | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR | TEXF_COMPARE : TEXF_FORCENEAREST), TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
}
-rtexture_t *R_LoadTextureCubeProjection(rtexturepool_t *rtexturepool, const char *identifier, int size, int border)
-{
- // 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%2)<<16, y = (i/2)<<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)
{
return rt ? (((gltexture_t *)rt)->flags & TEXF_ALPHA) != 0 : false;
// GL_EXT_bgra
#define GL_BGRA 0x80E1
-// GL_EXT_texture
-#define GL_LUMINANCE_ALPHA 0x190A
-#define GL_LUMINANCE16_ALPHA16 0x8048
-
//GL_AMD_texture_texture4
extern int gl_support_amd_texture_texture4;
rtexture_t *r_shadow_shadowmaprectangletexture;
rtexture_t *r_shadow_shadowmap2dtexture;
rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
-rtexture_t *r_shadow_shadowmapcubeprojectiontexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
+rtexture_t *r_shadow_shadowmapvsdcttexture;
int r_shadow_shadowmapsize; // changes for each light based on distance
int r_shadow_shadowmaplod; // changes for each light based on distance
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));
+ if (r_shadow_shadowmapvsdcttexture)
+ R_FreeTexture(r_shadow_shadowmapvsdcttexture);
+ r_shadow_shadowmapvsdcttexture = NULL;
CHECKGLERROR
}
r_shadow_shadowmaprectangletexture = NULL;
r_shadow_shadowmap2dtexture = NULL;
memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
- memset(r_shadow_shadowmapcubeprojectiontexture, 0, sizeof(r_shadow_shadowmapcubeprojectiontexture));
+ r_shadow_shadowmapvsdcttexture = NULL;
r_shadow_shadowmapmaxsize = 0;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmaplod = 0;
}
}
+static void R_Shadow_MakeVSDCT(void)
+{
+ // maps to a 2x3 texture rectangle with normalized coordinates
+ // +-
+ // XX
+ // YY
+ // ZZ
+ // stores abs(dir.xy), offset.xy/2.5
+ unsigned char data[4*6] =
+ {
+ 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
+ 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
+ 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
+ 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
+ 0, 0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
+ 0, 0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
+ };
+ r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_ALWAYSPRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALPHA, NULL);
+}
+
void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
{
int i;
if (r_shadow_shadowmode == 1)
{
// complex unrolled cube approach (more flexible)
- if (r_shadow_shadowmapvsdct && !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_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
+ R_Shadow_MakeVSDCT();
if (!r_shadow_shadowmap2dtexture)
{
#if 1
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_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap_parameters[0] = r_shadow_shadowmapvsdct ? 2*size * r_shadow_shadowmap_texturescale[0] : 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 3*size * r_shadow_shadowmap_texturescale[1] : size;
+ r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+ r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
}
else if (r_shadow_shadowmode == 2)
{
// complex unrolled cube approach (more flexible)
- if (r_shadow_shadowmapvsdct && !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_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
+ R_Shadow_MakeVSDCT();
if (!r_shadow_shadowmaprectangletexture)
{
#if 1
R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
r_shadow_shadowmap_texturescale[0] = 1.0f;
r_shadow_shadowmap_texturescale[1] = 1.0f;
- r_shadow_shadowmap_parameters[0] = r_shadow_shadowmapvsdct ? 2*size : 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 3*size : size;
+ r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+ r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
}
else if (r_shadow_shadowmode == 3)
if (r_shadow_shadowmapvsdct && (r_shadow_usingshadowmap2d || r_shadow_usingshadowmaprect))
{
- R_Mesh_TexBindCubeMap(GL20TU_CUBEPROJECTION, R_GetTexture(r_shadow_shadowmapcubeprojectiontexture[r_shadow_shadowmaplod]));
+ R_Mesh_TexBindCubeMap(GL20TU_CUBEPROJECTION, R_GetTexture(r_shadow_shadowmapvsdcttexture));
CHECKGLERROR
}
}
if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
r_shadow_shadowmaplod = i;
- size = r_shadow_shadowmapvsdct || r_shadow_shadowmode == 3 ? r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod : lodlinear;
+ size = r_shadow_shadowmode == 3 ? 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);
TEXTYPE_BGRA,
// 32bit S8D24 (24bit depth, 8bit stencil unused)
TEXTYPE_SHADOWMAP,
- // 32bit L16A16
- TEXTYPE_PROJECTION
}
textype_t;
rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter);
rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, qboolean filter);
rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, 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);