X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=87609f7c21b9edf3339fddad2be3a72b6790aef9;hb=135e0beb0c30b770396161df034c0e5e0c100c04;hp=8b43bf44b6b477a202928a49a4dc3952c4373ba6;hpb=ea4908b279c9f7752cafa403a056dcc85626a553;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index 8b43bf44..87609f7c 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -314,14 +314,14 @@ cvar_t r_shadow_realtime_world_compileshadow = {0, "r_shadow_realtime_world_comp cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"}; cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "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", "1", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"}; +cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "1", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes"}; 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_useshadowsampler = {CVAR_SAVE, "r_shadow_shadowmapping_useshadowsampler", "1", "whether to use sampler2DShadow if available"}; 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"}; cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "limit of shadowmap side size - must be at least r_shadow_shadowmapping_bordersize+2"}; cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "limit of shadowmap side size - can not be more than 1/8th of atlassize because lights store 6 sides (2x3 grid) and sometimes 12 sides (4x3 grid for shadows from EF_NOSELFSHADOW entities) and there are multiple lights..."}; -cvar_t r_shadow_shadowmapping_texturesize = { CVAR_SAVE, "r_shadow_shadowmapping_texturesize", "4096", "size of shadowmap atlas texture - all shadowmaps are packed into this texture at frame start"}; +cvar_t r_shadow_shadowmapping_texturesize = { CVAR_SAVE, "r_shadow_shadowmapping_texturesize", "8192", "size of shadowmap atlas texture - all shadowmaps are packed into this texture at frame start"}; cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"}; //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"}; //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"}; @@ -464,19 +464,19 @@ static void R_Shadow_SetShadowMode(void) { if (!r_fb.usedepthtextures) r_shadow_shadowmappcf = 1; - else if((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && vid.support.arb_shadow && r_shadow_shadowmapshadowsampler) + else if((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && vid.support.arb_shadow && r_shadow_shadowmapshadowsampler) { r_shadow_shadowmapsampler = true; r_shadow_shadowmappcf = 1; } else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) r_shadow_shadowmappcf = 1; - else if((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa")) + else if((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa")) r_shadow_shadowmappcf = 1; - else + else r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler; } - else + else { r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler; switch (r_shadow_shadowmapfilterquality) @@ -1607,7 +1607,7 @@ static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float borde int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 }; float scale = (size - 2*border)/size, len; float bias = border / (float)(size - border), dp, dn, ap, an; - // check if cone enclosing side would cross frustum plane + // check if cone enclosing side would cross frustum plane scale = 2 / (scale*scale + 2); Matrix4x4_OriginFromMatrix(&rtlight->matrix_lighttoworld, o); for (i = 0;i < 5;i++) @@ -2565,7 +2565,7 @@ static void R_Shadow_BounceGrid_GenerateSettings(r_shadow_bouncegrid_settings_t float bounceminimumintensity = s ? r_shadow_bouncegrid_static_bounceminimumintensity.value : r_shadow_bouncegrid_dynamic_bounceminimumintensity.value; // prevent any garbage in alignment padded areas as we'll be using memcmp - memset(settings, 0, sizeof(*settings)); + memset(settings, 0, sizeof(*settings)); // build up a complete collection of the desired settings, so that memcmp can be used to compare parameters settings->staticmode = s; @@ -2626,8 +2626,54 @@ static void R_Shadow_BounceGrid_UpdateSpacing(void) // calculate texture size enclosing entire world bounds at the spacing if (r_refdef.scene.worldmodel) { - VectorMA(r_refdef.scene.worldmodel->normalmins, -2.0f, spacing, mins); - VectorMA(r_refdef.scene.worldmodel->normalmaxs, 2.0f, spacing, maxs); + int lightindex; + int range; + qboolean bounds_set = false; + dlight_t *light; + rtlight_t *rtlight; + + // calculate bounds enclosing world lights as they should be noticably tighter + // than the world bounds on maps with unlit monster containers (see e1m7 etc) + range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked + for (lightindex = 0;lightindex < range;lightindex++) + { + const vec_t *rtlmins, *rtlmaxs; + + light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); + if (!light) + continue; + + rtlight = &light->rtlight; + rtlmins = rtlight->cullmins; + rtlmaxs = rtlight->cullmaxs; + + if (!bounds_set) + { + VectorCopy(rtlmins, mins); + VectorCopy(rtlmaxs, maxs); + bounds_set = true; + } + else + { + mins[0] = min(mins[0], rtlmins[0]); + mins[1] = min(mins[1], rtlmins[1]); + mins[2] = min(mins[2], rtlmins[2]); + maxs[0] = max(maxs[0], rtlmaxs[0]); + maxs[1] = max(maxs[1], rtlmaxs[1]); + maxs[2] = max(maxs[2], rtlmaxs[2]); + } + } + + // limit to no larger than the world bounds + mins[0] = max(mins[0], r_refdef.scene.worldmodel->normalmins[0]); + mins[1] = max(mins[1], r_refdef.scene.worldmodel->normalmins[1]); + mins[2] = max(mins[2], r_refdef.scene.worldmodel->normalmins[2]); + maxs[0] = min(maxs[0], r_refdef.scene.worldmodel->normalmaxs[0]); + maxs[1] = min(maxs[1], r_refdef.scene.worldmodel->normalmaxs[1]); + maxs[2] = min(maxs[2], r_refdef.scene.worldmodel->normalmaxs[2]); + + VectorMA(mins, -2.0f, spacing, mins); + VectorMA(maxs, 2.0f, spacing, maxs); } else { @@ -5600,7 +5646,7 @@ static void R_Shadow_DrawModelShadowMaps(void) VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin); dot1 = DotProduct(r_refdef.view.forward, shadowdir); dot2 = DotProduct(r_refdef.view.up, shadowdir); - if (fabs(dot1) <= fabs(dot2)) + if (fabs(dot1) <= fabs(dot2)) VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward); else VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward); @@ -5660,7 +5706,7 @@ static void R_Shadow_DrawModelShadowMaps(void) Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix); Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix); - Matrix4x4_CreateScale3(&scalematrix, size, -size, 1); + Matrix4x4_CreateScale3(&scalematrix, size, -size, 1); Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias); Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix); Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix); @@ -5889,13 +5935,10 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) { switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) - CHECKGLERROR // See if we can use the GPU-side method to prevent implicit sync if (vid.support.arb_query_buffer_object) { #define BUFFER_OFFSET(i) ((GLint *)((unsigned char*)NULL + (i))) @@ -5910,13 +5953,23 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4)); qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf); occlude = MATERIALFLAG_OCCLUDE; - } else { - qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels); - qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels); - if (visiblepixels < 1 || allpixels < 1) - return; - rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1); + cscale *= rtlight->corona_visibility; + CHECKGLERROR + break; } + // fallthrough +#else + return; +#endif + case RENDERPATH_GL11: + case RENDERPATH_GL13: +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) + CHECKGLERROR + qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels); + qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels); + if (visiblepixels < 1 || allpixels < 1) + return; + rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1); cscale *= rtlight->corona_visibility; CHECKGLERROR break;