]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
physics: fix and refactor unsticking
[xonotic/darkplaces.git] / r_shadow.c
index 67cf27ced1aae04be8ed88ff1914e160278096d2..2c5cecd34b75bbf65a2017dce825bf46ede3f39b 100644 (file)
@@ -232,7 +232,7 @@ cvar_t r_shadow_bouncegrid_subsamples = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bounc
 cvar_t r_shadow_bouncegrid_threaded = {CF_CLIENT | CF_ARCHIVE, "r_shadow_bouncegrid_threaded", "1", "enables use of taskqueue_maxthreads to perform the traces and slice rendering of bouncegrid"};
 cvar_t r_coronas = {CF_CLIENT | CF_ARCHIVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
 cvar_t r_coronas_occlusionsizescale = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
-cvar_t r_coronas_occlusionquery = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility"};
+cvar_t r_coronas_occlusionquery = {CF_CLIENT | CF_ARCHIVE, "r_coronas_occlusionquery", "0", "fades coronas according to visibility, requires OpenGL 4.4"};
 cvar_t gl_flashblend = {CF_CLIENT | CF_ARCHIVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
 cvar_t r_editlights = {CF_CLIENT, "r_editlights", "0", "enables .rtlights file editing mode"};
 cvar_t r_editlights_cursordistance = {CF_CLIENT, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
@@ -372,7 +372,7 @@ static void R_Shadow_SetShadowMode(void)
        }
 
        if(R_CompileShader_CheckStaticParms())
-               R_GLSL_Restart_f(&cmd_client);
+               R_GLSL_Restart_f(cmd_local);
 }
 
 qbool R_Shadow_ShadowMappingEnabled(void)
@@ -487,6 +487,18 @@ static void r_shadow_start(void)
        }
 }
 
+static void R_Shadow_BounceGrid_FreeHighPixels(void)
+{
+       r_shadow_bouncegrid_state.highpixels = NULL;
+       if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
+       if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
+       if (r_shadow_bouncegrid_state.u8pixels)      { Mem_Free(r_shadow_bouncegrid_state.u8pixels);      r_shadow_bouncegrid_state.u8pixels      = NULL; }
+       if (r_shadow_bouncegrid_state.fp16pixels)    { Mem_Free(r_shadow_bouncegrid_state.fp16pixels);    r_shadow_bouncegrid_state.fp16pixels    = NULL; }
+       if (r_shadow_bouncegrid_state.photons)       { Mem_Free(r_shadow_bouncegrid_state.photons);       r_shadow_bouncegrid_state.photons       = NULL; }
+       if (r_shadow_bouncegrid_state.photons_tasks) { Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL; }
+       if (r_shadow_bouncegrid_state.slices_tasks)  { Mem_Free(r_shadow_bouncegrid_state.slices_tasks);  r_shadow_bouncegrid_state.slices_tasks  = NULL; }
+}
+
 static void R_Shadow_FreeDeferred(void);
 static void r_shadow_shutdown(void)
 {
@@ -505,14 +517,7 @@ static void r_shadow_shutdown(void)
        if (r_shadow_scenelightlist)
                Mem_Free(r_shadow_scenelightlist);
        r_shadow_scenelightlist = NULL;
-       r_shadow_bouncegrid_state.highpixels = NULL;
-       if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
-       if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
-       if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
-       if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
-       if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
-       if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
-       if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
+       R_Shadow_BounceGrid_FreeHighPixels();
        memset(&r_shadow_bouncegrid_state, 0, sizeof(r_shadow_bouncegrid_state));
        r_shadow_attenuationgradienttexture = NULL;
        R_FreeTexturePool(&r_shadow_texturepool);
@@ -579,14 +584,7 @@ static void r_shadow_shutdown(void)
 
 static void r_shadow_newmap(void)
 {
-       r_shadow_bouncegrid_state.highpixels = NULL;
-       if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
-       if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
-       if (r_shadow_bouncegrid_state.u8pixels) { Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; }
-       if (r_shadow_bouncegrid_state.fp16pixels) { Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; }
-       if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
-       if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
-       if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
+       R_Shadow_BounceGrid_FreeHighPixels();
 
        if (r_shadow_bouncegrid_state.texture)    { R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; }
        if (r_shadow_lightcorona)                 { R_SkinFrame_MarkUsed(r_shadow_lightcorona); }
@@ -597,7 +595,7 @@ static void r_shadow_newmap(void)
        if (r_editlights_sprcubemapnoshadowlight) { R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight); }
        if (r_editlights_sprselection)            { R_SkinFrame_MarkUsed(r_editlights_sprselection); }
        if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname)))
-               R_Shadow_EditLights_Reload_f(&cmd_client);
+               R_Shadow_EditLights_Reload_f(cmd_local);
 }
 
 void R_Shadow_Init(void)
@@ -1228,7 +1226,7 @@ static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
        float dist = sqrt(x*x+y*y+z*z);
        float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
        // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
-       return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
+       return bound(0, (unsigned int)(intensity * 256.0f), 255) * 0x01010101U;
 }
 
 static void R_Shadow_MakeTextures(void)
@@ -1884,15 +1882,7 @@ static void R_Shadow_BounceGrid_UpdateSpacing(void)
        {
                if (r_shadow_bouncegrid_state.texture) { R_FreeTexture(r_shadow_bouncegrid_state.texture);r_shadow_bouncegrid_state.texture = NULL; }
 
-               r_shadow_bouncegrid_state.highpixels = NULL;
-
-               if (r_shadow_bouncegrid_state.blurpixels[0]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL; }
-               if (r_shadow_bouncegrid_state.blurpixels[1]) { Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL; }
-               if (r_shadow_bouncegrid_state.u8pixels) { Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL; }
-               if (r_shadow_bouncegrid_state.fp16pixels) { Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL; }
-               if (r_shadow_bouncegrid_state.photons) { Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL; }
-               if (r_shadow_bouncegrid_state.photons_tasks) { Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL; }
-               if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
+               R_Shadow_BounceGrid_FreeHighPixels();
 
                r_shadow_bouncegrid_state.numpixels = numpixels;
        }
@@ -2023,7 +2013,7 @@ static void R_Shadow_BounceGrid_AssignPhotons_Task(taskqueue_task_t *t)
                                        continue;
                        }
                        // skip if expanded light box is offscreen
-                       if (R_CullBox(cullmins, cullmaxs))
+                       if (R_CullFrustum(cullmins, cullmaxs))
                                continue;
                        // skip if overall light intensity is zero
                        if (w * VectorLength2(rtlight->color) == 0.0f)
@@ -2530,7 +2520,7 @@ static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
                }
 
                if (!r_shadow_bouncegrid_state.createtexture)
-                       R_UpdateTexture(r_shadow_bouncegrid_state.texture, pixelsbgra8, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
+                       R_UpdateTexture(r_shadow_bouncegrid_state.texture, pixelsbgra8, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands, 0);
                else
                        r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, pixelsbgra8, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
                break;
@@ -2581,7 +2571,7 @@ static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
                }
 
                if (!r_shadow_bouncegrid_state.createtexture)
-                       R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba16f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
+                       R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba16f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands, 0);
                else
                        r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, (const unsigned char *)pixelsrgba16f, TEXTYPE_COLORBUFFER16F, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
                break;
@@ -2590,7 +2580,7 @@ static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
                pixelsrgba32f = highpixels;
 
                if (!r_shadow_bouncegrid_state.createtexture)
-                       R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba32f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
+                       R_UpdateTexture(r_shadow_bouncegrid_state.texture, (const unsigned char *)pixelsrgba32f, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands, 0);
                else
                        r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, (const unsigned char *)pixelsrgba32f, TEXTYPE_COLORBUFFER32F, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);
                break;
@@ -2636,7 +2626,7 @@ static void R_Shadow_BounceGrid_TracePhotons_Shot(r_shadow_bouncegrid_photon_t *
        if ((remainingbounces == r_shadow_bouncegrid_state.settings.maxbounce || r_shadow_bouncegrid_state.settings.includedirectlighting) && p->numpaths < PHOTON_MAX_PATHS)
        {
                qbool notculled = true;
-               // cull paths that fail R_CullBox in dynamic mode
+               // cull paths that fail R_CullFrustum in dynamic mode
                if (!r_shadow_bouncegrid_state.settings.staticmode
                        && r_shadow_bouncegrid_dynamic_culllightpaths.integer)
                {
@@ -2647,7 +2637,7 @@ static void R_Shadow_BounceGrid_TracePhotons_Shot(r_shadow_bouncegrid_photon_t *
                        cullmaxs[0] = max(shotstart[0], shothit[0]) + r_shadow_bouncegrid_state.settings.spacing[0] + r_shadow_bouncegrid_state.settings.lightpathsize;
                        cullmaxs[1] = max(shotstart[1], shothit[1]) + r_shadow_bouncegrid_state.settings.spacing[1] + r_shadow_bouncegrid_state.settings.lightpathsize;
                        cullmaxs[2] = max(shotstart[2], shothit[2]) + r_shadow_bouncegrid_state.settings.spacing[2] + r_shadow_bouncegrid_state.settings.lightpathsize;
-                       if (R_CullBox(cullmins, cullmaxs))
+                       if (R_CullFrustum(cullmins, cullmaxs))
                                notculled = false;
                }
                if (notculled)
@@ -2787,14 +2777,7 @@ void R_Shadow_UpdateBounceGridTexture(void)
                        R_FreeTexture(r_shadow_bouncegrid_state.texture);
                        r_shadow_bouncegrid_state.texture = NULL;
                }
-               r_shadow_bouncegrid_state.highpixels = NULL;
-               if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
-               if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
-               if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
-               if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
-               if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
-               if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
-               if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
+               R_Shadow_BounceGrid_FreeHighPixels();
                r_shadow_bouncegrid_state.numpixels = 0;
                r_shadow_bouncegrid_state.numphotons = 0;
                r_shadow_bouncegrid_state.directional = false;
@@ -2871,16 +2854,7 @@ void R_Shadow_UpdateBounceGridTexture(void)
 
        // after we compute the static lighting we don't need to keep the highpixels array around
        if (settings.staticmode)
-       {
-               r_shadow_bouncegrid_state.highpixels = NULL;
-               if (r_shadow_bouncegrid_state.blurpixels[0]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[0]); r_shadow_bouncegrid_state.blurpixels[0] = NULL;
-               if (r_shadow_bouncegrid_state.blurpixels[1]) Mem_Free(r_shadow_bouncegrid_state.blurpixels[1]); r_shadow_bouncegrid_state.blurpixels[1] = NULL;
-               if (r_shadow_bouncegrid_state.u8pixels) Mem_Free(r_shadow_bouncegrid_state.u8pixels); r_shadow_bouncegrid_state.u8pixels = NULL;
-               if (r_shadow_bouncegrid_state.fp16pixels) Mem_Free(r_shadow_bouncegrid_state.fp16pixels); r_shadow_bouncegrid_state.fp16pixels = NULL;
-               if (r_shadow_bouncegrid_state.photons) Mem_Free(r_shadow_bouncegrid_state.photons); r_shadow_bouncegrid_state.photons = NULL;
-               if (r_shadow_bouncegrid_state.photons_tasks) Mem_Free(r_shadow_bouncegrid_state.photons_tasks); r_shadow_bouncegrid_state.photons_tasks = NULL;
-               if (r_shadow_bouncegrid_state.slices_tasks) Mem_Free(r_shadow_bouncegrid_state.slices_tasks); r_shadow_bouncegrid_state.slices_tasks = NULL;
-       }
+               R_Shadow_BounceGrid_FreeHighPixels();
 }
 
 void R_Shadow_RenderMode_VisibleLighting(qbool transparent)
@@ -2954,7 +2928,7 @@ static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, cons
 static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const float ambientcolor[3], const float diffusecolor[3], const float specularcolor[3])
 {
        // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
-       R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false);
+       R_SetupShader_Surface(ambientcolor, diffusecolor, specularcolor, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL, false, false);
        RSurf_DrawBatch();
 }
 
@@ -2985,7 +2959,7 @@ void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **textures
                VectorNegate(specularcolor, specularcolor);
                GL_BlendEquationSubtract(true);
        }
-       RSurf_SetupDepthAndCulling();
+       RSurf_SetupDepthAndCulling(false);
        switch (r_shadow_rendermode)
        {
        case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
@@ -3022,7 +2996,7 @@ void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec
        VectorCopy(color, rtlight->color);
        rtlight->cubemapname[0] = 0;
        if (cubemapname && cubemapname[0])
-               strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
+               dp_strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
        rtlight->shadow = shadow;
        rtlight->corona = corona;
        rtlight->style = style;
@@ -3376,7 +3350,7 @@ static void R_Shadow_DrawEntityShadow(entity_render_t *ent)
        relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
        relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
        relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
-       ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+       ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs);
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 }
 
@@ -3415,7 +3389,7 @@ static void R_Shadow_DrawEntityLight(entity_render_t *ent)
 
        R_Shadow_SetupEntityLight(ent);
 
-       model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
+       model->DrawLight(ent, model->submodelsurfaces_end - model->submodelsurfaces_start, model->modelsurfaces_sorted + model->submodelsurfaces_start, NULL);
 
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 }
@@ -3507,7 +3481,7 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight)
        }
 
        // skip if the light box is off screen
-       if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
+       if (R_CullFrustum(rtlight->cullmins, rtlight->cullmaxs))
                return;
 
        // in the typical case this will be quickly replaced by GetLightInfo
@@ -3546,7 +3520,7 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight)
                shadowtrispvs = r_shadow_buffer_shadowtrispvs;
                lighttrispvs = r_shadow_buffer_lighttrispvs;
                // if the reduced leaf bounds are offscreen, skip it
-               if (R_CullBox(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
+               if (R_CullFrustum(rtlight->cached_cullmins, rtlight->cached_cullmaxs))
                        return;
        }
        else
@@ -3587,7 +3561,7 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight)
                        continue;
                // skip the object entirely if it is not within the valid
                // shadow-casting region (which includes the lit region)
-               if (R_CullBoxCustomPlanes(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
+               if (R_CullBox(ent->mins, ent->maxs, rtlight->cached_numfrustumplanes, rtlight->cached_frustumplanes))
                        continue;
                if (!(model = ent->model))
                        continue;
@@ -4431,7 +4405,7 @@ static void R_Shadow_DrawModelShadowMaps(void)
                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);
+               ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs);
                rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
        }
 
@@ -4587,7 +4561,8 @@ void R_Shadow_DrawCoronas(void)
        {
        case RENDERPATH_GL32:
        case RENDERPATH_GLES2:
-               usequery = r_coronas_occlusionquery.integer;
+               // buffer binding target GL_QUERY_BUFFER: Core since version 4.4
+               usequery = r_coronas_occlusionquery.integer && vid.support.glversion >= 44;
 #ifndef USE_GLES2
                if (usequery)
                {
@@ -4701,7 +4676,7 @@ static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t ang
        light->style = style;
        light->shadow = shadowenable;
        light->corona = corona;
-       strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
+       dp_strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
        light->coronasizescale = coronasizescale;
        light->ambientscale = ambientscale;
        light->diffusescale = diffusescale;
@@ -5125,14 +5100,14 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                        if (com_token[0] == '}')
                                break; // end of entity
                        if (com_token[0] == '_')
-                               strlcpy(key, com_token + 1, sizeof(key));
+                               dp_strlcpy(key, com_token + 1, sizeof(key));
                        else
-                               strlcpy(key, com_token, sizeof(key));
+                               dp_strlcpy(key, com_token, sizeof(key));
                        while (key[strlen(key)-1] == ' ') // remove trailing spaces
                                key[strlen(key)-1] = 0;
                        if (!COM_ParseToken_Simple(&data, false, false, true))
                                break; // error
-                       strlcpy(value, com_token, sizeof(value));
+                       dp_strlcpy(value, com_token, sizeof(value));
 
                        // now that we have the key pair worked out...
                        if (!strcmp("light", key))
@@ -5344,7 +5319,7 @@ void R_Shadow_EditLights_Reload_f(cmd_state_t *cmd)
 {
        if (!cl.worldmodel)
                return;
-       strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname));
+       dp_strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname));
        R_Shadow_ClearWorldLights();
        if (r_shadow_realtime_world_importlightentitiesfrommap.integer <= 1)
        {
@@ -5417,7 +5392,7 @@ static void R_Shadow_EditLights_Edit_f(cmd_state_t *cmd)
        radius = r_shadow_selectedlight->radius;
        style = r_shadow_selectedlight->style;
        if (*r_shadow_selectedlight->cubemapname)
-               strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
+               dp_strlcpy(cubemapname, r_shadow_selectedlight->cubemapname, sizeof(cubemapname));
        else
                cubemapname[0] = 0;
        shadows = r_shadow_selectedlight->shadow;
@@ -5621,7 +5596,7 @@ static void R_Shadow_EditLights_Edit_f(cmd_state_t *cmd)
                        return;
                }
                if (Cmd_Argc(cmd) == 3)
-                       strlcpy(cubemapname, Cmd_Argv(cmd, 2), sizeof(cubemapname));
+                       dp_strlcpy(cubemapname, Cmd_Argv(cmd, 2), sizeof(cubemapname));
                else
                        cubemapname[0] = 0;
        }
@@ -5742,7 +5717,7 @@ static void R_Shadow_EditLights_EditAll_f(cmd_state_t *cmd)
                if (!light)
                        continue;
                R_Shadow_SelectLight(light);
-               R_Shadow_EditLights_Edit_f(&cmd_client);
+               R_Shadow_EditLights_Edit_f(cmd_local);
        }
        // return to old selected (to not mess editing once selection is locked)
        R_Shadow_SelectLight(oldselected);
@@ -5952,7 +5927,7 @@ static void R_Shadow_EditLights_CopyInfo_f(cmd_state_t *cmd)
        r_shadow_bufferlight.radius = r_shadow_selectedlight->radius;
        r_shadow_bufferlight.style = r_shadow_selectedlight->style;
        if (*r_shadow_selectedlight->cubemapname)
-               strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
+               dp_strlcpy(r_shadow_bufferlight.cubemapname, r_shadow_selectedlight->cubemapname, sizeof(r_shadow_bufferlight.cubemapname));
        else
                r_shadow_bufferlight.cubemapname[0] = 0;
        r_shadow_bufferlight.shadow = r_shadow_selectedlight->shadow;