typedef enum r_shadow_shadowmode_e
{
- R_SHADOW_SHADOWMODE_STENCIL,
- R_SHADOW_SHADOWMODE_SHADOWMAP2D
+ R_SHADOW_SHADOWMODE_STENCIL,
+ R_SHADOW_SHADOWMODE_SHADOWMAP2D
}
r_shadow_shadowmode_t;
matrix4x4_t r_shadow_shadowmapmatrix;
int r_shadow_lightscissor[4];
qboolean r_shadow_usingdeferredprepass;
-
+qboolean r_shadow_shadowmapdepthtexture;
int maxshadowtriangles;
int *shadowelements;
// lights are reloaded when this changes
char r_shadow_mapname[MAX_QPATH];
+// buffer for doing corona fading
+unsigned int r_shadow_occlusion_buf = 0;
+
// used only for light filters (cubemaps)
rtexturepool_t *r_shadow_filters_texturepool;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmapsampler = false;
r_shadow_shadowmappcf = 0;
+ r_shadow_shadowmapdepthtexture = r_fb.usedepthtextures;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
{
r_shadow_shadowmapsampler = true;
r_shadow_shadowmappcf = 1;
}
- else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
- r_shadow_shadowmappcf = 1;
+ else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
+ r_shadow_shadowmappcf = 1;
else if((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa"))
r_shadow_shadowmappcf = 1;
else
}
else
{
+ r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
switch (r_shadow_shadowmapfilterquality)
{
case 1:
- r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
break;
case 2:
- r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
r_shadow_shadowmappcf = 1;
break;
case 3:
void R_Shadow_PrepareShadowSides(int numtris)
{
- if (maxshadowsides < numtris)
- {
- maxshadowsides = numtris;
- if (shadowsides)
+ if (maxshadowsides < numtris)
+ {
+ maxshadowsides = numtris;
+ if (shadowsides)
Mem_Free(shadowsides);
if (shadowsideslist)
Mem_Free(shadowsideslist);
else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
{
tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
- R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0);
R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
}
else
tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
else
tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
- r_refdef.stats.lights_dynamicshadowtriangles += tris;
- r_refdef.stats.lights_shadowtriangles += tris;
+ r_refdef.stats[r_stat_lights_dynamicshadowtriangles] += tris;
+ r_refdef.stats[r_stat_lights_shadowtriangles] += tris;
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
{
// increment stencil if frontface is infront of depthbuffer
GL_CullFace(r_refdef.view.cullface_back);
R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
}
- R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0);
R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
}
}
int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
{
- // p1, p2, p3 are in the cubemap's local coordinate system
- // bias = border/(size - border)
+ // p1, p2, p3 are in the cubemap's local coordinate system
+ // bias = border/(size - border)
int mask = 0x3F;
- float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
+ float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<4)
+ mask &= (3<<4)
| (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
| (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
| (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<4)
- | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-
- dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
- if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<0)
- | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<0)
- | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-
- dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
- if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<2)
- | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<2)
- | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<4)
+ | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+
+ dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
+ if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
+ mask &= (3<<0)
+ | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<0)
+ | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+
+ dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
+ if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
+ mask &= (3<<2)
+ | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<2)
+ | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
return mask;
}
int mask = 0x3F;
VectorSubtract(maxs, mins, radius);
- VectorScale(radius, 0.5f, radius);
- VectorAdd(mins, radius, center);
- Matrix4x4_Transform(worldtolight, center, lightcenter);
+ VectorScale(radius, 0.5f, radius);
+ VectorAdd(mins, radius, center);
+ Matrix4x4_Transform(worldtolight, center, lightcenter);
Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
VectorSubtract(lightcenter, lightradius, pmin);
VectorAdd(lightcenter, lightradius, pmax);
- dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<4)
- | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
- | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<4)
- | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-
- dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<0)
- | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<0)
- | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-
- dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<2)
- | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<2)
- | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
-
- return mask;
+ dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<4)
+ | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
+ | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<4)
+ | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+
+ dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<0)
+ | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<0)
+ | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+
+ dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<2)
+ | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<2)
+ | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+
+ return mask;
}
#define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
{
- // p is in the cubemap's local coordinate system
- // bias = border/(size - border)
- float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
- float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
- float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
- int mask = 0x3F;
- if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
- if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
- if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
- if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
- if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
- if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
- return mask;
+ // p is in the cubemap's local coordinate system
+ // bias = border/(size - border)
+ float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
+ float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
+ float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
+ int mask = 0x3F;
+ if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
+ if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
+ if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
+ if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
+ if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
+ if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
+ return mask;
}
static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
}
if (PlaneDiff(o, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
{
- Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
- len = scale*VectorLength2(n);
+ Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
+ len = scale*VectorLength2(n);
if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
// 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);
- }
+ // 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
+ // 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);
void R_Shadow_ClearStencil(void)
{
GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 128);
- r_refdef.stats.lights_clears++;
+ r_refdef.stats[r_stat_lights_clears]++;
}
void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
GL_ColorMask(0, 0, 0, 0);
GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
GL_CullFace(GL_NONE);
- R_SetupShader_DepthOrShadow(false, false);
+ R_SetupShader_DepthOrShadow(false, false, false); // FIXME test if we have a skeletal model?
r_shadow_rendermode = mode;
switch(mode)
{
R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
else
R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
GL_DepthTest(true);
GL_DepthFunc(GL_GREATER);
GL_CullFace(r_refdef.view.cullface_back);
- R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL, 0);
R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
}
if (enable && r_shadow_bouncegrid_static.integer)
{
enable = false;
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
for (lightindex = 0;lightindex < range;lightindex++)
{
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
// clear variables that produce warnings otherwise
memset(splatcolor, 0, sizeof(splatcolor));
// iterate world rtlights
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
range1 = settings.staticmode ? 0 : r_refdef.scene.numlights;
range2 = range + range1;
photoncount = 0;
w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
if (w * VectorLength2(rtlight->color) == 0.0f)
continue;
- w *= (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
+ w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
VectorScale(rtlight->color, w, rtlight->photoncolor);
//if (!VectorLength2(rtlight->photoncolor))
// continue;
radius = rtlight->radius * settings.lightradiusscale;
s = settings.particleintensity / shootparticles;
VectorScale(rtlight->photoncolor, s, baseshotcolor);
- r_refdef.stats.bouncegrid_lights++;
- r_refdef.stats.bouncegrid_particles += shootparticles;
+ r_refdef.stats[r_stat_bouncegrid_lights]++;
+ r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles;
for (shotparticles = 0;shotparticles < shootparticles;shotparticles++)
{
if (settings.stablerandom > 0)
VectorMA(clipstart, radius, clipend, clipend);
for (bouncecount = 0;;bouncecount++)
{
- r_refdef.stats.bouncegrid_traces++;
+ r_refdef.stats[r_stat_bouncegrid_traces]++;
//r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
//r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
if (settings.staticmode)
{
// static mode fires a LOT of rays but none of them are identical, so they are not cached
- cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, true, false, NULL, true, true);
+ cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, collision_extendmovelength.value, true, false, NULL, true, true);
}
else
{
VectorMA(clipstart, 0.5f, stepdelta, steppos);
for (step = 0;step < numsteps;step++)
{
- r_refdef.stats.bouncegrid_splats++;
+ r_refdef.stats[r_stat_bouncegrid_splats]++;
// figure out which texture pixel this is in
texlerp[1][0] = ((steppos[0] - mins[0]) * ispacing[0]) - 0.5f;
texlerp[1][1] = ((steppos[1] - mins[1]) * ispacing[1]) - 0.5f;
}
if (cliptrace.fraction >= 1.0f)
break;
- r_refdef.stats.bouncegrid_hits++;
+ r_refdef.stats[r_stat_bouncegrid_hits]++;
if (bouncecount >= maxbounce)
break;
// scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
VectorMultiply(shotcolor, surfcolor, shotcolor);
if (VectorLength2(baseshotcolor) == 0.0f)
break;
- r_refdef.stats.bouncegrid_bounces++;
+ r_refdef.stats[r_stat_bouncegrid_bounces]++;
if (settings.bounceanglediffuse)
{
// random direction, primarily along plane normal
|| r_shadow_lightscissor[1] != r_refdef.view.viewport.y
|| r_shadow_lightscissor[2] != r_refdef.view.viewport.width
|| r_shadow_lightscissor[3] != r_refdef.view.viewport.height)
- r_refdef.stats.lights_scissored++;
+ r_refdef.stats[r_stat_lights_scissored]++;
return false;
}
lighttris++;
shadowtris = 0;
- if (rtlight->static_numlighttrispvsbytes)
+ if (rtlight->static_numshadowtrispvsbytes)
for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
shadowtris++;
{
if (!mesh->sidetotals[r_shadow_shadowmapside])
continue;
- r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
- if (mesh->vertex3fbuffer)
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer);
- else
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer);
+ r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->sidetotals[r_shadow_shadowmapside];
+ R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
}
CHECKGLERROR
mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
for (;mesh;mesh = mesh->next)
{
- r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
- if (mesh->vertex3fbuffer)
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer);
- else
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer);
+ r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->numtriangles;
+ R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
{
// increment stencil if frontface is infront of depthbuffer
static entity_render_t *shadowentities[MAX_EDICTS];
static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
qboolean nolight;
+ qboolean castshadows;
rtlight->draw = false;
rtlight->cached_numlightentities = 0;
rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
// look up the light style value at this time
- f = (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
+ f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
VectorScale(rtlight->color, f, rtlight->currentcolor);
/*
if (rtlight->selected)
return;
// count this light in the r_speeds
- r_refdef.stats.lights++;
+ r_refdef.stats[r_stat_lights]++;
// flag it as worth drawing later
rtlight->draw = true;
+ // if we have shadows disabled, don't count the shadow entities, this way we don't do the R_AnimCache_GetEntity on each one
+ castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows);
+ if (!castshadows)
+ numshadowentities = numshadowentities_noselfshadow = 0;
+
// cache all the animated entities that cast a shadow but are not visible
for (i = 0;i < numshadowentities;i++)
- if (!shadowentities[i]->animcache_vertex3f)
- R_AnimCache_GetEntity(shadowentities[i], false, false);
+ R_AnimCache_GetEntity(shadowentities[i], false, false);
for (i = 0;i < numshadowentities_noselfshadow;i++)
- if (!shadowentities_noselfshadow[i]->animcache_vertex3f)
- R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
+ R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
// allocate some temporary memory for rendering this light later in the frame
// reusable buffers need to be copied, static data can be used as-is
r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) ||
r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
- r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
+ r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16) ||
+ r_shadow_shadowmapdepthtexture != r_fb.usedepthtextures)
R_Shadow_FreeShadowMaps();
r_shadow_fb_fbo = fbo;
for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
{
rtlight_t *rtlight = r_refdef.scene.lights[lnum];
- f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
+ f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
VectorScale(rtlight->color, f, rtlight->currentcolor);
}
}
R_Shadow_RenderMode_End();
}
+#define MAX_MODELSHADOWS 1024
+static int r_shadow_nummodelshadows;
+static entity_render_t *r_shadow_modelshadows[MAX_MODELSHADOWS];
+
void R_Shadow_PrepareModelShadows(void)
{
int i;
vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
entity_render_t *ent;
+ r_shadow_nummodelshadows = 0;
if (!r_refdef.scene.numentities)
return;
break;
// fall through
case R_SHADOW_SHADOWMODE_STENCIL:
+ if (!vid.stencil)
+ return;
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))
+ if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ {
+ if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
+ break;
+ r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
R_AnimCache_GetEntity(ent, false, false);
+ }
}
return;
default:
if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
continue;
// cast shadows from anything of the map (submodels are optional)
- if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ {
+ if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
+ break;
+ r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
R_AnimCache_GetEntity(ent, false, false);
+ }
}
}
GLuint shadowfbo = 0;
float clearcolor[4];
- if (!r_refdef.scene.numentities)
+ if (!r_shadow_nummodelshadows)
return;
switch (r_shadow_shadowmode)
R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
else
R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
// outside the usable area
GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
-#if 0
- // debugging
- R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
- R_SetupShader_ShowDepth(true);
- GL_ColorMask(1,1,1,1);
- GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
-#endif
-
- for (i = 0;i < r_refdef.scene.numentities;i++)
- {
- ent = r_refdef.scene.entities[i];
-
- // cast shadows from anything of the map (submodels are optional)
- if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
- {
- relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
- Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
- relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
- relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
- relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
- relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
- relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
- relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
- RSurf_ActiveModelEntity(ent, false, false, false);
- ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
- rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
- }
+ for (i = 0;i < r_shadow_nummodelshadows;i++)
+ {
+ ent = r_shadow_modelshadows[i];
+ relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
+ Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
+ relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
+ relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
+ relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
+ relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
+ relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
+ relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
+ RSurf_ActiveModelEntity(ent, false, false, false);
+ ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
#if 0
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
-#ifdef OPENGL_ORIENTATION
+#ifdef MATRIX4x4_OPENGLORIENTATION
r_shadow_shadowmapmatrix.m[0][0] *= -1.0f;
r_shadow_shadowmapmatrix.m[0][1] *= -1.0f;
r_shadow_shadowmapmatrix.m[0][2] *= -1.0f;
vec3_t tmp, shadowdir;
prvm_vec3_t prvmshadowdir;
- if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
+ if (!r_shadow_nummodelshadows || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
return;
r_shadow_fb_fbo = fbo;
R_Shadow_ClearStencil();
- for (i = 0;i < r_refdef.scene.numentities;i++)
+ for (i = 0;i < r_shadow_nummodelshadows;i++)
{
- ent = r_refdef.scene.entities[i];
+ ent = r_shadow_modelshadows[i];
// cast shadows from anything of the map (submodels are optional)
- if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
+ VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
+ VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
+ if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
+ else
{
- relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
- VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
- VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
- if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
- else
+ if(ent->entitynumber != 0)
{
- if(ent->entitynumber != 0)
+ if(ent->entitynumber >= MAX_EDICTS) // csqc entity
{
- if(ent->entitynumber >= MAX_EDICTS) // csqc entity
+ // FIXME handle this
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ }
+ else
+ {
+ // 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)
{
- // FIXME handle this
- VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ entnum2 = cl.entities[entnum].state_current.tagentity;
+ if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
+ entnum = entnum2;
+ else
+ break;
}
- else
+ if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
{
- // 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);
+ 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, false);
- ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
- rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+ else
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
}
+
+ VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
+ RSurf_ActiveModelEntity(ent, false, false, false);
+ ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
// not really the right mode, but this will disable any silly stencil features
{
float zdist;
vec3_t centerorigin;
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
float vertex3f[12];
+#endif
// if it's too close, skip it
if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
return;
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
CHECKGLERROR
// NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
GL_DepthFunc(GL_ALWAYS);
R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
- R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
GL_DepthFunc(GL_LEQUAL);
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
- R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
CHECKGLERROR
static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
{
vec3_t color;
+ unsigned int occlude = 0;
GLint allpixels = 0, visiblepixels = 0;
+
// now we have to check the query result
if (rtlight->corona_queryindex_visiblepixels)
{
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
CHECKGLERROR
- qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
- qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
+ // See if we can use the GPU-side method to prevent implicit sync
+ if (vid.support.arb_query_buffer_object) {
+#define BUFFER_OFFSET(i) ((void*)NULL + (i))
+ if (!r_shadow_occlusion_buf) {
+ qglGenBuffersARB(1, &r_shadow_occlusion_buf);
+ qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
+ qglBufferDataARB(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY);
+ } else {
+ qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
+ }
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0));
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4));
+ qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
+ occlude = MATERIALFLAG_OCCLUDE;
+ } else {
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
+ if (visiblepixels < 1 || allpixels < 1)
+ return;
+ rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
+ }
+ cscale *= rtlight->corona_visibility;
CHECKGLERROR
-#endif
break;
+#else
+ return;
+#endif
case RENDERPATH_D3D9:
Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
+ return;
case RENDERPATH_D3D10:
Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
+ return;
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
+ return;
case RENDERPATH_SOFT:
//Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
- }
- //Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels);
- if (visiblepixels < 1 || allpixels < 1)
return;
- rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
- cscale *= rtlight->corona_visibility;
+ default:
+ return;
+ }
}
else
{
// FIXME: these traces should scan all render entities instead of cl.world
- if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
+ if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
return;
}
VectorScale(rtlight->currentcolor, cscale, color);
}
R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
- R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
+ R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST | occlude, 0, 4, 0, 2, false, false);
if(negated)
GL_BlendEquationSubtract(false);
}
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
if (usequery)
{
GL_ColorMask(0,0,0,0);
- if (r_maxqueries < (range + r_refdef.scene.numlights) * 2)
+ if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2)
if (r_maxqueries < MAX_OCCLUSION_QUERIES)
{
i = r_maxqueries;
- r_maxqueries = (range + r_refdef.scene.numlights) * 4;
+ r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
CHECKGLERROR
qglGenQueriesARB(r_maxqueries - i, r_queries + i);
static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
{
matrix4x4_t matrix;
+
+ // note that style is no longer validated here, -1 is used for unstyled lights and >= MAX_LIGHTSTYLES is accepted for sake of editing rtlights files that might be out of bounds but perfectly formatted
+
// validate parameters
- if (style < 0 || style >= MAX_LIGHTSTYLES)
- {
- Con_Printf("R_Shadow_NewWorldLight: invalid light style number %i, must be >= 0 and < %i\n", light->style, MAX_LIGHTSTYLES);
- style = 0;
- }
if (!cubemapname)
cubemapname = "";
unsigned int range;
dlight_t *light;
rtlight_t *rtlight;
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+ range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
if (lightindex >= range)
return -1;
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (rating >= 0.95)
{
rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
- if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1.0f)
+ if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f)
{
bestrating = rating;
best = light;
vec3_t dest, endpos;
trace_t trace;
VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
- trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true);
+ trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true);
if (trace.fraction < 1)
{
dist = trace.fraction * r_editlights_cursordistance.value;
if (!light)
continue;
if (light == r_shadow_selectedlight)
- lightnumber = lightindex;
+ lightnumber = (int)lightindex;
lightcount++;
}
dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
if (flags & LP_RTWORLD)
{
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
- numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+ numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
for (i = 0; i < numlights; i++)
{
dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
if (f <= 0)
continue;
// todo: add to both ambient and diffuse
- if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1)
+ if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
VectorMA(color, f, light->currentcolor, color);
}
}
if (f <= 0)
continue;
// todo: add to both ambient and diffuse
- if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1)
+ if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
VectorMA(color, f, light->color, color);
}
}
if (flags & LP_RTWORLD)
{
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
- numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+ numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
for (i = 0; i < numlights; i++)
{
dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value;
if (intensity <= 0.0f)
continue;
- if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
+ if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
continue;
// scale down intensity to add to both ambient and diffuse
//intensity *= 0.5f;
intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value;
if (intensity <= 0.0f)
continue;
- if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
+ if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
continue;
// scale down intensity to add to both ambient and diffuse
//intensity *= 0.5f;