X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=b97ae62d2a089a90578e6ffe1cbea4880b6179f8;hb=d328b3f12f6e49d373f37c16955679e61f7dc2b6;hp=f0c23bfea06600ea9c89410cfd5c840728a4daec;hpb=39017f0c52fcb627489fefa55112a0497d07b6e6;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index f0c23bfe..b97ae62d 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -269,6 +269,9 @@ static rtexture_t *r_shadow_fb_colortexture; // lights are reloaded when this changes char r_shadow_mapname[MAX_QPATH]; +// buffer for doing corona fading +unsigned int r_shadow_occlusion_buf = 0; + // used only for light filters (cubemaps) rtexturepool_t *r_shadow_filters_texturepool; @@ -295,6 +298,7 @@ cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_ cvar_t r_shadow_realtime_dlight_svbspculling = {0, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"}; cvar_t r_shadow_realtime_dlight_portalculling = {0, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"}; cvar_t r_shadow_realtime_world = {CVAR_SAVE, "r_shadow_realtime_world", "0", "enables rendering of full world lighting (whether loaded from the map, or a .rtlights file, or a .ent file, or a .lights file produced by hlight)"}; +cvar_t r_shadow_realtime_world_importlightentitiesfrommap = {0, "r_shadow_realtime_world_importlightentitiesfrommap", "1", "load lights from .ent file or map entities at startup if no .rtlights or .lights file is present (if set to 2, always use the .ent or map entities)"}; cvar_t r_shadow_realtime_world_lightmaps = {CVAR_SAVE, "r_shadow_realtime_world_lightmaps", "0", "brightness to render lightmaps when using full world lighting, try 0.5 for a tenebrae-like appearance"}; cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"}; cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"}; @@ -732,6 +736,7 @@ void R_Shadow_Init(void) Cvar_RegisterVariable(&r_shadow_lightradiusscale); Cvar_RegisterVariable(&r_shadow_projectdistance); Cvar_RegisterVariable(&r_shadow_frontsidecasting); + Cvar_RegisterVariable(&r_shadow_realtime_world_importlightentitiesfrommap); Cvar_RegisterVariable(&r_shadow_realtime_dlight); Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows); Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling); @@ -1384,7 +1389,7 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES) { tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris); - R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL); + R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0); R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); } else @@ -1396,8 +1401,8 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris); else tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris); - r_refdef.stats.lights_dynamicshadowtriangles += tris; - r_refdef.stats.lights_shadowtriangles += tris; + r_refdef.stats[r_stat_lights_dynamicshadowtriangles] += tris; + r_refdef.stats[r_stat_lights_shadowtriangles] += tris; if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL) { // increment stencil if frontface is infront of depthbuffer @@ -1418,7 +1423,7 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, GL_CullFace(r_refdef.view.cullface_back); R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255); } - R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL); + R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0); R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); } } @@ -2063,7 +2068,7 @@ void R_Shadow_RenderMode_Reset(void) void R_Shadow_ClearStencil(void) { GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 128); - r_refdef.stats.lights_clears++; + r_refdef.stats[r_stat_lights_clears]++; } void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass) @@ -2321,7 +2326,7 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow GL_DepthTest(true); GL_DepthFunc(GL_GREATER); GL_CullFace(r_refdef.view.cullface_back); - R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL); + R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL, 0); R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); } @@ -2418,7 +2423,7 @@ void R_Shadow_UpdateBounceGridTexture(void) if (enable && r_shadow_bouncegrid_static.integer) { enable = false; - range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked + range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked for (lightindex = 0;lightindex < range;lightindex++) { light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); @@ -2605,7 +2610,7 @@ void R_Shadow_UpdateBounceGridTexture(void) // clear variables that produce warnings otherwise memset(splatcolor, 0, sizeof(splatcolor)); // iterate world rtlights - range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked + range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked range1 = settings.staticmode ? 0 : r_refdef.scene.numlights; range2 = range + range1; photoncount = 0; @@ -2651,7 +2656,7 @@ void R_Shadow_UpdateBounceGridTexture(void) w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale); if (w * VectorLength2(rtlight->color) == 0.0f) continue; - w *= (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1); + w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1); VectorScale(rtlight->color, w, rtlight->photoncolor); //if (!VectorLength2(rtlight->photoncolor)) // continue; @@ -2694,8 +2699,8 @@ void R_Shadow_UpdateBounceGridTexture(void) radius = rtlight->radius * settings.lightradiusscale; s = settings.particleintensity / shootparticles; VectorScale(rtlight->photoncolor, s, baseshotcolor); - r_refdef.stats.bouncegrid_lights++; - r_refdef.stats.bouncegrid_particles += shootparticles; + r_refdef.stats[r_stat_bouncegrid_lights]++; + r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles; for (shotparticles = 0;shotparticles < shootparticles;shotparticles++) { if (settings.stablerandom > 0) @@ -2709,13 +2714,13 @@ void R_Shadow_UpdateBounceGridTexture(void) VectorMA(clipstart, radius, clipend, clipend); for (bouncecount = 0;;bouncecount++) { - r_refdef.stats.bouncegrid_traces++; + r_refdef.stats[r_stat_bouncegrid_traces]++; //r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask); //r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask); if (settings.staticmode) { // static mode fires a LOT of rays but none of them are identical, so they are not cached - cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, true, false, NULL, true, true); + cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, collision_extendmovelength.value, true, false, NULL, true, true); } else { @@ -2775,7 +2780,7 @@ void R_Shadow_UpdateBounceGridTexture(void) VectorMA(clipstart, 0.5f, stepdelta, steppos); for (step = 0;step < numsteps;step++) { - r_refdef.stats.bouncegrid_splats++; + r_refdef.stats[r_stat_bouncegrid_splats]++; // figure out which texture pixel this is in texlerp[1][0] = ((steppos[0] - mins[0]) * ispacing[0]) - 0.5f; texlerp[1][1] = ((steppos[1] - mins[1]) * ispacing[1]) - 0.5f; @@ -2829,7 +2834,7 @@ void R_Shadow_UpdateBounceGridTexture(void) } if (cliptrace.fraction >= 1.0f) break; - r_refdef.stats.bouncegrid_hits++; + r_refdef.stats[r_stat_bouncegrid_hits]++; if (bouncecount >= maxbounce) break; // scale down shot color by bounce intensity and texture color (or 50% if no texture reported) @@ -2845,7 +2850,7 @@ void R_Shadow_UpdateBounceGridTexture(void) VectorMultiply(shotcolor, surfcolor, shotcolor); if (VectorLength2(baseshotcolor) == 0.0f) break; - r_refdef.stats.bouncegrid_bounces++; + r_refdef.stats[r_stat_bouncegrid_bounces]++; if (settings.bounceanglediffuse) { // random direction, primarily along plane normal @@ -2991,7 +2996,7 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) || r_shadow_lightscissor[1] != r_refdef.view.viewport.y || r_shadow_lightscissor[2] != r_refdef.view.viewport.width || r_shadow_lightscissor[3] != r_refdef.view.viewport.height) - r_refdef.stats.lights_scissored++; + r_refdef.stats[r_stat_lights_scissored]++; return false; } @@ -3527,7 +3532,7 @@ void R_RTLight_Compile(rtlight_t *rtlight) lighttris++; shadowtris = 0; - if (rtlight->static_numlighttrispvsbytes) + if (rtlight->static_numshadowtrispvsbytes) for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++) if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i)) shadowtris++; @@ -3764,11 +3769,8 @@ static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist { if (!mesh->sidetotals[r_shadow_shadowmapside]) continue; - r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside]; - if (mesh->vertex3fbuffer) - R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer); - else - R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer); + r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->sidetotals[r_shadow_shadowmapside]; + R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f); R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); } CHECKGLERROR @@ -3804,11 +3806,8 @@ static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacel mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail; for (;mesh;mesh = mesh->next) { - r_refdef.stats.lights_shadowtriangles += mesh->numtriangles; - if (mesh->vertex3fbuffer) - R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer); - else - R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer); + r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->numtriangles; + R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL) { // increment stencil if frontface is infront of depthbuffer @@ -3939,6 +3938,7 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight) static entity_render_t *shadowentities[MAX_EDICTS]; static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS]; qboolean nolight; + qboolean castshadows; rtlight->draw = false; rtlight->cached_numlightentities = 0; @@ -3973,7 +3973,7 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight) rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube; // look up the light style value at this time - f = (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value; + f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value; VectorScale(rtlight->color, f, rtlight->currentcolor); /* if (rtlight->selected) @@ -4129,18 +4129,21 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight) return; // count this light in the r_speeds - r_refdef.stats.lights++; + r_refdef.stats[r_stat_lights]++; // flag it as worth drawing later rtlight->draw = true; + // if we have shadows disabled, don't count the shadow entities, this way we don't do the R_AnimCache_GetEntity on each one + castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows); + if (!castshadows) + numshadowentities = numshadowentities_noselfshadow = 0; + // cache all the animated entities that cast a shadow but are not visible for (i = 0;i < numshadowentities;i++) - if (!shadowentities[i]->animcache_vertex3f) - R_AnimCache_GetEntity(shadowentities[i], false, false); + R_AnimCache_GetEntity(shadowentities[i], false, false); for (i = 0;i < numshadowentities_noselfshadow;i++) - if (!shadowentities_noselfshadow[i]->animcache_vertex3f) - R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false); + R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false); // allocate some temporary memory for rendering this light later in the frame // reusable buffers need to be copied, static data can be used as-is @@ -4631,7 +4634,7 @@ void R_Shadow_PrepareLights(int fbo, rtexture_t *depthtexture, rtexture_t *color for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++) { rtlight_t *rtlight = r_refdef.scene.lights[lnum]; - f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value; + f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value; VectorScale(rtlight->color, f, rtlight->currentcolor); } } @@ -4675,6 +4678,10 @@ void R_Shadow_DrawLights(void) R_Shadow_RenderMode_End(); } +#define MAX_MODELSHADOWS 1024 +static int r_shadow_nummodelshadows; +static entity_render_t *r_shadow_modelshadows[MAX_MODELSHADOWS]; + void R_Shadow_PrepareModelShadows(void) { int i; @@ -4683,6 +4690,7 @@ void R_Shadow_PrepareModelShadows(void) vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs; entity_render_t *ent; + r_shadow_nummodelshadows = 0; if (!r_refdef.scene.numentities) return; @@ -4693,11 +4701,18 @@ void R_Shadow_PrepareModelShadows(void) break; // fall through case R_SHADOW_SHADOWMODE_STENCIL: + if (!vid.stencil) + return; for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; - if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + { + if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS) + break; + r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent; R_AnimCache_GetEntity(ent, false, false); + } } return; default: @@ -4742,8 +4757,13 @@ void R_Shadow_PrepareModelShadows(void) if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs)) continue; // cast shadows from anything of the map (submodels are optional) - if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + { + if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS) + break; + r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent; R_AnimCache_GetEntity(ent, false, false); + } } } @@ -4763,7 +4783,7 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort GLuint shadowfbo = 0; float clearcolor[4]; - if (!r_refdef.scene.numentities) + if (!r_shadow_nummodelshadows) return; switch (r_shadow_shadowmode) @@ -4861,28 +4881,23 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort // outside the usable area GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder); - 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); - Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin); - Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); - Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward); - Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright); - relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0])); - relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); - relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); - relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0])); - relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); - relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); - 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 - } + for (i = 0;i < r_shadow_nummodelshadows;i++) + { + ent = r_shadow_modelshadows[i]; + relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix); + Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin); + Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); + Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward); + Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright); + relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0])); + relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); + relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); + relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0])); + relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); + relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); + 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 } #if 0 @@ -4919,7 +4934,7 @@ void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colort case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: -#ifdef OPENGL_ORIENTATION +#ifdef MATRIX4x4_OPENGLORIENTATION r_shadow_shadowmapmatrix.m[0][0] *= -1.0f; r_shadow_shadowmapmatrix.m[0][1] *= -1.0f; r_shadow_shadowmapmatrix.m[0][2] *= -1.0f; @@ -4955,7 +4970,7 @@ void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortext vec3_t tmp, shadowdir; prvm_vec3_t prvmshadowdir; - if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1)) + if (!r_shadow_nummodelshadows || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1)) return; r_shadow_fb_fbo = fbo; @@ -4983,60 +4998,57 @@ void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortext R_Shadow_ClearStencil(); - for (i = 0;i < r_refdef.scene.numentities;i++) + for (i = 0;i < r_shadow_nummodelshadows;i++) { - ent = r_refdef.scene.entities[i]; + ent = r_shadow_modelshadows[i]; // cast shadows from anything of the map (submodels are optional) - if (ent->model && ent->model->DrawShadowVolume != 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); + if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction + Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); + else { - relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix); - VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance); - VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance); - if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction - Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); - else + if(ent->entitynumber != 0) { - if(ent->entitynumber != 0) + if(ent->entitynumber >= MAX_EDICTS) // csqc entity + { + // FIXME handle this + VectorNegate(ent->modellight_lightdir, relativelightdirection); + } + else { - if(ent->entitynumber >= MAX_EDICTS) // csqc entity + // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities) + int entnum, entnum2, recursion; + entnum = entnum2 = ent->entitynumber; + for(recursion = 32; recursion > 0; --recursion) { - // FIXME handle this - VectorNegate(ent->modellight_lightdir, relativelightdirection); + entnum2 = cl.entities[entnum].state_current.tagentity; + if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2]) + entnum = entnum2; + else + break; } - else + if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain { - // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities) - int entnum, entnum2, recursion; - entnum = entnum2 = ent->entitynumber; - for(recursion = 32; recursion > 0; --recursion) - { - entnum2 = cl.entities[entnum].state_current.tagentity; - if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2]) - entnum = entnum2; - else - break; - } - if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain - { - VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection); - // transform into modelspace of OUR entity - Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp); - Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection); - } - else - VectorNegate(ent->modellight_lightdir, relativelightdirection); + VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection); + // transform into modelspace of OUR entity + Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp); + Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection); } + else + VectorNegate(ent->modellight_lightdir, relativelightdirection); } - else - VectorNegate(ent->modellight_lightdir, relativelightdirection); } - - VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin); - RSurf_ActiveModelEntity(ent, false, false, false); - ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs); - rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity + else + VectorNegate(ent->modellight_lightdir, relativelightdirection); } + + VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin); + RSurf_ActiveModelEntity(ent, false, false, false); + ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs); + rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity } // not really the right mode, but this will disable any silly stencil features @@ -5077,7 +5089,9 @@ static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequer { float zdist; vec3_t centerorigin; +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) float vertex3f[12]; +#endif // if it's too close, skip it if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f)) return; @@ -5098,19 +5112,19 @@ static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequer case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: -#ifdef GL_SAMPLES_PASSED_ARB +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) CHECKGLERROR // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels); GL_DepthFunc(GL_ALWAYS); R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); - R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL); + R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); qglEndQueryARB(GL_SAMPLES_PASSED_ARB); GL_DepthFunc(GL_LEQUAL); qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels); R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); - R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL); + R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0); R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); qglEndQueryARB(GL_SAMPLES_PASSED_ARB); CHECKGLERROR @@ -5138,7 +5152,9 @@ static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1}; static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) { vec3_t color; + unsigned int occlude = 0; GLint allpixels = 0, visiblepixels = 0; + // now we have to check the query result if (rtlight->corona_queryindex_visiblepixels) { @@ -5149,36 +5165,55 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: -#ifdef GL_SAMPLES_PASSED_ARB +#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); + // 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))) + if (!r_shadow_occlusion_buf) { + qglGenBuffersARB(1, &r_shadow_occlusion_buf); + qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf); + qglBufferDataARB(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY); + } else { + qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf); + } + qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0)); + 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 -#endif break; +#else + return; +#endif case RENDERPATH_D3D9: Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; + return; case RENDERPATH_D3D10: Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; + return; case RENDERPATH_D3D11: Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; + return; case RENDERPATH_SOFT: //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - } - //Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels); - if (visiblepixels < 1 || allpixels < 1) return; - rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1); - cscale *= rtlight->corona_visibility; + default: + return; + } } else { // FIXME: these traces should scan all render entities instead of cl.world - if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1) + if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) return; } VectorScale(rtlight->currentcolor, cscale, color); @@ -5193,7 +5228,7 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) } R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false); - R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST, 0, 4, 0, 2, false, false); + R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST | occlude, 0, 4, 0, 2, false, false); if(negated) GL_BlendEquationSubtract(false); } @@ -5228,15 +5263,15 @@ void R_Shadow_DrawCoronas(void) case RENDERPATH_GLES1: case RENDERPATH_GLES2: usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer; -#ifdef GL_SAMPLES_PASSED_ARB +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) if (usequery) { GL_ColorMask(0,0,0,0); - if (r_maxqueries < (range + r_refdef.scene.numlights) * 2) + if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2) if (r_maxqueries < MAX_OCCLUSION_QUERIES) { i = r_maxqueries; - r_maxqueries = (range + r_refdef.scene.numlights) * 4; + r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4; r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES); CHECKGLERROR qglGenQueriesARB(r_maxqueries - i, r_queries + i); @@ -5334,12 +5369,10 @@ static dlight_t *R_Shadow_NewWorldLight(void) static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags) { matrix4x4_t matrix; + + // note that style is no longer validated here, -1 is used for unstyled lights and >= MAX_LIGHTSTYLES is accepted for sake of editing rtlights files that might be out of bounds but perfectly formatted + // validate parameters - if (style < 0 || style >= MAX_LIGHTSTYLES) - { - Con_Printf("R_Shadow_NewWorldLight: invalid light style number %i, must be >= 0 and < %i\n", light->style, MAX_LIGHTSTYLES); - style = 0; - } if (!cubemapname) cubemapname = ""; @@ -5476,7 +5509,7 @@ int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radiu unsigned int range; dlight_t *light; rtlight_t *rtlight; - range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); + range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); if (lightindex >= range) return -1; light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); @@ -5513,7 +5546,7 @@ static void R_Shadow_SelectLightInView(void) if (rating >= 0.95) { rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp))); - if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1.0f) + if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f) { bestrating = rating; best = light; @@ -5963,7 +5996,7 @@ static void R_Shadow_SetCursorLocationForView(void) vec3_t dest, endpos; trace_t trace; VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest); - trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true); + trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true); if (trace.fraction < 1) { dist = trace.fraction * r_editlights_cursordistance.value; @@ -6005,10 +6038,14 @@ void R_Shadow_EditLights_Reload_f(void) return; strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname)); R_Shadow_ClearWorldLights(); - R_Shadow_LoadWorldLights(); - if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) + if (r_shadow_realtime_world_importlightentitiesfrommap.integer <= 1) + { + R_Shadow_LoadWorldLights(); + if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) + R_Shadow_LoadLightsFile(); + } + if (r_shadow_realtime_world_importlightentitiesfrommap.integer >= 1) { - R_Shadow_LoadLightsFile(); if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(); } @@ -6451,7 +6488,7 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void) if (!light) continue; if (light == r_shadow_selectedlight) - lightnumber = lightindex; + lightnumber = (int)lightindex; lightcount++; } dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8; @@ -6727,7 +6764,7 @@ void R_LightPoint(float *color, const vec3_t p, const int flags) if (flags & LP_RTWORLD) { flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; - numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); + numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); for (i = 0; i < numlights; i++) { dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i); @@ -6747,7 +6784,7 @@ void R_LightPoint(float *color, const vec3_t p, const int flags) if (f <= 0) continue; // todo: add to both ambient and diffuse - if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1) + if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) VectorMA(color, f, light->currentcolor, color); } } @@ -6768,7 +6805,7 @@ void R_LightPoint(float *color, const vec3_t p, const int flags) if (f <= 0) continue; // todo: add to both ambient and diffuse - if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1) + if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1) VectorMA(color, f, light->color, color); } } @@ -6833,7 +6870,7 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const if (flags & LP_RTWORLD) { flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE; - numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); + numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); for (i = 0; i < numlights; i++) { dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i); @@ -6852,7 +6889,7 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value; if (intensity <= 0.0f) continue; - if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1) + if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) continue; // scale down intensity to add to both ambient and diffuse //intensity *= 0.5f; @@ -6885,7 +6922,7 @@ void R_CompleteLightPoint(vec3_t ambient, vec3_t diffuse, vec3_t lightdir, const intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value; if (intensity <= 0.0f) continue; - if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1) + if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1) continue; // scale down intensity to add to both ambient and diffuse //intensity *= 0.5f;