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)
// 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)
{
// 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)
{
// 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;
+ }
}
}
}
// 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);
+ }
}
}
}
- 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)