]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
fix segfault sendcvar for non existing cvars introduced in r6933
[xonotic/darkplaces.git] / r_shadow.c
index cc4e6a13a39a1a5021280dfb3721ef067c708991..897d352ee201a54650bee4446480f92e683f9305 100644 (file)
@@ -1006,6 +1006,7 @@ void R_Shadow_RenderMode_Begin(void)
        R_Mesh_ColorPointer(NULL, 0, 0);
        R_Mesh_ResetTextureState();
        GL_BlendFunc(GL_ONE, GL_ZERO);
+       GL_DepthRange(0, 1);
        GL_DepthTest(true);
        GL_DepthMask(false);
        GL_Color(0, 0, 0, 1);
@@ -1046,6 +1047,7 @@ void R_Shadow_RenderMode_Reset(void)
        }
        R_Mesh_ColorPointer(NULL, 0, 0);
        R_Mesh_ResetTextureState();
+       GL_DepthRange(0, 1);
        GL_DepthTest(true);
        GL_DepthMask(false);
        qglDepthFunc(GL_LEQUAL);CHECKGLERROR
@@ -1060,7 +1062,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();
@@ -1086,7 +1088,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++;
 }
 
@@ -1132,6 +1135,7 @@ void R_Shadow_RenderMode_VisibleShadowVolumes(void)
        CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_BlendFunc(GL_ONE, GL_ONE);
+       GL_DepthRange(0, 1);
        GL_DepthTest(r_showshadowvolumes.integer < 2);
        GL_Color(0.0, 0.0125 * r_view.colorscale, 0.1 * r_view.colorscale, 1);
        qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
@@ -1144,6 +1148,7 @@ void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transpar
        CHECKGLERROR
        R_Shadow_RenderMode_Reset();
        GL_BlendFunc(GL_ONE, GL_ONE);
+       GL_DepthRange(0, 1);
        GL_DepthTest(r_showlighting.integer < 2);
        GL_Color(0.1 * r_view.colorscale, 0.0125 * r_view.colorscale, 0, 1);
        if (!transparent)
@@ -2237,7 +2242,6 @@ static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertice
 void R_Shadow_RenderLighting(int firstvertex, int numvertices, int numtriangles, const int *element3i, int element3i_bufferobject, size_t element3i_bufferoffset)
 {
        float ambientscale, diffusescale, specularscale;
-       // FIXME: support MATERIALFLAG_NODEPTHTEST
        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;
@@ -2254,6 +2258,7 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int numtriangles,
        }
        if ((ambientscale + diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
                return;
+       GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
        GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
        GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
        if (rsurface_texture->colormapping)
@@ -2744,15 +2749,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)
@@ -2845,7 +2854,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)
        {
@@ -2870,12 +2881,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)
                        {
@@ -2888,7 +2913,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;
+                               }
                        }
                }
        }
@@ -2906,51 +2936,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);
+                       }
                }
        }
 }
@@ -3014,7 +3088,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++)
        {
@@ -3053,6 +3127,7 @@ void R_DrawModelShadows(void)
 
        // set up a 50% darkening blend on shadowed areas
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       GL_DepthRange(0, 1);
        GL_DepthTest(false);
        GL_DepthMask(false);
        qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
@@ -3272,7 +3347,7 @@ void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const r
 {
        // this is never batched (there can be only one)
        float scale = r_editlights_cursorgrid.value * 0.5f;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[1]->tex, NULL, false, r_editlights_cursorlocation, r_view.right, r_view.up, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[1]->tex, NULL, false, false, r_editlights_cursorlocation, r_view.right, r_view.up, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
 }
 
 void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
@@ -3286,7 +3361,7 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, co
                intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0);
        if (!light->shadow)
                intensity *= 0.5f;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacelist[0]]->tex, NULL, false, light->origin, r_view.right, r_view.up, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacelist[0]]->tex, NULL, false, false, light->origin, r_view.right, r_view.up, 8, -8, -8, 8, intensity, intensity, intensity, 0.5f);
 }
 
 void R_Shadow_DrawLightSprites(void)