int vertexupdatenum;
int r_shadow_buffer_numleafpvsbytes;
+unsigned char *r_shadow_buffer_visitingleafpvs;
unsigned char *r_shadow_buffer_leafpvs;
int *r_shadow_buffer_leaflist;
cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
+cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "1", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
shadowmarklist = NULL;
shadowmarkcount = 0;
r_shadow_buffer_numleafpvsbytes = 0;
+ r_shadow_buffer_visitingleafpvs = NULL;
r_shadow_buffer_leafpvs = NULL;
r_shadow_buffer_leaflist = NULL;
r_shadow_buffer_numsurfacepvsbytes = 0;
shadowmarklist = NULL;
shadowmarkcount = 0;
r_shadow_buffer_numleafpvsbytes = 0;
+ if (r_shadow_buffer_visitingleafpvs)
+ Mem_Free(r_shadow_buffer_visitingleafpvs);
+ r_shadow_buffer_visitingleafpvs = NULL;
if (r_shadow_buffer_leafpvs)
Mem_Free(r_shadow_buffer_leafpvs);
r_shadow_buffer_leafpvs = NULL;
Cvar_RegisterVariable(&r_shadow_gloss2intensity);
Cvar_RegisterVariable(&r_shadow_glossintensity);
Cvar_RegisterVariable(&r_shadow_glossexponent);
+ Cvar_RegisterVariable(&r_shadow_glossexact);
Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
Cvar_RegisterVariable(&r_shadow_lightintensityscale);
shadowmarklist = NULL;
shadowmarkcount = 0;
r_shadow_buffer_numleafpvsbytes = 0;
+ r_shadow_buffer_visitingleafpvs = NULL;
r_shadow_buffer_leafpvs = NULL;
r_shadow_buffer_leaflist = NULL;
r_shadow_buffer_numsurfacepvsbytes = 0;
int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
{
+ if (r_shadow_buffer_visitingleafpvs)
+ Mem_Free(r_shadow_buffer_visitingleafpvs);
if (r_shadow_buffer_leafpvs)
Mem_Free(r_shadow_buffer_leafpvs);
if (r_shadow_buffer_leaflist)
Mem_Free(r_shadow_buffer_leaflist);
r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
+ r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
}
// this variable must be set for the CompileShadowVolume code
r_shadow_compilingrtlight = rtlight;
R_Shadow_EnlargeLeafSurfaceTrisBuffer(model->brush.num_leafs, model->num_surfaces, model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles, model->surfmesh.num_triangles);
- model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs);
+ model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs);
numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
{
size_t lightindex;
dlight_t *light;
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (!light)
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];
+ static entity_render_t *lightentities[MAX_EDICTS];
+ static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
+ static entity_render_t *shadowentities[MAX_EDICTS];
+ static 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)
// dynamic light, world available and can receive realtime lighting
// calculate lit surfaces and leafs
R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
- r_refdef.scene.worldmodel->GetLightInfo(r_refdef.scene.worldentity, rtlight->shadoworigin, rtlight->radius, rsurface.rtlight_cullmins, rsurface.rtlight_cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs);
+ r_refdef.scene.worldmodel->GetLightInfo(r_refdef.scene.worldentity, rtlight->shadoworigin, rtlight->radius, rsurface.rtlight_cullmins, rsurface.rtlight_cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs);
leaflist = r_shadow_buffer_leaflist;
leafpvs = r_shadow_buffer_leafpvs;
surfacelist = r_shadow_buffer_surfacelist;
int lnum;
size_t lightindex;
dlight_t *light;
+ size_t range;
if (r_editlights.integer)
R_Shadow_DrawLightSprites();
}
else
{
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light && (light->flags & flag))
}
extern void R_SetupView(qboolean allowwaterclippingplane);
+extern cvar_t r_shadows;
extern cvar_t r_shadows_throwdistance;
void R_DrawModelShadows(void)
{
vec3_t relativelightorigin;
vec3_t relativelightdirection;
vec3_t relativeshadowmins, relativeshadowmaxs;
+ vec3_t tmp;
float vertex3f[12];
if (!r_drawentities.integer || !gl_stencil)
relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
- VectorNegate(ent->modellight_lightdir, relativelightdirection);
+
+ if(r_shadows.integer == 2)
+ {
+ // 2: simpler mode, throw shadows always DOWN
+ VectorSet(tmp, 0, 0, -1);
+ Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
+ }
+ else
+ {
+ if(ent->entitynumber != 0)
+ {
+ // 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);
+ }
+ else
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ }
+
VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
RSurf_ActiveModelEntity(ent, false, false);
ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->surfacelist, relativeshadowmins, relativeshadowmaxs);
size_t lightindex;
dlight_t *light;
rtlight_t *rtlight;
+ size_t range;
if (r_coronas.value < (1.0f / 256.0f) && !gl_flashblend.integer)
return;
R_Mesh_Matrix(&identitymatrix);
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
// FIXME: these traces should scan all render entities instead of cl.world
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (!light)
{
size_t lightindex;
dlight_t *light;
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light)
{
size_t lightindex;
dlight_t *light;
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light)
dlight_t *best;
size_t lightindex;
dlight_t *light;
+ size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
best = NULL;
bestrating = 0;
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (!light)
char *buf, *oldbuf;
char name[MAX_QPATH];
char line[MAX_INPUTLINE];
- if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray))
+ size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked, assuming the dpsnprintf mess doesn't screw it up...
+ // I hate lines which are 3 times my screen size :( --blub
+ if (!range)
return;
if (cl.worldmodel == NULL)
{
strlcat (name, ".rtlights", sizeof (name));
bufchars = bufmaxchars = 0;
buf = NULL;
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (!light)
{
size_t lightindex;
dlight_t *light;
+ size_t range;
if (!r_editlights.integer)
{
return;
}
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ // EditLights doesn't seem to have a "remove" command or something so:
+ range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (!light)
void R_Shadow_EditLights_DrawSelectedLightProperties(void)
{
int lightnumber, lightcount;
- size_t lightindex;
+ size_t lightindex, range;
dlight_t *light;
float x, y;
char temp[256];
DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0);
lightnumber = -1;
lightcount = 0;
- for (lightindex = 0;lightindex < Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);lightindex++)
+ range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
light = Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (!light)