From a7160f8d92d7278b9292087401847c18841852f4 Mon Sep 17 00:00:00 2001 From: eihrul Date: Thu, 4 Feb 2010 00:18:13 +0000 Subject: [PATCH] when r_shadow_shadowmapping is enabled, r_shadows uses shadowmaps instead of stencils git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9926 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 220 ++++++++++++++++++++++++++++++++++++++++------------- r_shadow.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++--- r_shadow.h | 1 + 3 files changed, 364 insertions(+), 63 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 68ca03a4..ee268807 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -253,8 +253,6 @@ const float r_screenvertex3f[12] = 0, 1, 0 }; -extern void R_DrawModelShadows(void); - void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b) { int i; @@ -896,6 +894,10 @@ static const char *builtinshaderstring = "#endif\n" "uniform vec4 FogPlane;\n" "\n" +"#ifdef USESHADOWMAPORTHO\n" +"varying vec3 ShadowMapTC;\n" +"#endif\n" +"\n" "\n" "\n" "\n" @@ -1013,7 +1015,7 @@ static const char *builtinshaderstring = "}\n" "#endif // USEOFFSETMAPPING\n" "\n" -"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n" +"#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n" "uniform sampler2D Texture_Attenuation;\n" "uniform samplerCube Texture_Cube;\n" "\n" @@ -1051,7 +1053,21 @@ static const char *builtinshaderstring = "#endif\n" "\n" "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" -"# ifndef USESHADOWMAPVSDCT\n" +"# ifdef USESHADOWMAPORTHO\n" +"# define GetShadowMapTC2D(dir) (min(dir, vec3(ShadowMap_Parameters.zw, 1.0)))\n" +"# else\n" +"# ifdef USESHADOWMAPVSDCT\n" +"vec3 GetShadowMapTC2D(vec3 dir)\n" +"{\n" +" vec3 adir = abs(dir);\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" +" return stc;\n" +"}\n" +"# else\n" "vec3 GetShadowMapTC2D(vec3 dir)\n" "{\n" " vec3 adir = abs(dir);\n" @@ -1094,17 +1110,7 @@ static const char *builtinshaderstring = " stc.z += ShadowMap_Parameters.z;\n" " return stc;\n" "}\n" -"# else\n" -"vec3 GetShadowMapTC2D(vec3 dir)\n" -"{\n" -" vec3 adir = abs(dir);\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" -" return stc;\n" -"}\n" +"# endif\n" "# endif\n" "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" "\n" @@ -1156,7 +1162,11 @@ static const char *builtinshaderstring = "# endif\n" "\n" "# endif\n" +"# ifdef USESHADOWMAPORTHO\n" +" return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n" +"# else\n" " return f;\n" +"# endif\n" "}\n" "# endif\n" "\n" @@ -1219,7 +1229,11 @@ static const char *builtinshaderstring = " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n" "# endif\n" "# endif\n" +"# ifdef USESHADOWMAPORTHO\n" +" return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n" +"# else\n" " return f;\n" +"# endif\n" "}\n" "# endif\n" "\n" @@ -1237,7 +1251,7 @@ static const char *builtinshaderstring = " return f;\n" "}\n" "# endif\n" -"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n" +"#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n" "#endif // FRAGMENT_SHADER\n" "\n" "\n" @@ -1398,6 +1412,9 @@ static const char *builtinshaderstring = "#ifdef MODE_LIGHTSOURCE\n" "uniform mat4 ModelToLight;\n" "#endif\n" +"#ifdef USESHADOWMAPORTHO\n" +"uniform mat4 ShadowMapMatrix;\n" +"#endif\n" "void main(void)\n" "{\n" "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n" @@ -1456,6 +1473,10 @@ static const char *builtinshaderstring = " // transform vertex to camera space, using ftransform to match non-VS rendering\n" " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n" "\n" +"#ifdef USESHADOWMAPORTHO\n" +" ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n" +"#endif\n" +"\n" "#ifdef USEREFLECTION\n" " ModelViewProjectionPosition = gl_Position;\n" "#endif\n" @@ -1651,6 +1672,10 @@ static const char *builtinshaderstring = "# endif\n" "#endif\n" "\n" +"#ifdef USESHADOWMAPORTHO\n" +" color.rgb *= ShadowMapCompare(ShadowMapTC);\n" +"#endif\n" +"\n" "#ifdef USEDEFERREDLIGHTMAP\n" " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n" " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n" @@ -2186,7 +2211,18 @@ const char *builtincgshaderstring = "\n" "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n" "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" -"# ifndef USESHADOWMAPVSDCT\n" +"# ifdef USESHADOWMAPVSDCT\n" +"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n" +"{\n" +" float3 adir = abs(dir);\n" +" float4 proj = texCUBE(Texture_CubeProjection, dir);\n" +" float ma = max(max(adir.x, adir.y), adir.z);\n" +" float3 stc = float3(lerp(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" +" return stc;\n" +"}\n" +"# else\n" "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n" "{\n" " float3 adir = abs(dir);\n" @@ -2229,17 +2265,6 @@ const char *builtincgshaderstring = " stc.z += ShadowMap_Parameters.z;\n" " return stc;\n" "}\n" -"# else\n" -"float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n" -"{\n" -" float3 adir = abs(dir);\n" -" float4 proj = texCUBE(Texture_CubeProjection, dir);\n" -" float ma = max(max(adir.x, adir.y), adir.z);\n" -" float3 stc = float3(lerp(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" -" return stc;\n" -"}\n" "# endif\n" "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n" "\n" @@ -3214,11 +3239,12 @@ typedef enum shaderpermutation_e SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing - 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_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection + SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping + SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5 + SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe) + SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array + SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array } shaderpermutation_t; @@ -3249,6 +3275,7 @@ shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] = {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, {"#define USESHADOWSAMPLER\n", " shadowsampler"}, {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, + {"#define USESHADOWMAPORTHO\n", " shadowmaportho"}, {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"}, {"#define USEALPHAKILL\n", " alphakill"}, {"#define USEREFLECTCUBE\n", " reflectcube"}, @@ -3410,6 +3437,7 @@ typedef struct r_glsl_permutation_s int loc_ModelViewMatrix; int loc_PixelToScreenTexCoord; int loc_ModelToReflectCube; + int loc_ShadowMapMatrix; } r_glsl_permutation_t; @@ -3635,6 +3663,7 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix"); p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord"); p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube"); + p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix"); // initialize the samplers to refer to the texture units we use if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST); if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND); @@ -3750,6 +3779,7 @@ typedef struct r_cg_permutation_s CGparameter vp_BackgroundTexMatrix; CGparameter vp_ModelViewProjectionMatrix; CGparameter vp_ModelViewMatrix; + CGparameter vp_ShadowMapMatrix; CGparameter fp_Texture_First; CGparameter fp_Texture_Second; @@ -4041,6 +4071,7 @@ static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, un p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix"); p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix"); p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix"); + p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix"); CHECKCGERROR } if (p->fprogram) @@ -4402,6 +4433,7 @@ 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]; extern float r_shadow_shadowmap_parameters[4]; extern qboolean r_shadow_shadowmapvsdct; @@ -4411,6 +4443,7 @@ 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_shadowmapvsdcttexture; +extern matrix4x4_t r_shadow_shadowmapmatrix; extern int r_shadow_shadowmaplod; // changes for each light based on distance extern int r_shadow_prepass_width; extern int r_shadow_prepass_height; @@ -4559,6 +4592,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE; if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; + if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d)) + { + permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; + + if (r_shadow_shadowmapsampler) + permutation |= SHADERPERMUTATION_SHADOWSAMPLER; + if (r_shadow_shadowmappcf > 1) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF2; + else if (r_shadow_shadowmappcf) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF; + } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; if (rsurface.texture->reflectmasktexture) @@ -4609,6 +4657,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE; if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; + if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d)) + { + permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; + + if (r_shadow_shadowmapsampler) + permutation |= SHADERPERMUTATION_SHADOWSAMPLER; + if (r_shadow_shadowmappcf > 1) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF2; + else if (r_shadow_shadowmappcf) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF; + } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)) @@ -4651,6 +4714,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE; if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; + if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d)) + { + permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; + + if (r_shadow_shadowmapsampler) + permutation |= SHADERPERMUTATION_SHADOWSAMPLER; + if (r_shadow_shadowmappcf > 1) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF2; + else if (r_shadow_shadowmappcf) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF; + } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)) @@ -4692,6 +4770,21 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE; if (rsurface.texture->colormapping) permutation |= SHADERPERMUTATION_COLORMAPPING; + if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d)) + { + permutation |= SHADERPERMUTATION_SHADOWMAPORTHO; + if (r_shadow_usingshadowmaprect) + permutation |= SHADERPERMUTATION_SHADOWMAPRECT; + if (r_shadow_usingshadowmap2d) + permutation |= SHADERPERMUTATION_SHADOWMAP2D; + + if (r_shadow_shadowmapsampler) + permutation |= SHADERPERMUTATION_SHADOWSAMPLER; + if (r_shadow_shadowmappcf > 1) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF2; + else if (r_shadow_shadowmappcf) + permutation |= SHADERPERMUTATION_SHADOWMAPPCF; + } if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) permutation |= SHADERPERMUTATION_REFLECTION; if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED)) @@ -4785,8 +4878,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted if (r_glsl_permutation->loc_FogColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0); - if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); - if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f)); } else @@ -4832,6 +4923,10 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);} if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);} + if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);} + if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]); + if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]); + if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]); if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]); if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]); @@ -4882,14 +4977,17 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture ); if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture ); if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture ); - if (rsurface.rtlight) + if (rsurface.rtlight || r_shadow_usingshadowmaportho) { - 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 ); + if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(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 ); + } } CHECKGLERROR break; @@ -4911,6 +5009,7 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, } if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR + if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR CHECKGLERROR @@ -4925,8 +5024,6 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, // additive passes are only darkened by fog, not tinted if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR - if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR - if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR } else @@ -4971,6 +5068,8 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR } + if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR + if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR @@ -5023,14 +5122,17 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, 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_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR - if (rsurface.rtlight) + if (rsurface.rtlight || r_shadow_usingshadowmaportho) { - 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 + 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 + } } CHECKGLERROR @@ -8159,10 +8261,14 @@ extern cvar_t cl_locs_show; static void R_DrawLocs(void); static void R_DrawEntityBBoxes(void); static void R_DrawModelDecals(void); +extern void R_DrawModelShadows(void); +extern void R_DrawModelShadowMaps(void); extern cvar_t cl_decals_newsystem; extern qboolean r_shadow_usingdeferredprepass; void R_RenderScene(void) { + qboolean shadowmapping = false; + r_refdef.stats.renders++; R_UpdateFogColor(); @@ -8212,6 +8318,9 @@ void R_RenderScene(void) if (r_timereport_active) R_TimeReport("preparelights"); + if (R_Shadow_ShadowMappingEnabled()) + shadowmapping = true; + if (r_shadow_usingdeferredprepass) R_Shadow_DrawPrepass(); @@ -8228,6 +8337,15 @@ void R_RenderScene(void) R_TimeReport("modeldepth"); } + if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0) + { + R_DrawModelShadowMaps(); + R_ResetViewRendering3D(); + // don't let sound skip if going slow + if (r_refdef.scene.extraupdate) + S_ExtraUpdate (); + } + if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw) { r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity); @@ -8247,7 +8365,7 @@ void R_RenderScene(void) if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) + if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_DrawModelShadows(); R_ResetViewRendering3D(); @@ -8267,7 +8385,7 @@ void R_RenderScene(void) if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) + if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0) { R_DrawModelShadows(); R_ResetViewRendering3D(); diff --git a/r_shadow.c b/r_shadow.c index 7c16c17e..734c43e4 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -180,6 +180,7 @@ r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_N 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]; float r_shadow_shadowmap_parameters[4]; @@ -200,6 +201,7 @@ qboolean r_shadow_shadowmapvsdct; qboolean r_shadow_shadowmapsampler; int r_shadow_shadowmappcf; int r_shadow_shadowmapborder; +matrix4x4_t r_shadow_shadowmapmatrix; int r_shadow_lightscissor[4]; qboolean r_shadow_usingdeferredprepass; @@ -449,6 +451,19 @@ void R_Shadow_SetShadowMode(void) } } +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; + } +} + void R_Shadow_FreeShadowMaps(void) { int i; @@ -490,6 +505,8 @@ void R_Shadow_FreeShadowMaps(void) r_shadow_shadowmapvsdcttexture = NULL; CHECKGLERROR + + r_shadow_usingshadowmaportho = false; } void r_shadow_start(void) @@ -2086,6 +2103,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) { float nearclip, farclip, bias; r_viewport_t viewport; + int flipped; GLuint fbo = 0; CHECKGLERROR nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius; @@ -2170,9 +2188,11 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) init_done: R_SetViewport(&viewport); - if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) + switch (r_shadow_rendermode) { - int flipped = (side & 1) ^ (side >> 2); + 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; GL_CullFace(r_refdef.view.cullface_back); @@ -2187,13 +2207,15 @@ init_done: GL_Clear(GL_DEPTH_BUFFER_BIT); } GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height); - } - else if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) - { + break; + case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE: 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); if (clear) GL_Clear(GL_DEPTH_BUFFER_BIT); + break; + default: + break; } CHECKGLERROR } @@ -2230,12 +2252,20 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb } if (shadowmapping) { - if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D) + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: r_shadow_usingshadowmap2d = true; - else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE) + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: r_shadow_usingshadowmaprect = true; - else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE) + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: r_shadow_usingshadowmapcube = true; + break; + default: + break; + } } R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0); CHECKGLERROR @@ -3345,12 +3375,17 @@ void R_Shadow_DrawEntityShadow(entity_render_t *ent) relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius; relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius; relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius; - if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) + 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); - } - else + break; + default: ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs); + break; + } rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } @@ -4001,6 +4036,8 @@ void R_Shadow_PrepareLights(void) r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16)) R_Shadow_FreeShadowMaps(); + r_shadow_usingshadowmaportho = false; + switch (vid.renderpath) { case RENDERPATH_GL20: @@ -4158,6 +4195,151 @@ extern cvar_t r_shadows_drawafterrtlighting; extern cvar_t r_shadows_castfrombmodels; extern cvar_t r_shadows_throwdistance; extern cvar_t r_shadows_throwdirection; + +void R_DrawModelShadowMaps(void) +{ + int i; + float relativethrowdistance, scale, size, nearclip, farclip, dot1, dot2; + entity_render_t *ent; + vec3_t relativelightorigin; + vec3_t relativelightdirection; + vec3_t relativeshadowmins, relativeshadowmaxs; + vec3_t shadowdir, shadowforward; + float m[12]; + matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix; + r_viewport_t viewport; + GLuint fbo = 0; + + if (!r_refdef.scene.numentities) + return; + + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + break; + default: + return; + } + + CHECKGLERROR + R_ResetViewRendering3D(); + R_Shadow_RenderMode_Begin(); + R_Shadow_RenderMode_ActiveLight(NULL); + + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + if (!r_shadow_shadowmap2dtexture) + R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize); + 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: + 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; + } + + size = 2*r_shadow_shadowmapmaxsize; + + r_shadow_shadowmap_parameters[0] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f); + r_shadow_shadowmap_parameters[1] = 1.0f; + r_shadow_shadowmap_parameters[2] = size; + r_shadow_shadowmap_parameters[3] = size; + + scale = r_shadow_shadowmapping_precision.value; + nearclip = -r_shadows_throwdistance.value; + farclip = r_shadows_throwdistance.value; + Math_atov(r_shadows_throwdirection.string, shadowdir); + VectorNormalize(shadowdir); + dot1 = DotProduct(r_refdef.view.forward, shadowdir); + dot2 = DotProduct(r_refdef.view.up, shadowdir); + if (fabs(dot1) <= fabs(dot2)) + VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward); + else + VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward); + VectorNormalize(shadowforward); + VectorM(scale, shadowforward, &m[0]); + m[3] = fabs(dot1) * 0.5f * size - DotProduct(r_refdef.view.origin, &m[0]); + CrossProduct(shadowdir, shadowforward, &m[4]); + VectorM(scale, &m[4], &m[4]); + m[7] = 0.5f * size - DotProduct(r_refdef.view.origin, &m[4]); + VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]); + m[11] = 0.5f - DotProduct(r_refdef.view.origin, &m[8]); + Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m); + Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix); + R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, size, size, 0, 0, -1, NULL); + +#if 0 + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR + R_SetupShader_ShowDepth(); +#else + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR + R_SetupShader_DepthOrShadow(); +#endif + CHECKGLERROR + GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value); + GL_DepthMask(true); + GL_DepthTest(true); + R_SetViewport(&viewport); + GL_Scissor(viewport.x, viewport.y, viewport.width + r_shadow_shadowmapborder, viewport.height + r_shadow_shadowmapborder); + qglClearDepth(1); +#if 0 + qglClearColor(1,1,1,1); + GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +#else + GL_Clear(GL_DEPTH_BUFFER_BIT); +#endif + GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder); + CHECKGLERROR + + for (i = 0;i < r_refdef.scene.numentities;i++) + { + ent = r_refdef.scene.entities[i]; + + // cast shadows from anything of the map (submodels are optional) + if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + { + relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix); + VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance); + VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance); + Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); + VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin); + RSurf_ActiveModelEntity(ent, false, false, false); + ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs); + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity + } + } + + R_Shadow_RenderMode_End(); + + Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix); + Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix); + Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &shadowmatrix, &invmvpmatrix); + + r_shadow_usingshadowmaportho = true; + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + r_shadow_usingshadowmap2d = true; + break; + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + r_shadow_usingshadowmaprect = true; + break; + default: + break; + } +} + void R_DrawModelShadows(void) { int i; @@ -4168,7 +4350,7 @@ void R_DrawModelShadows(void) vec3_t relativeshadowmins, relativeshadowmaxs; vec3_t tmp, shadowdir; - if (!r_refdef.scene.numentities || !vid.stencil) + if (!r_refdef.scene.numentities || !vid.stencil || r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) return; CHECKGLERROR diff --git a/r_shadow.h b/r_shadow.h index ac32dc33..93ccb2bd 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -38,6 +38,7 @@ extern cvar_t gl_ext_separatestencil; extern cvar_t gl_ext_stenciltwoside; void R_Shadow_Init(void); +qboolean R_Shadow_ShadowMappingEnabled(void); void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, const vec3_t projectdirection, float projectdistance, int nummarktris, const int *marktris, vec3_t trismins, vec3_t trismaxs); void R_Shadow_ShadowMapFromList(int numverts, int numtris, const float *vertex3f, const int *elements, int numsidetris, const int *sidetotals, const unsigned char *sides, const int *sidetris); void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs); -- 2.39.2