From e1e429311c776dbb16d3e7c914ca62716841fd3a Mon Sep 17 00:00:00 2001 From: "havoc havoc@d7cf8633-e32d-0410-b094-e92efae38249" <> Date: Fri, 17 Sep 2010 08:56:55 +0000 Subject: [PATCH] UNMERGE remove r_shadow_texturetype cvar (now always uses 2D textures), remove shadowmap cube and rect support removed GL_ARB_texture_rectangle texture support throughout engine (nothing using it) refactored D3D9 path in R_Mesh_SetRenderTargets in unsuccessful attempt to fix D3D9 shadowmapping git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10467 d7cf8633-e32d-0410-b094-e92efae38249 ::stable-branch::unmerge=5896a10952478d0f0f805aca72f1bb268ace7d81 --- gl_backend.c | 155 +++++++++------------- gl_rmain.c | 360 +++++++++++++++++++++++++++++++++++++++++++++----- gl_textures.c | 31 ++++- glquake.h | 9 ++ r_shadow.c | 316 ++++++++++++++++++++++++++++++++++---------- r_textures.h | 3 + render.h | 2 + vid.h | 2 + vid_shared.c | 4 + 9 files changed, 680 insertions(+), 202 deletions(-) diff --git a/gl_backend.c b/gl_backend.c index 3596dc4f..15adfc73 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -110,7 +110,7 @@ typedef struct gltextureunit_s size_t pointer_texcoord_offset; rtexture_t *texture; - int t2d, t3d, tcubemap; + int t2d, t3d, tcubemap, trectangle; int arrayenabled; int rgbscale, alphascale; int combine; @@ -183,8 +183,8 @@ typedef struct gl_state_s qboolean active; #ifdef SUPPORTD3D -// rtexture_t *d3drt_depthtexture; -// rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS]; + rtexture_t *d3drt_depthtexture; + rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS]; IDirect3DSurface9 *d3drt_depthsurface; IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS]; IDirect3DSurface9 *d3drt_backbufferdepthsurface; @@ -379,26 +379,6 @@ static void gl_backend_devicelost(void) #ifdef SUPPORTD3D gl_state.d3dvertexbuffer = NULL; #endif - switch(vid.renderpath) - { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface); - IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface); -#endif - break; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - } endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray); for (i = 0;i < endindex;i++) { @@ -436,26 +416,6 @@ static void gl_backend_devicelost(void) static void gl_backend_devicerestored(void) { - switch(vid.renderpath) - { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface); - IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface); -#endif - break; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - } } void gl_backend_init(void) @@ -988,42 +948,6 @@ void R_Mesh_DestroyFramebufferObject(int fbo) } } -#ifdef SUPPORTD3D -void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3) -{ -// LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still) -// if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3) -// return; - - gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface; -// if (gl_state.d3drt_depthsurface != depthsurface) - { - gl_state.d3drt_depthsurface = depthsurface; - IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface); - } - if (gl_state.d3drt_colorsurfaces[0] != colorsurface0) - { - gl_state.d3drt_colorsurfaces[0] = colorsurface0; - IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]); - } - if (gl_state.d3drt_colorsurfaces[1] != colorsurface1) - { - gl_state.d3drt_colorsurfaces[1] = colorsurface1; - IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]); - } - if (gl_state.d3drt_colorsurfaces[2] != colorsurface2) - { - gl_state.d3drt_colorsurfaces[2] = colorsurface2; - IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]); - } - if (gl_state.d3drt_colorsurfaces[3] != colorsurface3) - { - gl_state.d3drt_colorsurfaces[3] = colorsurface3; - IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]); - } -} -#endif - void R_Mesh_ResetRenderTargets(void) { switch(vid.renderpath) @@ -1040,7 +964,22 @@ void R_Mesh_ResetRenderTargets(void) break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D - R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL); + if (gl_state.framebufferobject) + { + unsigned int i; + gl_state.framebufferobject = 0; + IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_backbufferdepthsurface); + IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_backbuffercolorsurface); + gl_state.d3drt_depthsurface = NULL; + for (i = 1;i < vid.maxdrawbuffers;i++) + { + if (gl_state.d3drt_colorsurfaces[i]) + { + gl_state.d3drt_colorsurfaces[i] = NULL; + IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, i, NULL); + } + } + } #endif break; case RENDERPATH_D3D10: @@ -1084,22 +1023,27 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost if (fbo) { - IDirect3DSurface9 *colorsurfaces[4]; - for (i = 0;i < 4;i++) + gl_state.framebufferobject = 1; + gl_state.d3drt_depthtexture = depthtexture; + if (gl_state.d3drt_depthtexture) + IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, (IDirect3DSurface9 *)gl_state.d3drt_depthtexture->d3dtexture); + else + IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, NULL); + for (i = 0;i < vid.maxdrawbuffers;i++) { - colorsurfaces[i] = NULL; - if (textures[i]) - IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]); + gl_state.d3drt_colortextures[i] = textures[i]; + if (gl_state.d3drt_colortextures[i]) + { + IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)gl_state.d3drt_colortextures[i]->d3dtexture, 0, &gl_state.d3drt_colorsurfaces[i]); + IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, i, gl_state.d3drt_colorsurfaces[i]); + IDirect3DSurface9_Release(gl_state.d3drt_colorsurfaces[i]); + } + else + IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, i, i ? NULL : gl_state.d3drt_backbuffercolorsurface); } - // set the render targets for real - R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]); - // release the texture surface levels (they won't be lost while bound...) - for (i = 0;i < 4;i++) - if (textures[i]) - IDirect3DSurface9_Release(colorsurfaces[i]); } else - R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL); + R_Mesh_ResetRenderTargets(); #endif break; case RENDERPATH_D3D10: @@ -1240,6 +1184,10 @@ static void GL_Backend_ResetState(void) { qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR } + if (vid.support.arb_texture_rectangle) + { + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);CHECKGLERROR + } } for (i = 0;i < vid.texarrayunits;i++) @@ -1307,6 +1255,11 @@ static void GL_Backend_ResetState(void) qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR } + if (vid.support.arb_texture_rectangle) + { + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);CHECKGLERROR + } GL_BindVBO(0); qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR @@ -2122,7 +2075,6 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi void R_Mesh_Start(void) { BACKENDACTIVECHECK - R_Mesh_ResetRenderTargets(); R_Mesh_SetUseVBO(); if (gl_printcheckerror.integer && !gl_paranoid.integer) { @@ -2607,7 +2559,6 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri // restores backend state, used when done with 3D rendering void R_Mesh_Finish(void) { - R_Mesh_ResetRenderTargets(); } r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16) @@ -2885,6 +2836,8 @@ int R_Mesh_TexBound(unsigned int unitnum, int id) return unit->t3d; if (id == GL_TEXTURE_CUBE_MAP_ARB) return unit->tcubemap; + if (id == GL_TEXTURE_RECTANGLE_ARB) + return unit->trectangle; return 0; } @@ -2966,6 +2919,7 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex) case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break; case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break; case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break; + case GL_TEXTURE_RECTANGLE_ARB: if (unit->trectangle != texnum) {GL_ActiveTexture(unitnum);unit->trectangle = texnum;qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR}break; } break; case RENDERPATH_GL13: @@ -3258,6 +3212,12 @@ void R_Mesh_ResetTextureState(void) GL_ActiveTexture(unitnum); qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + if (unit->trectangle) + { + unit->trectangle = 0; + GL_ActiveTexture(unitnum); + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } } for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++) { @@ -3310,6 +3270,13 @@ void R_Mesh_ResetTextureState(void) qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR } + if (unit->trectangle) + { + unit->trectangle = 0; + GL_ActiveTexture(unitnum); + qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR + qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR + } if (unit->arrayenabled) { unit->arrayenabled = false; diff --git a/gl_rmain.c b/gl_rmain.c index 885453db..683a1655 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -587,6 +587,10 @@ static const char *builtinshaderstring = "#define USEEYEVECTOR\n" "#endif\n" "\n" +"#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n" +"# extension GL_ARB_texture_rectangle : enable\n" +"#endif\n" +"\n" "#ifdef USESHADOWMAP2D\n" "# ifdef GL_EXT_gpu_shader4\n" "# extension GL_EXT_gpu_shader4 : enable\n" @@ -600,6 +604,10 @@ static const char *builtinshaderstring = "# endif\n" "#endif\n" "\n" +"#ifdef USESHADOWMAPCUBE\n" +"# extension GL_EXT_gpu_shader4 : enable\n" +"#endif\n" +"\n" "//#ifdef USESHADOWSAMPLER\n" "//# extension GL_ARB_shadow : enable\n" "//#endif\n" @@ -1144,6 +1152,14 @@ static const char *builtinshaderstring = "\n" "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n" "\n" +"#ifdef USESHADOWMAPRECT\n" +"# ifdef USESHADOWSAMPLER\n" +"uniform sampler2DRectShadow Texture_ShadowMapRect;\n" +"# else\n" +"uniform sampler2DRect Texture_ShadowMapRect;\n" +"# endif\n" +"#endif\n" +"\n" "#ifdef USESHADOWMAP2D\n" "# ifdef USESHADOWSAMPLER\n" "uniform sampler2DShadow Texture_ShadowMap2D;\n" @@ -1156,12 +1172,20 @@ static const char *builtinshaderstring = "uniform samplerCube Texture_CubeProjection;\n" "#endif\n" "\n" -"#if defined(USESHADOWMAP2D)\n" +"#ifdef USESHADOWMAPCUBE\n" +"# ifdef USESHADOWSAMPLER\n" +"uniform samplerCubeShadow Texture_ShadowMapCube;\n" +"# else\n" +"uniform samplerCube Texture_ShadowMapCube;\n" +"# endif\n" +"#endif\n" +"\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n" "uniform vec2 ShadowMap_TextureScale;\n" "uniform vec4 ShadowMap_Parameters;\n" "#endif\n" "\n" -"#if defined(USESHADOWMAP2D)\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" "# ifdef USESHADOWMAPORTHO\n" "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n" "# else\n" @@ -1186,7 +1210,63 @@ static const char *builtinshaderstring = "}\n" "# endif\n" "# endif\n" -"#endif // defined(USESHADOWMAP2D)\n" +"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" +"\n" +"#ifdef USESHADOWMAPCUBE\n" +"vec4 GetShadowMapTCCube(vec3 dir)\n" +"{\n" +" vec3 adir = abs(dir);\n" +" return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n" +"}\n" +"#endif\n" +"\n" +"# ifdef USESHADOWMAPRECT\n" +"float ShadowMapCompare(vec3 dir)\n" +"{\n" +" vec3 shadowmaptc = GetShadowMapTC2D(dir);\n" +" float f;\n" +"# ifdef USESHADOWSAMPLER\n" +"\n" +"# ifdef USESHADOWMAPPCF\n" +"# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n" +" f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n" +"# else\n" +" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n" +"# endif\n" +"\n" +"# else\n" +"\n" +"# ifdef USESHADOWMAPPCF\n" +"# if USESHADOWMAPPCF > 1\n" +"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n" +" vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n" +" vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n" +" vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n" +" vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n" +" vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n" +" vec4 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" +"# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n" +" vec2 offset = fract(shadowmaptc.xy);\n" +" vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n" +" vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n" +" vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n" +" vec3 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" +"# ifdef USESHADOWMAPORTHO\n" +" return mix(ShadowMap_Parameters.w, 1.0, f);\n" +"# else\n" +" return f;\n" +"# endif\n" +"}\n" +"# endif\n" "\n" "# ifdef USESHADOWMAP2D\n" "float ShadowMapCompare(vec3 dir)\n" @@ -1275,6 +1355,21 @@ static const char *builtinshaderstring = "# endif\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" +"# ifdef USESHADOWSAMPLER\n" +" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n" +"# else\n" +" f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n" +"# endif\n" +" return f;\n" +"}\n" +"# endif\n" "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n" "#endif // FRAGMENT_SHADER\n" "\n" @@ -1401,7 +1496,7 @@ static const char *builtinshaderstring = "# endif\n" "#endif\n" "\n" -"#if defined(USESHADOWMAP2D)\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n" " fade *= ShadowMapCompare(CubeVector);\n" "#endif\n" "\n" @@ -1615,7 +1710,7 @@ static const char *builtinshaderstring = "#endif\n" " color.rgb *= LightColor;\n" " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n" -"#if defined(USESHADOWMAP2D)\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n" " color.rgb *= ShadowMapCompare(CubeVector);\n" "#endif\n" "# ifdef USECUBEFILTER\n" @@ -2307,7 +2402,7 @@ const char *builtincgshaderstring = "#endif // USEOFFSETMAPPING\n" "\n" "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n" -"#if defined(USESHADOWMAP2D)\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" "# ifdef USESHADOWMAPORTHO\n" "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n" "# else\n" @@ -2336,7 +2431,71 @@ const char *builtincgshaderstring = "}\n" "# endif\n" "# endif\n" -"#endif // defined(USESHADOWMAP2D)\n" +"#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" +"\n" +"#ifdef USESHADOWMAPCUBE\n" +"float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n" +"{\n" +" float3 adir = abs(dir);\n" +" return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n" +"}\n" +"#endif\n" +"\n" +"# ifdef USESHADOWMAPRECT\n" +"#ifdef USESHADOWMAPVSDCT\n" +"float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n" +"#else\n" +"float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n" +"#endif\n" +"{\n" +"#ifdef USESHADOWMAPVSDCT\n" +" float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n" +"#else\n" +" float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n" +"#endif\n" +" float f;\n" +"# ifdef USESHADOWSAMPLER\n" +"\n" +"# ifdef USESHADOWMAPPCF\n" +"# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n" +" f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n" +"# else\n" +" f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n" +"# endif\n" +"\n" +"# else\n" +"\n" +"# ifdef USESHADOWMAPPCF\n" +"# if USESHADOWMAPPCF > 1\n" +"# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n" +" float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n" +" float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n" +" float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n" +" float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n" +" float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n" +" float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n" +" f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n" +"# else\n" +"# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n" +" float2 offset = frac(shadowmaptc.xy);\n" +" float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n" +" float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n" +" float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n" +" float3 cols = row2 + lerp(row1, row3, offset.y);\n" +" f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n" +"# endif\n" +"# else\n" +" f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n" +"# endif\n" +"\n" +"# endif\n" +"# ifdef USESHADOWMAPORTHO\n" +" return lerp(ShadowMap_Parameters.w, 1.0, f);\n" +"# else\n" +" return f;\n" +"# endif\n" +"}\n" +"# endif\n" "\n" "# ifdef USESHADOWMAP2D\n" "#ifdef USESHADOWMAPVSDCT\n" @@ -2433,6 +2592,21 @@ const char *builtincgshaderstring = "# endif\n" "}\n" "# endif\n" +"\n" +"# ifdef USESHADOWMAPCUBE\n" +"float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n" +"{\n" +" // apply depth texture cubemap as light filter\n" +" float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n" +" float f;\n" +"# ifdef USESHADOWSAMPLER\n" +" f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n" +"# else\n" +" f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n" +"# endif\n" +" return f;\n" +"}\n" +"# endif\n" "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n" "#endif // FRAGMENT_SHADER\n" "\n" @@ -2598,6 +2772,14 @@ const char *builtincgshaderstring = "uniform samplerCUBE Texture_Cube : register(s10),\n" "#endif\n" "\n" +"#ifdef USESHADOWMAPRECT\n" +"# ifdef USESHADOWSAMPLER\n" +"uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n" +"# else\n" +"uniform samplerRECT Texture_ShadowMapRect : register(s11),\n" +"# endif\n" +"#endif\n" +"\n" "#ifdef USESHADOWMAP2D\n" "# ifdef USESHADOWSAMPLER\n" "uniform sampler Texture_ShadowMap2D : register(s11),\n" @@ -2610,7 +2792,15 @@ const char *builtincgshaderstring = "uniform samplerCUBE Texture_CubeProjection : register(s12),\n" "#endif\n" "\n" -"#if defined(USESHADOWMAP2D)\n" +"#ifdef USESHADOWMAPCUBE\n" +"# ifdef USESHADOWSAMPLER\n" +"uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n" +"# else\n" +"uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n" +"# endif\n" +"#endif\n" +"\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n" "uniform float2 ShadowMap_TextureScale : register(c35),\n" "uniform float4 ShadowMap_Parameters : register(c34),\n" "#endif\n" @@ -2650,8 +2840,18 @@ const char *builtincgshaderstring = "# endif\n" "#endif\n" "\n" -"#if defined(USESHADOWMAP2D)\n" -" fade *= ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n" +"#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n" +" fade *= ShadowMapCompare(CubeVector,\n" +"# if defined(USESHADOWMAP2D)\n" +"Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n" +"# endif\n" +"# if defined(USESHADOWMAPRECT)\n" +"Texture_ShadowMapRect, ShadowMap_Parameters\n" +"# endif\n" +"# if defined(USESHADOWMAPCUBE)\n" +"Texture_ShadowMapCube, ShadowMap_Parameters\n" +"# endif\n" +"\n" "#ifdef USESHADOWMAPVSDCT\n" ", Texture_CubeProjection\n" "#endif\n" @@ -2961,6 +3161,14 @@ const char *builtincgshaderstring = "\n" "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n" "\n" +"#ifdef USESHADOWMAPRECT\n" +"# ifdef USESHADOWSAMPLER\n" +"uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n" +"# else\n" +"uniform samplerRECT Texture_ShadowMapRect : register(s11),\n" +"# endif\n" +"#endif\n" +"\n" "#ifdef USESHADOWMAP2D\n" "# ifdef USESHADOWSAMPLER\n" "uniform sampler Texture_ShadowMap2D : register(s11),\n" @@ -2973,7 +3181,15 @@ const char *builtincgshaderstring = "uniform samplerCUBE Texture_CubeProjection : register(s12),\n" "#endif\n" "\n" -"#if defined(USESHADOWMAP2D)\n" +"#ifdef USESHADOWMAPCUBE\n" +"# ifdef USESHADOWSAMPLER\n" +"uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n" +"# else\n" +"uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n" +"# endif\n" +"#endif\n" +"\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n" "uniform float2 ShadowMap_TextureScale : register(c35),\n" "uniform float4 ShadowMap_Parameters : register(c34),\n" "#endif\n" @@ -3058,8 +3274,18 @@ const char *builtincgshaderstring = "#endif\n" " color.rgb *= LightColor;\n" " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n" -"#if defined(USESHADOWMAP2D)\n" -" color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n" +"#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n" +" color.rgb *= half(ShadowMapCompare(CubeVector,\n" +"# if defined(USESHADOWMAP2D)\n" +"Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n" +"# endif\n" +"# if defined(USESHADOWMAPRECT)\n" +"Texture_ShadowMapRect, ShadowMap_Parameters\n" +"# endif\n" +"# if defined(USESHADOWMAPCUBE)\n" +"Texture_ShadowMapCube, ShadowMap_Parameters\n" +"# endif\n" +"\n" "#ifdef USESHADOWMAPVSDCT\n" ", Texture_CubeProjection\n" "#endif\n" @@ -3165,7 +3391,14 @@ const char *builtincgshaderstring = "#endif\n" "\n" "#ifdef USESHADOWMAPORTHO\n" -" color.rgb *= ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale);\n" +" color.rgb *= ShadowMapCompare(ShadowMapTC,\n" +"# if defined(USESHADOWMAP2D)\n" +"Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n" +"# endif\n" +"# if defined(USESHADOWMAPRECT)\n" +"Texture_ShadowMapRect, ShadowMap_Parameters\n" +"# endif\n" +" );\n" "#endif\n" "\n" "#ifdef USEDEFERREDLIGHTMAP\n" @@ -3263,17 +3496,19 @@ typedef enum shaderpermutation_e SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!) - SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter - SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results - SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results - SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test - SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing - SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection - SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping - SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 - SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe) - SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array - SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array + SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter + SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter + SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter + SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results + SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test + SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing + SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection + SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping + SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 + SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe) + SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array + SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array } shaderpermutation_t; @@ -3298,6 +3533,8 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USEREFLECTION\n", " reflection"}, {"#define USEOFFSETMAPPING\n", " offsetmapping"}, {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"}, + {"#define USESHADOWMAPRECT\n", " shadowmaprect"}, + {"#define USESHADOWMAPCUBE\n", " shadowmapcube"}, {"#define USESHADOWMAP2D\n", " shadowmap2d"}, {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"}, {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, @@ -3427,6 +3664,8 @@ typedef struct r_glsl_permutation_s int loc_Texture_Cube; 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_Texture_ScreenDepth; @@ -3653,6 +3892,8 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube"); p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction"); p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection"); + 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_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth"); @@ -3735,6 +3976,8 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE); 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 , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : 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 , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D); if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION); if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH); @@ -3850,6 +4093,8 @@ typedef struct r_cg_permutation_s CGparameter fp_Texture_Cube; CGparameter fp_Texture_Refraction; CGparameter fp_Texture_Reflection; + CGparameter fp_Texture_ShadowMapRect; + CGparameter fp_Texture_ShadowMapCube; CGparameter fp_Texture_ShadowMap2D; CGparameter fp_Texture_CubeProjection; CGparameter fp_Texture_ScreenDepth; @@ -4148,6 +4393,8 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube"); p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction"); p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection"); + p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect"); + p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube"); p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D"); p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection"); p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth"); @@ -5034,6 +5281,8 @@ extern cvar_t r_shadow_deferred_8bitrange; 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 qboolean r_shadow_usingshadowmaportho; extern float r_shadow_shadowmap_texturescale[2]; @@ -5041,7 +5290,9 @@ extern float r_shadow_shadowmap_parameters[4]; extern qboolean r_shadow_shadowmapvsdct; extern qboolean r_shadow_shadowmapsampler; extern int r_shadow_shadowmappcf; +extern rtexture_t *r_shadow_shadowmaprectangletexture; extern rtexture_t *r_shadow_shadowmap2dtexture; +extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS]; extern rtexture_t *r_shadow_shadowmap2dcolortexture; extern rtexture_t *r_shadow_shadowmapvsdcttexture; extern matrix4x4_t r_shadow_shadowmapmatrix; @@ -5239,10 +5490,15 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE); if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; - if (r_shadow_usingshadowmap2d) - { - permutation |= SHADERPERMUTATION_SHADOWMAP2D; - if(r_shadow_shadowmapvsdct) + 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_shadowmapsampler) @@ -5287,7 +5543,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) { permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; - permutation |= SHADERPERMUTATION_SHADOWMAP2D; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; if (r_shadow_shadowmapsampler) permutation |= SHADERPERMUTATION_SHADOWSAMPLER; @@ -5339,7 +5598,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) { permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; - permutation |= SHADERPERMUTATION_SHADOWMAP2D; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; if (r_shadow_shadowmapsampler) permutation |= SHADERPERMUTATION_SHADOWSAMPLER; @@ -5386,7 +5648,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) { permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; - permutation |= SHADERPERMUTATION_SHADOWMAP2D; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; if (r_shadow_shadowmapsampler) permutation |= SHADERPERMUTATION_SHADOWSAMPLER; @@ -5432,7 +5697,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)) { permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; - permutation |= SHADERPERMUTATION_SHADOWMAP2D; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; if (r_shadow_shadowmapsampler) permutation |= SHADERPERMUTATION_SHADOWSAMPLER; @@ -5777,9 +6045,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))) { if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture ); + if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture ); if (rsurface.rtlight) { if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap ); + if (r_shadow_usingshadowmapcube) + if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]); if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture ); } } @@ -5944,9 +6215,12 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))) { if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR + if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR if (rsurface.rtlight) { if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR + if (r_shadow_usingshadowmapcube) + if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR } } @@ -5991,10 +6265,15 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_shadow_glossexact.integer) permutation |= SHADERPERMUTATION_EXACTSPECULARMATH; } - if (r_shadow_usingshadowmap2d) + if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube) { - permutation |= SHADERPERMUTATION_SHADOWMAP2D; - if (r_shadow_shadowmapvsdct) + 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_shadowmapsampler) @@ -6028,6 +6307,9 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture ); R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture ); R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap ); + R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture ); + if (r_shadow_usingshadowmapcube) + R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]); R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture ); R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture ); #endif @@ -6055,6 +6337,9 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture ); if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture ); if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap ); + if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture ); + if (r_shadow_usingshadowmapcube) + if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]); if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture ); if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture ); break; @@ -6076,6 +6361,9 @@ void R_SetupShader_DeferredLight(const rtlight_t *rtlight) if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR + if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR + if (r_shadow_usingshadowmapcube) + if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR #endif diff --git a/gl_textures.c b/gl_textures.c index 455924b6..96783250 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -95,12 +95,13 @@ typedef enum gltexturetype_e GLTEXTURETYPE_2D, GLTEXTURETYPE_3D, GLTEXTURETYPE_CUBEMAP, + GLTEXTURETYPE_RECTANGLE, GLTEXTURETYPE_TOTAL } gltexturetype_t; -static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB}; -static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2}; +static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_RECTANGLE_ARB}; +static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2, 2}; static int cubemapside[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, @@ -1212,6 +1213,9 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) } } break; + case GLTEXTURETYPE_RECTANGLE: + qglTexImage2D(GL_TEXTURE_RECTANGLE_ARB, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, NULL);CHECKGLERROR + break; } GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype); qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR @@ -1315,6 +1319,9 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) } } break; + case GLTEXTURETYPE_RECTANGLE: + Sys_Error("Direct3D does not have RECTANGLE textures\n"); + break; } } glt->d3daddressw = 0; @@ -1381,6 +1388,11 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden if (cls.state == ca_dedicated) return NULL; + if (texturetype == GLTEXTURETYPE_RECTANGLE && !vid.support.arb_texture_rectangle) + { + Con_Printf ("R_LoadTexture: rectangle texture not supported by driver\n"); + return NULL; + } if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map) { Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n"); @@ -1603,6 +1615,11 @@ rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *ident return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette); } +rtexture_t *R_LoadTextureRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette) +{ + return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, miplevel, textype, GLTEXTURETYPE_RECTANGLE, data, palette); +} + static int R_ShadowMapTextureFlags(int precision, qboolean filter) { int flags = TEXF_RENDERTARGET | TEXF_CLAMP; @@ -1615,11 +1632,21 @@ static int R_ShadowMapTextureFlags(int precision, qboolean filter) return flags; } +rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter) +{ + return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL); +} + rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter) { return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL); } +rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, int precision, qboolean filter) +{ + return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL); +} + int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha) { gltexture_t *glt = (gltexture_t *)rt; diff --git a/glquake.h b/glquake.h index 46065023..c1311f49 100644 --- a/glquake.h +++ b/glquake.h @@ -406,6 +406,15 @@ extern void (GLAPIENTRY *qglCopyTexSubImage3D)(GLenum target, GLint level, GLint #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C #endif +#ifndef GL_TEXTURE_RECTANGLE_ARB +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#endif + #ifndef GL_DEPTH_COMPONENT16_ARB #define GL_DEPTH_COMPONENT16_ARB 0x81A5 #define GL_DEPTH_COMPONENT24_ARB 0x81A6 diff --git a/r_shadow.c b/r_shadow.c index 08bec055..706c6410 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -163,14 +163,18 @@ typedef enum r_shadow_rendermode_e R_SHADOW_RENDERMODE_LIGHT_GLSL, R_SHADOW_RENDERMODE_VISIBLEVOLUMES, R_SHADOW_RENDERMODE_VISIBLELIGHTING, - R_SHADOW_RENDERMODE_SHADOWMAP2D + R_SHADOW_RENDERMODE_SHADOWMAP2D, + R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE, + R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE } r_shadow_rendermode_t; typedef enum r_shadow_shadowmode_e { R_SHADOW_SHADOWMODE_STENCIL, - R_SHADOW_SHADOWMODE_SHADOWMAP2D + R_SHADOW_SHADOWMODE_SHADOWMAP2D, + R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE, + R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE } r_shadow_shadowmode_t; @@ -178,7 +182,9 @@ 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; qboolean r_shadow_usingshadowmaportho; int r_shadow_shadowmapside; float r_shadow_shadowmap_texturescale[2]; @@ -188,9 +194,12 @@ int r_shadow_drawbuffer; int r_shadow_readbuffer; #endif int r_shadow_cullface_front, r_shadow_cullface_back; +GLuint r_shadow_fborectangle; +GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS]; GLuint r_shadow_fbo2d; r_shadow_shadowmode_t r_shadow_shadowmode; int r_shadow_shadowmapfilterquality; +int r_shadow_shadowmaptexturetype; int r_shadow_shadowmapdepthbits; int r_shadow_shadowmapmaxsize; qboolean r_shadow_shadowmapvsdct; @@ -243,7 +252,9 @@ rtexture_t *r_shadow_attenuationgradienttexture; rtexture_t *r_shadow_attenuation2dtexture; rtexture_t *r_shadow_attenuation3dtexture; skinframe_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_shadowmap2dcolortexture; rtexture_t *r_shadow_shadowmapvsdcttexture; int r_shadow_shadowmapsize; // changes for each light based on distance @@ -298,6 +309,7 @@ cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compi cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "0", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"}; 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_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"}; cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"}; cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"}; cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"}; @@ -370,6 +382,7 @@ void R_Shadow_SetShadowMode(void) r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4); r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0; r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer; + r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer; r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer; r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16); r_shadow_shadowmaplod = -1; @@ -415,10 +428,32 @@ void R_Shadow_SetShadowMode(void) break; } } - r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; + switch (r_shadow_shadowmaptexturetype) + { + case 0: + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; + break; + case 1: + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE; + break; + case 2: + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE; + break; + default: + if((vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler) + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; + else if(vid.support.arb_texture_rectangle) + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE; + else + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; + break; + } // Cg has very little choice in depth texture sampling if (vid.cgcontext) + { r_shadow_shadowmapsampler = false; + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; + } break; case RENDERPATH_CGGL: case RENDERPATH_D3D9: @@ -441,6 +476,8 @@ qboolean R_Shadow_ShadowMappingEnabled(void) switch (r_shadow_shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: return true; default: return false; @@ -449,16 +486,33 @@ qboolean R_Shadow_ShadowMappingEnabled(void) void R_Shadow_FreeShadowMaps(void) { + int i; + R_Shadow_SetShadowMode(); + R_Mesh_DestroyFramebufferObject(r_shadow_fborectangle); + R_Mesh_DestroyFramebufferObject(r_shadow_fbo2d); + for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++) + R_Mesh_DestroyFramebufferObject(r_shadow_fbocubeside[i]); + r_shadow_fborectangle = 0; r_shadow_fbo2d = 0; + memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside)); + + 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; + 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)); + if (r_shadow_shadowmap2dcolortexture) R_FreeTexture(r_shadow_shadowmap2dcolortexture); r_shadow_shadowmap2dcolortexture = NULL; @@ -475,18 +529,23 @@ void r_shadow_start(void) r_shadow_attenuation2dtexture = NULL; r_shadow_attenuation3dtexture = NULL; r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL; + r_shadow_shadowmaprectangletexture = NULL; r_shadow_shadowmap2dtexture = NULL; + memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture)); r_shadow_shadowmap2dcolortexture = NULL; r_shadow_shadowmapvsdcttexture = NULL; r_shadow_shadowmapmaxsize = 0; r_shadow_shadowmapsize = 0; r_shadow_shadowmaplod = 0; r_shadow_shadowmapfilterquality = -1; + r_shadow_shadowmaptexturetype = -1; r_shadow_shadowmapdepthbits = 0; r_shadow_shadowmapvsdct = false; r_shadow_shadowmapsampler = false; r_shadow_shadowmappcf = 0; + r_shadow_fborectangle = 0; r_shadow_fbo2d = 0; + memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside)); R_Shadow_FreeShadowMaps(); @@ -655,6 +714,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_scissor); Cvar_RegisterVariable(&r_shadow_shadowmapping); Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct); + Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype); Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality); Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits); Cvar_RegisterVariable(&r_shadow_shadowmapping_precision); @@ -1945,6 +2005,8 @@ 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_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + r_shadow_usingshadowmaprect = false; + r_shadow_usingshadowmapcube = false; r_shadow_usingshadowmap2d = false; r_shadow_usingshadowmaportho = false; R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255); @@ -2024,6 +2086,20 @@ static void R_Shadow_MakeShadowMap(int side, int size) break; } break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + if (r_shadow_shadowmaprectangletexture) return; + r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", size*2, size*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler); + r_shadow_fborectangle = R_Mesh_CreateFramebufferObject(r_shadow_shadowmaprectangletexture, NULL, NULL, NULL, NULL); + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: + if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) return; + r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler); + // special trick to get an empty fbo we configure ourselves... + r_shadow_fbocubeside[r_shadow_shadowmaplod] = R_Mesh_CreateFramebufferObject(NULL, NULL, NULL, NULL, NULL); + R_Mesh_SetRenderTargets(r_shadow_fbocubeside[r_shadow_shadowmaplod], NULL, NULL, NULL, NULL, NULL); + if (qglFramebufferTexture2DEXT) + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR + break; default: return; } @@ -2059,24 +2135,58 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip); r_shadow_shadowmapside = side; r_shadow_shadowmapsize = size; + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder); + r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size; + R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL); + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done; + + // complex unrolled cube approach (more flexible) + if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture) + R_Shadow_MakeVSDCT(); + if (!r_shadow_shadowmap2dtexture) + R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize); + if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d; + 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_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder); + r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size; + R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL); + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done; + + // complex unrolled cube approach (more flexible) + if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture) + R_Shadow_MakeVSDCT(); + if (!r_shadow_shadowmaprectangletexture) + R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize); + if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle; + r_shadow_shadowmap_texturescale[0] = 1.0f; + r_shadow_shadowmap_texturescale[1] = 1.0f; + r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: + r_shadow_shadowmap_parameters[0] = 1.0f; + r_shadow_shadowmap_parameters[2] = 1.0f; + R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL); + if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done; + + // simple cube approach + if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) + R_Shadow_MakeShadowMap(side, size); + if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod]; + r_shadow_shadowmap_texturescale[0] = 0.0f; + r_shadow_shadowmap_texturescale[1] = 0.0f; + r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE; + break; + default: + break; + } - r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder); - r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size; - R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL); - if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done; - - // complex unrolled cube approach (more flexible) - if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture) - R_Shadow_MakeVSDCT(); - if (!r_shadow_shadowmap2dtexture) - R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize); - if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d; - 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_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; - - R_Mesh_ResetTextureState(); - R_Mesh_ResetRenderTargets(); R_Shadow_RenderMode_Reset(); if (fbo) { @@ -2091,66 +2201,79 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) init_done: R_SetViewport(&viewport); - flipped = (side & 1) ^ (side >> 2); - r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front; - r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back; - switch(vid.renderpath) + switch (r_shadow_rendermode) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - GL_CullFace(r_refdef.view.cullface_back); - // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once - if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask - { - // get tightest scissor rectangle that encloses all viewports in the clear mask - int x1 = clear & 0x15 ? 0 : size; - int x2 = clear & 0x2A ? 2 * size : size; - int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size); - int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size); - GL_Scissor(x1, y1, x2 - x1, y2 - y1); - GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0); - } - GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); - break; - case RENDERPATH_D3D9: - // completely different meaning than in OpenGL path - r_shadow_shadowmap_parameters[1] = 0; - r_shadow_shadowmap_parameters[3] = -bias; - // we invert the cull mode because we flip the projection matrix - // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided... - GL_CullFace(r_refdef.view.cullface_front); - // D3D considers it an error to use a scissor larger than the viewport... clear just this view - GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); - if (r_shadow_shadowmapsampler) + case R_SHADOW_RENDERMODE_SHADOWMAP2D: + case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE: + flipped = (side & 1) ^ (side >> 2); + r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front; + r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back; + switch(vid.renderpath) { + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GL20: + case RENDERPATH_CGGL: + GL_CullFace(r_refdef.view.cullface_back); + // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once + if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask + { + // get tightest scissor rectangle that encloses all viewports in the clear mask + int x1 = clear & 0x15 ? 0 : size; + int x2 = clear & 0x2A ? 2 * size : size; + int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size); + int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size); + GL_Scissor(x1, y1, x2 - x1, y2 - y1); + GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0); + } + GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); + break; + case RENDERPATH_D3D9: + // completely different meaning than in OpenGL path + r_shadow_shadowmap_parameters[1] = 0; + r_shadow_shadowmap_parameters[3] = -bias; + // we invert the cull mode because we flip the projection matrix + // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided... + GL_CullFace(r_refdef.view.cullface_front); + // D3D considers it an error to use a scissor larger than the viewport... clear just this view + GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); + if (r_shadow_shadowmapsampler) + { + GL_ColorMask(0,0,0,0); + if (clear) + GL_Clear(GL_DEPTH_BUFFER_BIT, testcolor, 1.0f, 0); + } + else + { + GL_ColorMask(1,1,1,1); + if (clear) + GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, testcolor, 1.0f, 0); + } + break; + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: + // D3D considers it an error to use a scissor larger than the viewport... clear just this view + GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); GL_ColorMask(0,0,0,0); if (clear) - GL_Clear(GL_DEPTH_BUFFER_BIT, testcolor, 1.0f, 0); - } - else - { - GL_ColorMask(1,1,1,1); - if (clear) - GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, testcolor, 1.0f, 0); + GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0); + break; } break; - case RENDERPATH_D3D10: - case RENDERPATH_D3D11: - // D3D considers it an error to use a scissor larger than the viewport... clear just this view + case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE: + if (qglFramebufferTexture2DEXT) + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); - GL_ColorMask(0,0,0,0); if (clear) GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0); break; + default: + break; } } void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping) { - R_Mesh_ResetTextureState(); - R_Mesh_ResetRenderTargets(); if (transparent) { r_shadow_lightscissor[0] = r_refdef.view.viewport.x; @@ -2165,7 +2288,23 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb // do global setup needed for the chosen lighting mode if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL) GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0); - r_shadow_usingshadowmap2d = shadowmapping; + if (shadowmapping) + { + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + r_shadow_usingshadowmap2d = true; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + r_shadow_usingshadowmaprect = true; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: + r_shadow_usingshadowmapcube = true; + break; + default: + break; + } + } r_shadow_rendermode = r_shadow_lightingrendermode; // only draw light where this geometry was already rendered AND the // stencil is 128 (values other than this mean shadow) @@ -2212,7 +2351,23 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255); R_Mesh_SetRenderTargets(r_shadow_prepasslightingfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL); - r_shadow_usingshadowmap2d = shadowmapping; + if (shadowmapping) + { + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + r_shadow_usingshadowmap2d = true; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + r_shadow_usingshadowmaprect = true; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: + r_shadow_usingshadowmapcube = true; + break; + default: + break; + } + } // render the lighting R_SetupShader_DeferredLight(rsurface.rtlight); @@ -2949,6 +3104,8 @@ void R_RTLight_Compile(rtlight_t *rtlight) switch (rtlight->shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: if (model->CompileShadowMap && rtlight->shadow) model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist); break; @@ -3312,6 +3469,8 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent) switch (r_shadow_rendermode) { case R_SHADOW_RENDERMODE_SHADOWMAP2D: + case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE: + case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE: ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs); break; default: @@ -3688,7 +3847,7 @@ void R_Shadow_DrawLight(rtlight_t *rtlight) //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_shadowmapmaxsize); - if (castshadows && r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D) + if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)) { float borderbias; int side; @@ -3703,7 +3862,10 @@ void R_Shadow_DrawLight(rtlight_t *rtlight) if ((r_shadow_shadowmapmaxsize >> i) > lodlinear) r_shadow_shadowmaplod = i; - size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize); + if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE) + size = max(1, r_shadow_shadowmapmaxsize >> r_shadow_shadowmaplod); + else + size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize); borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder); @@ -3830,7 +3992,7 @@ void R_Shadow_DrawLight(rtlight_t *rtlight) if (r_shadow_usingdeferredprepass) { // when rendering deferred lighting, we simply rasterize the box - if (castshadows && r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D) + if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)) R_Shadow_RenderMode_DrawDeferredLight(false, true); else if (castshadows && vid.stencil) R_Shadow_RenderMode_DrawDeferredLight(true, false); @@ -3961,6 +4123,7 @@ void R_Shadow_PrepareLights(void) if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4) || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) || r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) || + r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer || r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer || r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer || r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16)) @@ -4139,6 +4302,7 @@ void R_Shadow_PrepareModelShadows(void) switch (r_shadow_shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: if (r_shadows.integer >= 2) break; // fall through @@ -4216,6 +4380,7 @@ void R_DrawModelShadowMaps(void) switch (r_shadow_shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: break; default: return; @@ -4235,6 +4400,14 @@ void R_DrawModelShadowMaps(void) r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture); r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D; break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + if (!r_shadow_shadowmaprectangletexture) + R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize); + fbo = r_shadow_fborectangle; + r_shadow_shadowmap_texturescale[0] = 1.0f; + r_shadow_shadowmap_texturescale[1] = 1.0f; + r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE; + break; default: break; } @@ -4359,6 +4532,9 @@ void R_DrawModelShadowMaps(void) case R_SHADOW_SHADOWMODE_SHADOWMAP2D: r_shadow_usingshadowmap2d = true; break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + r_shadow_usingshadowmaprect = true; + break; default: break; } diff --git a/r_textures.h b/r_textures.h index 433066a7..f63224ac 100644 --- a/r_textures.h +++ b/r_textures.h @@ -128,7 +128,10 @@ extern cvar_t gl_texturecompression_reflectmask; rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, 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, int miplevel, 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, int miplevel, const unsigned int *palette); +rtexture_t *R_LoadTextureRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette); +rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter); rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter); +rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, int precision, qboolean filter); rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel); // saves a texture to a DDS file diff --git a/render.h b/render.h index 00a93ed9..b5dea8db 100644 --- a/render.h +++ b/render.h @@ -500,6 +500,8 @@ typedef enum gl20_texunit_e // conflicts with lightmap/deluxemap GL20TU_ATTENUATION = 9, GL20TU_CUBE = 10, + GL20TU_SHADOWMAPRECT = 11, + GL20TU_SHADOWMAPCUBE = 11, GL20TU_SHADOWMAP2D = 11, GL20TU_CUBEPROJECTION = 12, // orthographic-projection shadowmapping diff --git a/vid.h b/vid.h index 343e8f18..7eecb295 100644 --- a/vid.h +++ b/vid.h @@ -56,6 +56,7 @@ typedef struct viddef_support_s qboolean arb_texture_env_combine; qboolean arb_texture_gather; qboolean arb_texture_non_power_of_two; + qboolean arb_texture_rectangle; qboolean arb_vertex_buffer_object; qboolean arb_vertex_shader; qboolean ati_separate_stencil; @@ -113,6 +114,7 @@ typedef struct viddef_s unsigned int maxtexturesize_2d; unsigned int maxtexturesize_3d; unsigned int maxtexturesize_cubemap; + unsigned int maxtexturesize_rectangle; unsigned int max_anisotropy; unsigned int maxdrawbuffers; diff --git a/vid_shared.c b/vid_shared.c index 2788e3e0..eb665eed 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -851,6 +851,7 @@ void VID_CheckExtensions(void) vid.support.arb_texture_env_combine = GL_CheckExtension("GL_ARB_texture_env_combine", NULL, "-nocombine", false) || GL_CheckExtension("GL_EXT_texture_env_combine", NULL, "-nocombine", false); vid.support.arb_texture_gather = GL_CheckExtension("GL_ARB_texture_gather", NULL, "-notexturegather", false); vid.support.arb_texture_non_power_of_two = GL_CheckExtension("GL_ARB_texture_non_power_of_two", NULL, "-notexturenonpoweroftwo", false); + vid.support.arb_texture_rectangle = GL_CheckExtension("GL_ARB_texture_rectangle", NULL, "-norectangle", false); vid.support.arb_vertex_buffer_object = GL_CheckExtension("GL_ARB_vertex_buffer_object", vbofuncs, "-novbo", false); vid.support.arb_vertex_shader = GL_CheckExtension("GL_ARB_vertex_shader", vertexshaderfuncs, "-novertexshader", false); vid.support.ati_separate_stencil = GL_CheckExtension("2.0", gl2separatestencilfuncs, "-noseparatestencil", true) || GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "-noseparatestencil", false); @@ -876,6 +877,7 @@ void VID_CheckExtensions(void) // COMMANDLINEOPTION: GL: -nofragmentshader disables GL_ARB_fragment_shader (allows pixel shader effects, can improve per pixel lighting performance and capabilities) // COMMANDLINEOPTION: GL: -nomtex disables GL_ARB_multitexture (required for faster map rendering) // COMMANDLINEOPTION: GL: -noocclusionquery disables GL_ARB_occlusion_query (which allows coronas to fade according to visibility, and potentially used for rendering optimizations) +// COMMANDLINEOPTION: GL: -norectangle disables GL_ARB_texture_rectangle (required for bumpmapping) // COMMANDLINEOPTION: GL: -nos3tc disables GL_EXT_texture_compression_s3tc (which allows use of .dds texture caching) // COMMANDLINEOPTION: GL: -noseparatestencil disables use of OpenGL2.0 glStencilOpSeparate and GL_ATI_separate_stencil extensions (which accelerate shadow rendering) // COMMANDLINEOPTION: GL: -noshaderobjects disables GL_ARB_shader_objects (required for vertex shader and fragment shader) @@ -913,6 +915,8 @@ void VID_CheckExtensions(void) qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy); if (vid.support.arb_texture_cube_map) qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, (GLint*)&vid.maxtexturesize_cubemap); + if (vid.support.arb_texture_rectangle) + qglGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, (GLint*)&vid.maxtexturesize_rectangle); if (vid.support.ext_texture_3d) qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d); -- 2.39.2