r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
break;
}
+ // Cg has very little choice in depth texture sampling
+ if (vid.cgcontext)
+ {
+ r_shadow_shadowmapsampler = false;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
+ }
}
break;
case RENDERPATH_GL13:
}
// this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
// check if frustum corners/origin cross plane sides
+#if 1
+ // infinite version, assumes frustum corners merely give direction and extend to infinite distance
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
+ dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
+ masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+ masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+ dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
+ masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+ dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
+ masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+ for (i = 0;i < 4;i++)
+ {
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
+ VectorSubtract(n, p, n);
+ dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
+ if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
+ dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
+ if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
+ dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
+ if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
+ }
+#else
+ // finite version, assumes corners are a finite distance from origin dependent on far plane
for (i = 0;i < 5;i++)
{
Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
- dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn),
+ dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
- dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn),
+ dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
- dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn),
+ dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
}
+#endif
return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
}
static entity_render_t *lightentities_noselfshadow[MAX_EDICTS];
static entity_render_t *shadowentities[MAX_EDICTS];
static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
+ qboolean nolight;
rtlight->draw = false;
// 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)
- if (VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f))
- return;
+ nolight = VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f);
// loading is done before visibility checks because loading should happen
// all at once at the start of a level, not when it stalls gameplay.
// (especially important to benchmarks)
// compile light
- if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
+ if (rtlight->isstatic && !nolight && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
{
if (rtlight->compiled)
R_RTLight_Uncompile(rtlight);
if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f))
return;
+ // skip processing on corona-only lights
+ if (nolight)
+ return;
+
// if the light box is offscreen, skip it
if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs))
return;
extern cvar_t r_shadows_throwdistance;
extern cvar_t r_shadows_throwdirection;
extern cvar_t r_shadows_focus;
+extern cvar_t r_shadows_shadowmapscale;
void R_Shadow_PrepareModelShadows(void)
{
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
- break;
+ if (r_shadows.integer >= 2)
+ break;
+ // fall through
case R_SHADOW_SHADOWMODE_STENCIL:
for (i = 0;i < r_refdef.scene.numentities;i++)
{
}
size = 2*r_shadow_shadowmapmaxsize;
- scale = r_shadow_shadowmapping_precision.value;
+ scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
radius = 0.5f * size / scale;
Math_atov(r_shadows_throwdirection.string, shadowdir);
}
size = 2*r_shadow_shadowmapmaxsize;
- scale = r_shadow_shadowmapping_precision.value / size;
+ scale = (r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value) / size;
radius = 0.5f / scale;
nearclip = -r_shadows_throwdistance.value;
farclip = r_shadows_throwdistance.value;
vec3_t relativeshadowmins, relativeshadowmaxs;
vec3_t tmp, shadowdir;
- if (!r_refdef.scene.numentities || !vid.stencil || r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL)
+ if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
return;
CHECKGLERROR
{
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)
+ if(ent->entitynumber >= MAX_EDICTS) // csqc entity
{
- entnum2 = cl.entities[entnum].state_current.tagentity;
- if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
- entnum = entnum2;
- else
- break;
+ // FIXME handle this
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
}
- if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
+ else
{
- 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);
+ // 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);
}
else
VectorNegate(ent->modellight_lightdir, relativelightdirection);