]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
Xonotic's travis script: Build the Linux binaries against SDL 2.0.4.
[xonotic/darkplaces.git] / r_shadow.c
index 1884285951b5a5ee209d8ae6c017406b87ef99c9..b97ae62d2a089a90578e6ffe1cbea4880b6179f8 100644 (file)
@@ -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
@@ -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);
        }
 }
@@ -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;
@@ -2715,7 +2720,7 @@ void R_Shadow_UpdateBounceGridTexture(void)
                                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
                                {
@@ -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++;
@@ -3765,10 +3770,7 @@ static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist
                        if (!mesh->sidetotals[r_shadow_shadowmapside])
                                continue;
                        r_refdef.stats[r_stat_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_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
@@ -3805,10 +3807,7 @@ static void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacel
                for (;mesh;mesh = mesh->next)
                {
                        r_refdef.stats[r_stat_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_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)
@@ -4134,13 +4134,16 @@ static void R_Shadow_PrepareLight(rtlight_t *rtlight)
        // 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;