From 58eab13c07cc60570bb94d0a511ae57433f0019c Mon Sep 17 00:00:00 2001 From: eihrul Date: Thu, 1 Oct 2009 16:09:44 +0000 Subject: [PATCH] better VSDCT transform git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9272 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_backend.c | 115 ++++++++++++++++++++++++++++++++++---------------- gl_rmain.c | 40 ++++++++++++------ gl_textures.c | 38 ----------------- glquake.h | 4 -- r_shadow.c | 53 +++++++++++++++-------- r_textures.h | 3 -- 6 files changed, 140 insertions(+), 113 deletions(-) diff --git a/gl_backend.c b/gl_backend.c index 78e56421..e4dc9755 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -442,42 +442,83 @@ void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *came 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) @@ -521,7 +562,7 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri 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); diff --git a/gl_rmain.c b/gl_rmain.c index dfa8a441..2d101390 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -924,40 +924,52 @@ static const char *builtinshaderstring = " 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" diff --git a/gl_textures.c b/gl_textures.c index c3cbcf3d..e0c9720c 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -61,7 +61,6 @@ 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 { @@ -219,8 +218,6 @@ 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; @@ -1066,7 +1063,6 @@ 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"); @@ -1149,40 +1145,6 @@ rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char 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)<flags & TEXF_ALPHA) != 0 : false; diff --git a/glquake.h b/glquake.h index 301b4660..9a749e3b 100644 --- a/glquake.h +++ b/glquake.h @@ -953,10 +953,6 @@ 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 - //GL_AMD_texture_texture4 extern int gl_support_amd_texture_texture4; diff --git a/r_shadow.c b/r_shadow.c index b0c34542..a6f99ec0 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -227,7 +227,7 @@ rtexture_t *r_shadow_lightcorona; 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 @@ -435,10 +435,9 @@ void R_Shadow_FreeShadowMaps(void) 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 } @@ -454,7 +453,7 @@ void r_shadow_start(void) 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; @@ -1536,6 +1535,26 @@ void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass) } } +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; @@ -1553,8 +1572,8 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) 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 @@ -1586,18 +1605,18 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) 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 @@ -1631,8 +1650,8 @@ void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size) 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) @@ -1740,7 +1759,7 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb 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 } } @@ -3778,7 +3797,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) 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); diff --git a/r_textures.h b/r_textures.h index 55adebc5..d43be404 100644 --- a/r_textures.h +++ b/r_textures.h @@ -37,8 +37,6 @@ typedef enum textype_e TEXTYPE_BGRA, // 32bit S8D24 (24bit depth, 8bit stencil unused) TEXTYPE_SHADOWMAP, - // 32bit L16A16 - TEXTYPE_PROJECTION } textype_t; @@ -86,7 +84,6 @@ rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *ident 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); -- 2.39.2