}
// 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];
}
nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
farclip = 1.0f;
bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
- r_shadow_shadowmap_parameters[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
- r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
+ r_shadow_shadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
+ r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
r_shadow_shadowmapside = side;
r_shadow_shadowmapsize = size;
switch (r_shadow_shadowmode)
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+ r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
break;
case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+ r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
break;
case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
r_shadow_shadowmap_parameters[0] = 1.0f;
- r_shadow_shadowmap_parameters[1] = 1.0f;
+ r_shadow_shadowmap_parameters[2] = 1.0f;
R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
extern cvar_t r_shadows_castfrombmodels;
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)
{
int i;
float scale, size, radius, dot1, dot2;
- vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowmins, shadowmaxs;
+ vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
entity_render_t *ent;
if (!r_refdef.scene.numentities)
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
break;
- case R_SHADOW_SHADOWMODE_STENCIL;
+ case R_SHADOW_SHADOWMODE_STENCIL:
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
- R_AnimCache_GetEntity(ent false, false);
+ R_AnimCache_GetEntity(ent, false, false);
}
return;
default:
}
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);
VectorNormalize(shadowdir);
dot1 = DotProduct(r_refdef.view.forward, shadowdir);
VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
VectorNormalize(shadowforward);
CrossProduct(shadowdir, shadowforward, shadowright);
- VectorMA(r_refdef.view.origin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
+ Math_atov(r_shadows_focus.string, shadowfocus);
+ VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
+ VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
+ VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
+ VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
+ if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
+ dot1 = 1;
+ VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0]));
shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1]));
void R_DrawModelShadowMaps(void)
{
int i;
- float relativethrowdistance, scale, size, radius, nearclip, farclip, dot1, dot2;
+ float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2;
entity_render_t *ent;
vec3_t relativelightorigin;
vec3_t relativelightdirection, relativeforward, relativeright;
vec3_t relativeshadowmins, relativeshadowmaxs;
- vec3_t shadowdir, shadowforward, shadowright, shadoworigin;
+ vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
float m[12];
- matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix;
+ matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
r_viewport_t viewport;
GLuint fbo = 0;
}
size = 2*r_shadow_shadowmapmaxsize;
-
- r_shadow_shadowmap_parameters[0] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
- r_shadow_shadowmap_parameters[1] = 1.0f;
- r_shadow_shadowmap_parameters[2] = size;
- r_shadow_shadowmap_parameters[3] = size;
-
- scale = r_shadow_shadowmapping_precision.value;
- radius = 0.5f * size / scale;
+ 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;
+ bias = r_shadow_shadowmapping_bias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
+
+ r_shadow_shadowmap_parameters[0] = size;
+ r_shadow_shadowmap_parameters[1] = size;
+ r_shadow_shadowmap_parameters[2] = 1.0;
+ r_shadow_shadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
+
Math_atov(r_shadows_throwdirection.string, shadowdir);
VectorNormalize(shadowdir);
+ Math_atov(r_shadows_focus.string, shadowfocus);
+ VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
+ VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
+ VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
+ VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin);
dot1 = DotProduct(r_refdef.view.forward, shadowdir);
dot2 = DotProduct(r_refdef.view.up, shadowdir);
if (fabs(dot1) <= fabs(dot2))
VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
VectorNormalize(shadowforward);
VectorM(scale, shadowforward, &m[0]);
- m[3] = fabs(dot1) * 0.5f * size - DotProduct(r_refdef.view.origin, &m[0]);
+ if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2])
+ dot1 = 1;
+ m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]);
CrossProduct(shadowdir, shadowforward, shadowright);
VectorM(scale, shadowright, &m[4]);
- m[7] = 0.5f * size - DotProduct(r_refdef.view.origin, &m[4]);
+ m[7] = 0.5f - DotProduct(shadoworigin, &m[4]);
VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
- m[11] = 0.5f - DotProduct(r_refdef.view.origin, &m[8]);
+ m[11] = 0.5f - DotProduct(shadoworigin, &m[8]);
Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
- R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, size, size, 0, 0, -1, NULL);
+ R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, 0, 1, 1, 0, -1, NULL);
- VectorMA(r_refdef.view.origin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
+ VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
#if 0
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
- Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &shadowmatrix, &invmvpmatrix);
+ Matrix4x4_CreateScale3(&scalematrix, size, -size, 1);
+ Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias);
+ Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix);
+ Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix);
r_shadow_usingshadowmaportho = true;
switch (r_shadow_shadowmode)