]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
player model no longer shadows gun model
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 7 Apr 2007 12:36:25 +0000 (12:36 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 7 Apr 2007 12:36:25 +0000 (12:36 +0000)
technical explanation: this was done by adding a RENDER_NOSELFSHADOW flag which is used on view models, this flag prevents any entities using the flag from shadowing themselves or eachother...  then another hack was added to queue the shadowing of the RENDER_EXTERIORMODEL entities in the RENDER_NOSELFSHADOW batch (so it does not shadow other RENDER_NOSELFSHADOW entities), but still have it receive shadows by lighting it in the normal self-shadowing batch...   In more general use the RENDER_NOSELFSHADOW flag could be used to make characters not shadow themselves (like in Doom3), however r_shadow_frontsidecasting 0 is a better approach to that problem (partial self-shadowing characters)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7070 d7cf8633-e32d-0410-b094-e92efae38249

cl_main.c
csprogs.c
gl_rsurf.c
protocol.c
protocol.h
r_shadow.c
todo

index a159d68490a0bc71038bf0632b7efc1296ab415d..136749b79985843e78c0f4d65128365cb40d81f8 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -1003,6 +1003,8 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
         && !(e->render.flags & RENDER_VIEWMODEL)
         && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
                e->render.flags |= RENDER_SHADOW;
+       if (e->render.flags & RENDER_VIEWMODEL)
+               e->render.flags |= RENDER_NOSELFSHADOW;
 }
 
 // creates light and trails from an entity
index 4762810b58ef5b7fe238eef3ae12b5ab1ad3a85d..1acbddfb36a7df4bc6b9dcc26fbd99ce2394f90f 100644 (file)
--- a/csprogs.c
+++ b/csprogs.c
@@ -201,6 +201,8 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed)
         && !(e->render.flags & RENDER_VIEWMODEL)
         && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer)))
                e->render.flags |= RENDER_SHADOW;
+       if (e->render.flags & (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL))
+               e->render.flags |= RENDER_NOSELFSHADOW;
 
        return true;
 }
index a5d1e3f3f71a4b2144948069aaa95712adfa1c42..fb94ed8146b8c8076140ecf57528eaeed0c313ab 100644 (file)
@@ -983,7 +983,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface
        model_t *model = ent->model;
        msurface_t *surface;
        int i, k, l, m, mend, endsurface, batchnumsurfaces, batchnumtriangles, batchfirstvertex, batchlastvertex;
-       qboolean usebufferobject;
+       qboolean usebufferobject, culltriangles;
        const int *element3i;
        msurface_t *batchsurfacelist[RSURF_MAX_BATCHSURFACES];
        int batchelements[BATCHSIZE*3];
@@ -992,6 +992,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface
        RSurf_ActiveModelEntity(ent, true, true);
        R_UpdateAllTextureInfo(ent);
        CHECKGLERROR
+       culltriangles = r_shadow_culltriangles.integer && !(ent->flags & RENDER_NOSELFSHADOW);
        element3i = rsurface_model->surfmesh.data_element3i;
        // this is a double loop because non-visible surface skipping has to be
        // fast, and even if this is not the world model (and hence no visibility
@@ -1049,7 +1050,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface
                                                RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
                                                for (m = surface->num_firsttriangle, mend = m + surface->num_triangles;m < mend;m++)
                                                {
-                                                       if (r_shadow_culltriangles.integer)
+                                                       if (culltriangles)
                                                        {
                                                                if (trispvs)
                                                                {
index 7889e23b1b93f3629d42cc8923620e8810532ef8..9786497eaa9bfdcffe64daad05d9cd9105f9e43a 100644 (file)
@@ -2008,6 +2008,8 @@ void EntityState5_ReadUpdate(entity_state_t *s)
                                Con_Print(" SHADOW");
                        if (s->flags & RENDER_LIGHT)
                                Con_Print(" LIGHT");
+                       if (s->flags & RENDER_NOSELFSHADOW)
+                               Con_Print(" NOSELFSHADOW");
                        Con_Print(")");
                }
                if (bits & E5_ALPHA)
index c7bbf20503b1ec2b5bf4ec20dc0290f84dcad7b8..95bab5500b87102ae019e8e63ee0006c43b8a302 100644 (file)
@@ -319,6 +319,8 @@ void Protocol_Names(char *buffer, size_t buffersize);
 #define RENDER_COLORMAPPED 32
 #define RENDER_SHADOW 65536 // cast shadow
 #define RENDER_LIGHT 131072 // receive light
+#define RENDER_NOSELFSHADOW 262144 // render lighting on this entity before its own shadow is added to the scene
+// (note: all RENDER_NOSELFSHADOW entities are grouped together and rendered in a batch before their shadows are rendered, so they can not shadow eachother either)
 
 // this is 96 bytes
 typedef struct entity_state_s
index 61c23ec11d5c030d8e897290d0b937e4f02ca72b..897d352ee201a54650bee4446480f92e683f9305 100644 (file)
@@ -2749,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)
@@ -2850,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)
        {
@@ -2875,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)
                        {
@@ -2893,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;
+                               }
                        }
                }
        }
@@ -2911,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(true);
-                       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);
+                       }
                }
        }
 }
diff --git a/todo b/todo
index 37b09dd6f2602181fb45858e1c11d619333c8392..0e66bd67099492d60634d8fbd3e5dc7a9c101f1d 100644 (file)
--- a/todo
+++ b/todo
@@ -1,11 +1,11 @@
 - todo: difficulty ratings are: 0 = trivial, 1 = easy, 2 = easy-moderate, 3 = moderate, 4 = moderate-hard, 5 = hard, 6 = hard++, 7 = nightmare, d = done, -d = done but have not notified the people who asked for it, f = failed, -f = failed but have not notified the people who asked for it
-0 bug darkplaces memory: memstats doesn't account for memory used by VBO/EBO buffers in models
 0 bug darkplaces client: can't move mouse around in nexuiz menu if vid_mouse is 0
 0 bug darkplaces client: decals are not sticking to submodels
 0 bug darkplaces client: if you press 1 during the demo loop when quake starts, escape doesn't do anything until you hit some other key (daemon)
 0 bug darkplaces loader: make rtlight entity loader support q3map/q3map2 lights properly, they use a spawnflag for LINEAR mode, by default they use 1/(x*x) falloff (Carni, motorsep)
 0 bug darkplaces loader: mcbsp hull selection is ignoring the custom hulls supported by mcbsp (div0)
 0 bug darkplaces loader: q1bsp loader computes wrong submodel size for submodels with no surfaces, such as a func_wall comprised entirely of SKIP or CAULK brushes (neg|ke)
+0 bug darkplaces memory: memstats doesn't account for memory used by VBO/EBO buffers in models
 0 bug darkplaces readme: it would be a very good idea to add documentation of sv_gameplayfix_* cvars in the readme as a means to run broken mods (xaGe)
 0 bug darkplaces renderer: GL13 path has broken handling of unlit surfaces in Nexuiz toxic.bsp - the small red light surfaces are black in GL13 path (m0rfar)
 0 bug darkplaces renderer: if an animated model has transparent surfaces, each one calls RSurf_ActiveModelEntity, recomputing all vertices
 0 feature darkplaces protocol: add lava-steam particle puff effect for bursting lava bubbles (Zombie)
 0 feature darkplaces protocol: add support for .float corona and corona_radius to control corona intensity and radius on dlights
 0 feature darkplaces prvm: if developer is >= 100, list unfreed strzone strings when level ends (div0)
+0 feature darkplaces prvm: modify PRVM_ExecuteProgram to be able to call builtins directly, and add prog->argc = before every PRVM_ExecuteProgram call (div0)
 0 feature darkplaces qc: add FTE_STRINGS extension, and specifically support -1 for strncmp/strncasecmp to compare whole string (div0)
 0 feature darkplaces quakec: DP_QC_STRFTIME extension providing strftime function to find out what the current time is with a format string (FrikaC)
 0 feature darkplaces quakec: add a DP_QC_STRCATREPEAT extension providing string(float atimes, string a[, float btimes, string b, [float ctimes, string c, [float dtimes, string d]]]) strcatrepeat = #???; which repeats the given strings a given number of times and concatenates them together (like many strcat calls), can be given 2, 4, 6, or 8 parameters, stores it into a temp buffer, and returns the temp buffer (FA-Zalon)