]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
removed rsurface_entity field, and copied all fields that were accessed
[xonotic/darkplaces.git] / r_shadow.c
index 0959b37be8d3bcbda5ef0d8d6a1111bc01f7a758..2214404de1dbe93450cdf85926c5b65c4e598e10 100644 (file)
@@ -228,7 +228,6 @@ 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_dlightshadows = {CVAR_SAVE, "r_shadow_realtime_world_dlightshadows", "1", "enables shadows from dynamic lights when using full world lighting"};
 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"};
@@ -237,8 +236,8 @@ cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compi
 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation"};
 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
 cvar_t r_shadow_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
-cvar_t r_shadow_shadow_polygonfactor = {0, "r_shadow_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
-cvar_t r_shadow_shadow_polygonoffset = {0, "r_shadow_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
+cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
+cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
 cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect r_glsl lighting)"};
 cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
@@ -404,14 +403,13 @@ void R_Shadow_Help_f(void)
 "r_shadow_realtime_dlight : use high quality dynamic lights in normal mode\n"
 "r_shadow_realtime_dlight_shadows : cast shadows from dlights\n"
 "r_shadow_realtime_world : use high quality world lighting mode\n"
-"r_shadow_realtime_world_dlightshadows : cast shadows from dlights\n"
 "r_shadow_realtime_world_lightmaps : use lightmaps in addition to lights\n"
 "r_shadow_realtime_world_shadows : cast shadows from world lights\n"
 "r_shadow_realtime_world_compile : compile surface/visibility information\n"
 "r_shadow_realtime_world_compileshadow : compile shadow geometry\n"
 "r_shadow_scissor : use scissor optimization\n"
-"r_shadow_shadow_polygonfactor : nudge shadow volumes closer/further\n"
-"r_shadow_shadow_polygonoffset : nudge shadow volumes closer/further\n"
+"r_shadow_polygonfactor : nudge shadow volumes closer/further\n"
+"r_shadow_polygonoffset : nudge shadow volumes closer/further\n"
 "r_shadow_texture3d : use 3d attenuation texture (if hardware supports)\n"
 "r_showlighting : useful for performance testing; bright = slow!\n"
 "r_showshadowvolumes : useful for performance testing; bright = slow!\n"
@@ -442,7 +440,6 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
        Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
        Cvar_RegisterVariable(&r_shadow_realtime_world);
-       Cvar_RegisterVariable(&r_shadow_realtime_world_dlightshadows);
        Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
        Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
        Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
@@ -451,8 +448,8 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
        Cvar_RegisterVariable(&r_shadow_scissor);
        Cvar_RegisterVariable(&r_shadow_culltriangles);
-       Cvar_RegisterVariable(&r_shadow_shadow_polygonfactor);
-       Cvar_RegisterVariable(&r_shadow_shadow_polygonoffset);
+       Cvar_RegisterVariable(&r_shadow_polygonfactor);
+       Cvar_RegisterVariable(&r_shadow_polygonoffset);
        Cvar_RegisterVariable(&r_shadow_texture3d);
        Cvar_RegisterVariable(&gl_ext_separatestencil);
        Cvar_RegisterVariable(&gl_ext_stenciltwoside);
@@ -1062,7 +1059,7 @@ void R_Shadow_RenderMode_Reset(void)
        GL_BlendFunc(GL_ONE, GL_ZERO);
 }
 
-void R_Shadow_RenderMode_StencilShadowVolumes(void)
+void R_Shadow_RenderMode_StencilShadowVolumes(qboolean clearstencil)
 {
        CHECKGLERROR
        R_Shadow_RenderMode_Reset();
@@ -1088,7 +1085,8 @@ void R_Shadow_RenderMode_StencilShadowVolumes(void)
                qglStencilMask(~0);CHECKGLERROR
                qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
        }
-       GL_Clear(GL_STENCIL_BUFFER_BIT);
+       if (clearstencil)
+               GL_Clear(GL_STENCIL_BUFFER_BIT);
        r_refdef.stats.lights_clears++;
 }
 
@@ -1286,7 +1284,8 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        VectorCopy(ambientcolor, color4f);
                                if (r_refdef.fogenabled)
                                {
-                                       float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+                                       float f;
+                                       f = FogPoint_Model(vertex3f);
                                        VectorScale(color4f, f, color4f);
                                }
                                color4f[3] = 1;
@@ -1301,7 +1300,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                {
                                        float f;
                                        Matrix4x4_Transform(&r_shadow_entitytolight, vertex3f, v);
-                                       f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+                                       f = FogPoint_Model(vertex3f);
                                        VectorScale(color4f, f, color4f);
                                }
                                color4f[3] = 1;
@@ -1333,7 +1332,8 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        }
                                        if (r_refdef.fogenabled)
                                        {
-                                               float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+                                               float f;
+                                               f = FogPoint_Model(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -1354,7 +1354,8 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        color4f[2] = ambientcolor[2] * distintensity;
                                        if (r_refdef.fogenabled)
                                        {
-                                               float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+                                               float f;
+                                               f = FogPoint_Model(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -1390,7 +1391,8 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        }
                                        if (r_refdef.fogenabled)
                                        {
-                                               float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+                                               float f;
+                                               f = FogPoint_Model(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -1412,7 +1414,8 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu
                                        color4f[2] = ambientcolor[2] * distintensity;
                                        if (r_refdef.fogenabled)
                                        {
-                                               float f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+                                               float f;
+                                               f = FogPoint_Model(vertex3f);
                                                VectorScale(color4f, f, color4f);
                                        }
                                }
@@ -2186,7 +2189,7 @@ void R_Shadow_RenderLighting_Light_Vertex_Pass(const model_t *model, int firstve
 static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, int element3i_bufferobject, size_t element3i_bufferoffset, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float ambientscale, float diffusescale, float specularscale, qboolean dopants, qboolean doshirt)
 {
        // OpenGL 1.1 path (anything)
-       model_t *model = rsurface_entity->model;
+       const model_t *model = rsurface_model;
        float ambientcolorbase[3], diffusecolorbase[3];
        float ambientcolorpants[3], diffusecolorpants[3];
        float ambientcolorshirt[3], diffusecolorshirt[3];
@@ -2243,9 +2246,9 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int numtriangles,
        float ambientscale, diffusescale, specularscale;
        vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
        // calculate colors to render this texture with
-       lightcolorbase[0] = r_shadow_rtlight->currentcolor[0] * rsurface_entity->colormod[0] * rsurface_texture->currentalpha;
-       lightcolorbase[1] = r_shadow_rtlight->currentcolor[1] * rsurface_entity->colormod[1] * rsurface_texture->currentalpha;
-       lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * rsurface_entity->colormod[2] * rsurface_texture->currentalpha;
+       lightcolorbase[0] = r_shadow_rtlight->currentcolor[0] * rsurface_texture->currentlayers[0].color[0] * rsurface_texture->currentlayers[0].color[3];
+       lightcolorbase[1] = r_shadow_rtlight->currentcolor[1] * rsurface_texture->currentlayers[0].color[1] * rsurface_texture->currentlayers[0].color[3];
+       lightcolorbase[2] = r_shadow_rtlight->currentcolor[2] * rsurface_texture->currentlayers[0].color[2] * rsurface_texture->currentlayers[0].color[3];
        ambientscale = r_shadow_rtlight->ambientscale;
        diffusescale = r_shadow_rtlight->diffusescale;
        specularscale = r_shadow_rtlight->specularscale * rsurface_texture->specularscale;
@@ -2262,21 +2265,21 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int numtriangles,
        GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
        if (rsurface_texture->colormapping)
        {
-               qboolean dopants = rsurface_texture->currentskinframe->pants != NULL && VectorLength2(rsurface_entity->colormap_pantscolor) >= (1.0f / 1048576.0f);
-               qboolean doshirt = rsurface_texture->currentskinframe->shirt != NULL && VectorLength2(rsurface_entity->colormap_shirtcolor) >= (1.0f / 1048576.0f);
+               qboolean dopants = rsurface_texture->currentskinframe->pants != NULL && VectorLength2(rsurface_colormap_pantscolor) >= (1.0f / 1048576.0f);
+               qboolean doshirt = rsurface_texture->currentskinframe->shirt != NULL && VectorLength2(rsurface_colormap_shirtcolor) >= (1.0f / 1048576.0f);
                if (dopants)
                {
-                       lightcolorpants[0] = lightcolorbase[0] * rsurface_entity->colormap_pantscolor[0];
-                       lightcolorpants[1] = lightcolorbase[1] * rsurface_entity->colormap_pantscolor[1];
-                       lightcolorpants[2] = lightcolorbase[2] * rsurface_entity->colormap_pantscolor[2];
+                       lightcolorpants[0] = lightcolorbase[0] * rsurface_colormap_pantscolor[0];
+                       lightcolorpants[1] = lightcolorbase[1] * rsurface_colormap_pantscolor[1];
+                       lightcolorpants[2] = lightcolorbase[2] * rsurface_colormap_pantscolor[2];
                }
                else
                        VectorClear(lightcolorpants);
                if (doshirt)
                {
-                       lightcolorshirt[0] = lightcolorbase[0] * rsurface_entity->colormap_shirtcolor[0];
-                       lightcolorshirt[1] = lightcolorbase[1] * rsurface_entity->colormap_shirtcolor[1];
-                       lightcolorshirt[2] = lightcolorbase[2] * rsurface_entity->colormap_shirtcolor[2];
+                       lightcolorshirt[0] = lightcolorbase[0] * rsurface_colormap_shirtcolor[0];
+                       lightcolorshirt[1] = lightcolorbase[1] * rsurface_colormap_shirtcolor[1];
+                       lightcolorshirt[2] = lightcolorbase[2] * rsurface_colormap_shirtcolor[2];
                }
                else
                        VectorClear(lightcolorshirt);
@@ -2748,15 +2751,19 @@ void R_Shadow_DrawEntityLight(entity_render_t *ent, int numsurfaces, int *surfac
 
 void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
 {
-       int i, usestencil;
+       int i;
        float f;
        int numleafs, numsurfaces;
        int *leaflist, *surfacelist;
        unsigned char *leafpvs, *shadowtrispvs, *lighttrispvs;
        int numlightentities;
+       int numlightentities_noselfshadow;
        int numshadowentities;
+       int numshadowentities_noselfshadow;
        entity_render_t *lightentities[MAX_EDICTS];
+       entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
        entity_render_t *shadowentities[MAX_EDICTS];
+       entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
 
        // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
        // skip lights that are basically invisible (color 0 0 0)
@@ -2849,7 +2856,9 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
 
        // make a list of lit entities and shadow casting entities
        numlightentities = 0;
+       numlightentities_noselfshadow = 0;
        numshadowentities = 0;
+       numshadowentities_noselfshadow = 0;
        // add dynamic entities that are lit by the light
        if (r_drawentities.integer)
        {
@@ -2874,12 +2883,26 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                                // so now check if it's in a leaf seen by the light
                                if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingLeafPVS && !r_refdef.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.worldmodel, leafpvs, ent->mins, ent->maxs))
                                        continue;
-                               lightentities[numlightentities++] = ent;
+                               if (ent->flags & RENDER_NOSELFSHADOW)
+                                       lightentities_noselfshadow[numlightentities_noselfshadow++] = ent;
+                               else
+                                       lightentities[numlightentities++] = ent;
                                // since it is lit, it probably also casts a shadow...
                                // about the VectorDistance2 - light emitting entities should not cast their own shadow
                                Matrix4x4_OriginFromMatrix(&ent->matrix, org);
                                if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
-                                       shadowentities[numshadowentities++] = ent;
+                               {
+                                       // note: exterior models without the RENDER_NOSELFSHADOW
+                                       // flag still create a RENDER_NOSELFSHADOW shadow but
+                                       // are lit normally, this means that they are
+                                       // self-shadowing but do not shadow other
+                                       // RENDER_NOSELFSHADOW entities such as the gun
+                                       // (very weird, but keeps the player shadow off the gun)
+                                       if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
+                                               shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
+                                       else
+                                               shadowentities[numshadowentities++] = ent;
+                               }
                        }
                        else if (ent->flags & RENDER_SHADOW)
                        {
@@ -2892,7 +2915,12 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
                                // about the VectorDistance2 - light emitting entities should not cast their own shadow
                                Matrix4x4_OriginFromMatrix(&ent->matrix, org);
                                if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
-                                       shadowentities[numshadowentities++] = ent;
+                               {
+                                       if (ent->flags & (RENDER_NOSELFSHADOW | RENDER_EXTERIORMODEL))
+                                               shadowentities_noselfshadow[numshadowentities_noselfshadow++] = ent;
+                                       else
+                                               shadowentities[numshadowentities++] = ent;
+                               }
                        }
                }
        }
@@ -2910,51 +2938,95 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
        // count this light in the r_speeds
        r_refdef.stats.lights++;
 
-       usestencil = false;
-       if (numsurfaces + numshadowentities && rtlight->shadow && (rtlight->isstatic ? r_refdef.rtworldshadows : r_refdef.rtdlightshadows))
+       if (r_showshadowvolumes.integer && numsurfaces + numshadowentities + numshadowentities_noselfshadow && rtlight->shadow && (rtlight->isstatic ? r_refdef.rtworldshadows : r_refdef.rtdlightshadows))
+       {
+               // optionally draw visible shape of the shadow volumes
+               // for performance analysis by level designers
+               R_Shadow_RenderMode_VisibleShadowVolumes();
+               if (numsurfaces)
+                       R_Shadow_DrawWorldShadow(numsurfaces, surfacelist, shadowtrispvs);
+               for (i = 0;i < numshadowentities;i++)
+                       R_Shadow_DrawEntityShadow(shadowentities[i]);
+               for (i = 0;i < numshadowentities_noselfshadow;i++)
+                       R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
+       }
+
+       if (gl_stencil && numsurfaces + numshadowentities + numshadowentities_noselfshadow && rtlight->shadow && (rtlight->isstatic ? r_refdef.rtworldshadows : r_refdef.rtdlightshadows))
        {
                // draw stencil shadow volumes to mask off pixels that are in shadow
                // so that they won't receive lighting
-               if (gl_stencil)
+               R_Shadow_RenderMode_StencilShadowVolumes(true);
+               if (numsurfaces)
+                       R_Shadow_DrawWorldShadow(numsurfaces, surfacelist, shadowtrispvs);
+               for (i = 0;i < numshadowentities;i++)
+                       R_Shadow_DrawEntityShadow(shadowentities[i]);
+               if (numlightentities_noselfshadow)
                {
-                       usestencil = true;
-                       R_Shadow_RenderMode_StencilShadowVolumes();
-                       if (numsurfaces)
-                               R_Shadow_DrawWorldShadow(numsurfaces, surfacelist, shadowtrispvs);
-                       for (i = 0;i < numshadowentities;i++)
-                               R_Shadow_DrawEntityShadow(shadowentities[i]);
+                       // draw lighting in the unmasked areas
+                       R_Shadow_RenderMode_Lighting(true, false);
+                       for (i = 0;i < numlightentities_noselfshadow;i++)
+                               R_Shadow_DrawEntityLight(lightentities_noselfshadow[i], numsurfaces, surfacelist);
+
+                       // optionally draw the illuminated areas
+                       // for performance analysis by level designers
+                       if (r_showlighting.integer)
+                       {
+                               R_Shadow_RenderMode_VisibleLighting(!r_showdisabledepthtest.integer, false);
+                               for (i = 0;i < numlightentities_noselfshadow;i++)
+                                       R_Shadow_DrawEntityLight(lightentities_noselfshadow[i], numsurfaces, surfacelist);
+                       }
+
+                       R_Shadow_RenderMode_StencilShadowVolumes(false);
                }
+               for (i = 0;i < numshadowentities_noselfshadow;i++)
+                       R_Shadow_DrawEntityShadow(shadowentities_noselfshadow[i]);
 
-               // optionally draw visible shape of the shadow volumes
-               // for performance analysis by level designers
-               if (r_showshadowvolumes.integer)
+               if (numsurfaces + numlightentities)
                {
-                       R_Shadow_RenderMode_VisibleShadowVolumes();
+                       // draw lighting in the unmasked areas
+                       R_Shadow_RenderMode_Lighting(true, false);
                        if (numsurfaces)
-                               R_Shadow_DrawWorldShadow(numsurfaces, surfacelist, shadowtrispvs);
-                       for (i = 0;i < numshadowentities;i++)
-                               R_Shadow_DrawEntityShadow(shadowentities[i]);
+                               R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
+                       for (i = 0;i < numlightentities;i++)
+                               R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist);
+
+                       // optionally draw the illuminated areas
+                       // for performance analysis by level designers
+                       if (r_showlighting.integer)
+                       {
+                               R_Shadow_RenderMode_VisibleLighting(!r_showdisabledepthtest.integer, false);
+                               if (numsurfaces)
+                                       R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
+                               for (i = 0;i < numlightentities;i++)
+                                       R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist);
+                       }
                }
        }
-
-       if (numsurfaces + numlightentities)
+       else
        {
-               // draw lighting in the unmasked areas
-               R_Shadow_RenderMode_Lighting(usestencil, false);
-               if (numsurfaces)
-                       R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
-               for (i = 0;i < numlightentities;i++)
-                       R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist);
-
-               // optionally draw the illuminated areas
-               // for performance analysis by level designers
-               if (r_showlighting.integer)
+               if (numsurfaces + numlightentities)
                {
-                       R_Shadow_RenderMode_VisibleLighting(usestencil && !r_showdisabledepthtest.integer, false);
+                       // draw lighting in the unmasked areas
+                       R_Shadow_RenderMode_Lighting(false, false);
                        if (numsurfaces)
                                R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
                        for (i = 0;i < numlightentities;i++)
                                R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist);
+                       for (i = 0;i < numlightentities_noselfshadow;i++)
+                               R_Shadow_DrawEntityLight(lightentities_noselfshadow[i], numsurfaces, surfacelist);
+
+                       // optionally draw the illuminated areas
+                       // for performance analysis by level designers
+                       if (r_showlighting.integer)
+                       {
+                               R_Shadow_RenderMode_VisibleLighting(false, false);
+                               if (numsurfaces)
+                                       R_Shadow_DrawWorldLight(numsurfaces, surfacelist, lighttrispvs);
+                               for (i = 0;i < numlightentities;i++)
+                                       R_Shadow_DrawEntityLight(lightentities[i], numsurfaces, surfacelist);
+                               for (i = 0;i < numlightentities_noselfshadow;i++)
+                                       R_Shadow_DrawEntityLight(lightentities_noselfshadow[i], numsurfaces, surfacelist);
+                       }
                }
        }
 }
@@ -3018,7 +3090,7 @@ void R_DrawModelShadows(void)
        else
                r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL;
 
-       R_Shadow_RenderMode_StencilShadowVolumes();
+       R_Shadow_RenderMode_StencilShadowVolumes(true);
 
        for (i = 0;i < r_refdef.numentities;i++)
        {
@@ -3544,7 +3616,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                data = r_refdef.worldmodel->brush.entities;
        if (!data)
                return;
-       for (entnum = 0;COM_ParseTokenConsole(&data) && com_token[0] == '{';entnum++)
+       for (entnum = 0;COM_ParseToken_Simple(&data, false) && com_token[0] == '{';entnum++)
        {
                type = LIGHTTYPE_MINUSX;
                origin[0] = origin[1] = origin[2] = 0;
@@ -3562,7 +3634,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                islight = false;
                while (1)
                {
-                       if (!COM_ParseTokenConsole(&data))
+                       if (!COM_ParseToken_Simple(&data, false))
                                break; // error
                        if (com_token[0] == '}')
                                break; // end of entity
@@ -3572,7 +3644,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                                strlcpy(key, com_token, sizeof(key));
                        while (key[strlen(key)-1] == ' ') // remove trailing spaces
                                key[strlen(key)-1] = 0;
-                       if (!COM_ParseTokenConsole(&data))
+                       if (!COM_ParseToken_Simple(&data, false))
                                break; // error
                        strlcpy(value, com_token, sizeof(value));
 
@@ -4180,24 +4252,24 @@ void R_Shadow_EditLights_DrawSelectedLightProperties(void)
        for (lightcount = 0, light = r_shadow_worldlightchain;light;lightcount++, light = light->next)
                if (light == r_shadow_selectedlight)
                        lightnumber = lightcount;
-       sprintf(temp, "Cursor  %f %f %f  Total Lights %i", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2], lightcount);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
+       sprintf(temp, "Cursor  %f %f %f  Total Lights %i", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2], lightcount);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
        if (r_shadow_selectedlight == NULL)
                return;
-       sprintf(temp, "Light #%i properties", lightnumber);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Origin       : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Angles       : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Color        : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Radius       : %f\n", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Corona       : %f\n", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Style        : %i\n", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "CoronaSize   : %f\n", r_shadow_selectedlight->coronasizescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Ambient      : %f\n", r_shadow_selectedlight->ambientscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Diffuse      : %f\n", r_shadow_selectedlight->diffusescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "Specular     : %f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
-       sprintf(temp, "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0);y += 8;
+       sprintf(temp, "Light #%i properties", lightnumber);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Origin       : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Angles       : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Color        : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Radius       : %f\n", r_shadow_selectedlight->radius);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Corona       : %f\n", r_shadow_selectedlight->corona);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Style        : %i\n", r_shadow_selectedlight->style);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Shadows      : %s\n", r_shadow_selectedlight->shadow ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Cubemap      : %s\n", r_shadow_selectedlight->cubemapname);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "CoronaSize   : %f\n", r_shadow_selectedlight->coronasizescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Ambient      : %f\n", r_shadow_selectedlight->ambientscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Diffuse      : %f\n", r_shadow_selectedlight->diffusescale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "Specular     : %f\n", r_shadow_selectedlight->specularscale);DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "NormalMode   : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
+       sprintf(temp, "RealTimeMode : %s\n", (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? "yes" : "no");DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, true);y += 8;
 }
 
 void R_Shadow_EditLights_ToggleShadow_f(void)