29 #include "../idlib/precompiled.h"
112 #define TRIANGLE_CULLED(p1,p2,p3) ( pointCull[p1] & pointCull[p2] & pointCull[p3] & 0x3f )
115 #define TRIANGLE_CLIPPED(p1,p2,p3) ( ( ( pointCull[p1] & pointCull[p2] & pointCull[p3] ) & 0xfc0 ) != 0xfc0 )
118 #define EDGE_CULLED(p1,p2) ( ( pointCull[p1] ^ 0xfc0 ) & ( pointCull[p2] ^ 0xfc0 ) & 0xfc0 )
120 #define EDGE_CLIPPED(p1,p2) ( ( pointCull[p1] & pointCull[p2] & 0xfc0 ) != 0xfc0 )
124 #define POINT_CULLED(p1) ( ( pointCull[p1] & 0xfc0 ) != 0xfc0 )
127 #define LIGHT_CLIP_EPSILON 0.1f
129 #define MAX_CLIP_SIL_EDGES 2048
130 static int numClipSilEdges;
135 static byte *globalFacing;
139 static byte *faceCastsShadow;
143 #define MAX_SHADOW_INDEXES 0x18000
144 #define MAX_SHADOW_VERTS 0x18000
145 static int numShadowIndexes;
147 static int numShadowVerts;
149 static bool overflowed;
206 static bool callOptimizer;
215 static int indexFrustumNumber;
245 i = a[0] + a[1]*127 + a[2]*1023;
246 j = b[0] + b[1]*127 + b[2]*1023;
248 return (
bool)(i <
j);
267 lg = rearPlane.
ToVec4() * lv;
270 mat[0][0] = lg -rearPlane[0] * lv[0];
271 mat[0][1] = -rearPlane[1] * lv[0];
272 mat[0][2] = -rearPlane[2] * lv[0];
273 mat[0][3] = -rearPlane[3] * lv[0];
275 mat[1][0] = -rearPlane[0] * lv[1];
276 mat[1][1] = lg -rearPlane[1] * lv[1];
277 mat[1][2] = -rearPlane[2] * lv[1];
278 mat[1][3] = -rearPlane[3] * lv[1];
280 mat[2][0] = -rearPlane[0] * lv[2];
281 mat[2][1] = -rearPlane[1] * lv[2];
282 mat[2][2] = lg -rearPlane[2] * lv[2];
283 mat[2][3] = -rearPlane[3] * lv[2];
285 mat[3][0] = -rearPlane[0] * lv[3];
286 mat[3][1] = -rearPlane[1] * lv[3];
287 mat[3][2] = -rearPlane[2] * lv[3];
288 mat[3][3] = lg -rearPlane[3] * lv[3];
300 const idPlane &lightPlaneLocal,
301 int firstShadowVert,
int numShadowVerts ) {
312 in = &shadowVerts[firstShadowVert];
313 for ( i = firstShadowVert ; i < numShadowVerts ; i+= 2, in += 2 ) {
325 in[1].
x = ( in->
ToVec3() * mat[0].
ToVec3() + mat[0][3] ) * oow;
326 in[1].
y = ( in->
ToVec3() * mat[1].
ToVec3() + mat[1][3] ) * oow;
327 in[1].
z = ( in->
ToVec3() * mat[2].
ToVec3() + mat[2][3] ) * oow;
335 in = &shadowVerts[firstShadowVert];
336 for ( i = firstShadowVert ; i < numShadowVerts ; i+= 2, in += 2 ) {
338 in[1].
x = *in * mat[0].
ToVec3() + mat[0][3];
339 in[1].
y = *in * mat[1].
ToVec3() + mat[1][3];
340 in[1].
z = *in * mat[2].
ToVec3() + mat[2][3];
341 in[1].
w = *in * mat[3].
ToVec3() + mat[3][3];
348 #define MAX_CLIPPED_POINTS 20
367 static int R_ChopWinding(
clipTri_t clipTris[2],
int inNum,
const idPlane &plane ) {
377 in = &clipTris[inNum];
378 out = &clipTris[inNum^1];
379 counts[0] = counts[1] = counts[2] = 0;
382 for ( i = 0 ; i < in->
numVerts ; i++ ) {
411 for ( i = 0 ; i < in->
numVerts ; i++ ) {
414 if ( sides[i] != SIDE_BACK ) {
416 if ( sides[i] ==
SIDE_ON && sides[i+1] == SIDE_BACK ) {
424 if ( (sides[i] == SIDE_FRONT && sides[i+1] == SIDE_BACK)
425 || (sides[i] == SIDE_BACK && sides[i+1] == SIDE_FRONT) ) {
427 p2 = &in->
verts[i+1];
429 dot = dists[
i] / (dists[
i]-dists[i+1]);
430 for ( j=0 ; j<3 ; j++ ) {
431 mid[
j] = (*p1)[
j] + dot*((*p2)[
j]-(*p1)[
j]);
437 if ( sides[i+1] != SIDE_FRONT ) {
473 for ( i = 0 ; i < 6 ; i++ ) {
474 if ( planeBits & ( 1 << i ) ) {
475 p = R_ChopWinding( pingPong, p, frustum[i] );
476 if ( pingPong[p].numVerts < 1 ) {
489 base = numShadowVerts;
490 for ( i = 0 ; i < ct->
numVerts ; i++ ) {
500 for ( i = 2 ; i < ct->
numVerts ; i++ ) {
501 shadowIndexes[numShadowIndexes++] = base + i * 2;
502 shadowIndexes[numShadowIndexes++] = base + ( i - 1 ) * 2;
503 shadowIndexes[numShadowIndexes++] = base;
509 for ( i = 0 ; i < ct->
numVerts ; i++ ) {
514 clipSilEdges[ numClipSilEdges ][0] = base + i * 2;
516 clipSilEdges[ numClipSilEdges ][1] = base;
518 clipSilEdges[ numClipSilEdges ][1] = base + ( i + 1 ) * 2;
550 for ( j = 0 ; j < 6 ; j++ ) {
580 f = d1 / ( d1 - d2 );
581 clip[0] = p1[0] + f * ( p2[0] - p1[0] );
582 clip[1] = p1[1] + f * ( p2[1] - p1[1] );
583 clip[2] = p1[2] + f * ( p2[2] - p1[2] );
600 static void R_AddClipSilEdges(
void ) {
602 int v1_back, v2_back;
611 for ( i = 0 ; i < numClipSilEdges ; i++ ) {
612 v1 = clipSilEdges[
i][0];
613 v2 = clipSilEdges[
i][1];
616 if ( PointsOrdered( shadowVerts[ v1 ].ToVec3(), shadowVerts[ v2 ].ToVec3() ) ) {
617 shadowIndexes[numShadowIndexes++] =
v1;
618 shadowIndexes[numShadowIndexes++] =
v2;
619 shadowIndexes[numShadowIndexes++] = v1_back;
620 shadowIndexes[numShadowIndexes++] =
v2;
621 shadowIndexes[numShadowIndexes++] = v2_back;
622 shadowIndexes[numShadowIndexes++] = v1_back;
624 shadowIndexes[numShadowIndexes++] =
v1;
625 shadowIndexes[numShadowIndexes++] =
v2;
626 shadowIndexes[numShadowIndexes++] = v2_back;
627 shadowIndexes[numShadowIndexes++] =
v1;
628 shadowIndexes[numShadowIndexes++] = v2_back;
629 shadowIndexes[numShadowIndexes++] = v1_back;
642 static void R_AddSilEdges(
const srfTriangles_t *tri,
unsigned short *pointCull,
const idPlane frustum[6] ) {
653 if ( sil->
p1 < 0 || sil->
p1 > numPlanes || sil->
p2 < 0 || sil->
p2 > numPlanes ) {
663 if ( !( faceCastsShadow[ sil->
p1 ] ^ faceCastsShadow[ sil->
p2 ] ) ) {
691 v1 = remap[ sil->
v1 ];
692 v2 = remap[ sil->
v2 ];
693 if ( v1 < 0 || v2 < 0 ) {
708 if ( faceCastsShadow[ sil->
p2 ] ) {
709 if ( PointsOrdered( shadowVerts[ v1 ].ToVec3(), shadowVerts[ v2 ].ToVec3() ) ) {
710 shadowIndexes[numShadowIndexes++] =
v1;
711 shadowIndexes[numShadowIndexes++] = v1+1;
712 shadowIndexes[numShadowIndexes++] =
v2;
713 shadowIndexes[numShadowIndexes++] =
v2;
714 shadowIndexes[numShadowIndexes++] = v1+1;
715 shadowIndexes[numShadowIndexes++] = v2+1;
717 shadowIndexes[numShadowIndexes++] =
v1;
718 shadowIndexes[numShadowIndexes++] = v2+1;
719 shadowIndexes[numShadowIndexes++] =
v2;
720 shadowIndexes[numShadowIndexes++] =
v1;
721 shadowIndexes[numShadowIndexes++] = v1+1;
722 shadowIndexes[numShadowIndexes++] = v2+1;
725 if ( PointsOrdered( shadowVerts[ v1 ].ToVec3(), shadowVerts[ v2 ].ToVec3() ) ) {
726 shadowIndexes[numShadowIndexes++] =
v1;
727 shadowIndexes[numShadowIndexes++] =
v2;
728 shadowIndexes[numShadowIndexes++] = v1+1;
729 shadowIndexes[numShadowIndexes++] =
v2;
730 shadowIndexes[numShadowIndexes++] = v2+1;
731 shadowIndexes[numShadowIndexes++] = v1+1;
733 shadowIndexes[numShadowIndexes++] =
v1;
734 shadowIndexes[numShadowIndexes++] =
v2;
735 shadowIndexes[numShadowIndexes++] = v2+1;
736 shadowIndexes[numShadowIndexes++] =
v1;
737 shadowIndexes[numShadowIndexes++] = v2+1;
738 shadowIndexes[numShadowIndexes++] = v1+1;
751 static void R_CalcPointCull(
const srfTriangles_t *tri,
const idPlane frustum[6],
unsigned short *pointCull ) {
759 for ( frontBits = 0, i = 0; i < 6; i++ ) {
762 frontBits |= 1<<(i+6);
767 for ( i = 0; i < tri->
numVerts; i++ ) {
768 pointCull[
i] = frontBits;
772 if ( frontBits == ( ( ( 1 << 6 ) - 1 ) ) << 6 ) {
776 planeSide = (
float *) _alloca16( tri->
numVerts *
sizeof(
float ) );
782 for ( i = 0; i < 6; i++ ) {
784 if ( frontBits & (1<<(i+6)) ) {
792 for ( i = 0; i < tri->
numVerts; i++ ) {
793 pointCull[
i] |= side1[
i] | (side2[
i] << 6);
817 bool makeClippedPlanes ) {
820 unsigned short *pointCull;
822 int firstShadowIndex;
826 pointCull = (
unsigned short *)_alloca16( tri->
numVerts *
sizeof( pointCull[0] ) );
830 R_CalcPointCull( tri, frustum, pointCull );
833 firstShadowIndex = numShadowIndexes;
834 firstShadowVert = numShadowVerts;
839 for ( i = 0 ; i < numTris ; i++ ) {
842 faceCastsShadow[
i] = 0;
846 if ( globalFacing[i] ) {
871 remap[
i1] = numShadowVerts;
876 remap[
i2] = numShadowVerts;
881 remap[i3] = numShadowVerts;
888 cullBits = ( ( pointCull[
i1 ] ^ 0xfc0 ) | ( pointCull[ i2 ] ^ 0xfc0 ) | ( pointCull[ i3 ] ^ 0xfc0 ) ) >> 6;
892 tri->
verts[i3].
xyz, cullBits, frustum ) ) {
893 faceCastsShadow[
i] = 1;
901 if ( remap[i1] == -1 || remap[i2] == -1 || remap[i3] == -1 ) {
902 common->
Error(
"R_CreateShadowVolumeInFrustum: bad remap[]" );
904 shadowIndexes[numShadowIndexes++] = remap[i3];
905 shadowIndexes[numShadowIndexes++] = remap[
i2];
906 shadowIndexes[numShadowIndexes++] = remap[
i1];
907 faceCastsShadow[
i] = 1;
913 numCapIndexes = numShadowIndexes - firstShadowIndex;
917 if ( numCapIndexes == 0 ) {
925 if ( callOptimizer ) {
932 opt =
SuperOptimizeOccluders( shadowVerts, shadowIndexes + firstShadowIndex, numCapIndexes, farPlane, lightOrigin );
935 numShadowIndexes = firstShadowIndex;
936 numShadowVerts = firstShadowVert;
942 common->
Printf(
"WARNING: overflowed MAX_SHADOW tables, shadow discarded\n" );
948 for ( i = 0 ; i < opt.
numVerts ; i++ ) {
949 shadowVerts[numShadowVerts+
i][0] = opt.
verts[
i][0];
950 shadowVerts[numShadowVerts+
i][1] = opt.
verts[
i][1];
951 shadowVerts[numShadowVerts+
i][2] = opt.
verts[
i][2];
952 shadowVerts[numShadowVerts+
i][3] = 1;
957 common->
Error(
"optimized shadow index out of range" );
959 shadowIndexes[numShadowIndexes+
i] = index + numShadowVerts;
966 indexRef[indexFrustumNumber].
frontCapStart = firstShadowIndex;
969 indexRef[indexFrustumNumber].
end = numShadowIndexes;
970 indexFrustumNumber++;
982 faceCastsShadow[numTris] = 0;
990 for ( i = 0 ; i < numCapIndexes ; i += 3 ) {
991 shadowIndexes[ numShadowIndexes + i + 0 ] = shadowIndexes[ firstShadowIndex + i + 2 ] + 1;
992 shadowIndexes[ numShadowIndexes + i + 1 ] = shadowIndexes[ firstShadowIndex + i + 1 ] + 1;
993 shadowIndexes[ numShadowIndexes + i + 2 ] = shadowIndexes[ firstShadowIndex + i + 0 ] + 1;
995 numShadowIndexes += numCapIndexes;
997 c_caps += numCapIndexes * 2;
999 int preSilIndexes = numShadowIndexes;
1003 if ( makeClippedPlanes ) {
1004 R_AddClipSilEdges();
1009 R_AddSilEdges( tri, pointCull, frustum );
1011 c_sils += numShadowIndexes - preSilIndexes;
1015 R_ProjectPointsToFarPlane( ent, light, farPlane, firstShadowVert, numShadowVerts );
1018 indexRef[indexFrustumNumber].
frontCapStart = firstShadowIndex;
1019 indexRef[indexFrustumNumber].
rearCapStart = firstShadowIndex+numCapIndexes;
1020 indexRef[indexFrustumNumber].
silStart = preSilIndexes;
1021 indexRef[indexFrustumNumber].
end = numShadowIndexes;
1022 indexFrustumNumber++;
1048 for ( i = 0 ; i < 6 ; i++ ) {
1053 for ( j = 0 ; j < 6 ; j++ ) {
1055 plane[0] = pointLightFrustums[
i][
j][0] / adjustedRadius[0];
1056 plane[1] = pointLightFrustums[
i][
j][1] / adjustedRadius[1];
1057 plane[2] = pointLightFrustums[
i][
j][2] / adjustedRadius[2];
1061 plane[3] += adjustedRadius[i>>1];
1071 static int faceCorners[6][4] = {
1079 static int faceEdgeAdjacent[6][4] = {
1088 bool centerOutside =
false;
1095 centerOutside =
true;
1101 for ( i = 0 ; i < 8 ; i++ ) {
1103 for ( j = 0 ; j < 3 ; j++ ) {
1104 if ( i & ( 1 << j ) ) {
1116 for (
int side = 0 ; side < 6 ; side++ ) {
1118 idVec3 &p1 = corners[faceCorners[side][0]];
1119 idVec3 &p2 = corners[faceCorners[side][1]];
1120 idVec3 &p3 = corners[faceCorners[side][2]];
1133 frust->
planes[5] = backPlane;
1134 frust->
planes[4] = backPlane;
1138 idVec3 &p1 = corners[faceCorners[side][
edge]];
1139 idVec3 &p2 = corners[faceCorners[side][(
edge+1)&3]];
1145 if ( centerOutside ) {
1146 idVec3 &p3 = corners[faceEdgeAdjacent[side][
edge]];
1177 for ( i = 0 ; i < 6 ; i++ ) {
1258 for ( i = 0; i < numFaces && allFront; i++ ) {
1259 allFront &= cullInfo.
facing[
i];
1267 numShadowIndexes = 0;
1270 indexFrustumNumber = 0;
1276 globalFacing = cullInfo.
facing;
1278 remap = (
int *)_alloca16( tri->
numVerts *
sizeof( remap[0] ) );
1285 for (
int frustumNum = 0 ; frustumNum < light->
numShadowFrustums ; frustumNum++ ) {
1287 ALIGN16(
idPlane frustum[6] );
1296 for ( j = 0 ; j < frust->
numPlanes ; j++ ) {
1309 int oldFrustumNumber = indexFrustumNumber;
1311 R_CreateShadowVolumeInFrustum( ent, tri, light, lightOrigin, frustum, frustum[5], frust->
makeClippedPlanes );
1319 if ( indexFrustumNumber != oldFrustumNumber ) {
1323 capPlaneBits |= 1<<frustumNum;
1329 if ( numShadowIndexes == 0 ) {
1362 for ( i = 0 ; i < indexFrustumNumber ; i++ ) {
1365 shadowIndexes+indexRef[i].
silStart, c *
sizeof( newTri->
indexes[0] ) );
1370 for ( i = 0 ; i < indexFrustumNumber ; i++ ) {
1378 for ( i = 0 ; i < indexFrustumNumber ; i++ ) {
int numShadowIndexesNoFrontCaps
idPlane pointLightFrustums[6][6]
void CleanupOptimizedShadowTris(srfTriangles_t *tri)
bool FromPoints(const idVec3 &p1, const idVec3 &p2, const idVec3 &p3, bool fixDegenerate=true)
const idVec3 & Normal(void) const
#define MAX_CLIP_SIL_EDGES
void R_CalcInteractionFacing(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
idCVar r_useShadowVertexProgram("r_useShadowVertexProgram","1", CVAR_RENDERER|CVAR_BOOL,"do the shadow projection in the vertex program on capable cards")
const float * ToFloatPtr(void) const
float Distance(const idVec3 &v) const
#define MAX_CLIPPED_POINTS
srfTriangles_t * R_CreateVertexProgramTurboShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
const idVec4 & ToVec4(void) const
idCVar r_shadows("r_shadows","1", CVAR_RENDERER|CVAR_BOOL|CVAR_ARCHIVE,"enable shadows")
srfTriangles_t * R_AllocStaticTriSurf(void)
virtual void VPCALL Memset(void *dst, const int val, const int count)=0
void SetNormal(const idVec3 &normal)
#define TRIANGLE_CULLED(p1, p2, p3)
shadowFrustum_t shadowFrustums[6]
int edgeFlags[MAX_CLIPPED_POINTS]
idVec3 verts[MAX_CLIPPED_POINTS]
GLfloat GLfloat GLfloat v2
bool backEndRendererHasVertexPrograms
virtual void VPCALL CmpLT(byte *dst, const float *src0, const float constant, const int count)=0
GLubyte GLubyte GLubyte GLubyte w
void SetDist(const float dist)
#define EDGE_CULLED(p1, p2)
static float Fabs(float f)
void R_MakeShadowFrustums(idRenderLightLocal *light)
float PlaneDistance(const idPlane &plane) const
#define EDGE_CLIPPED(p1, p2)
virtual void virtual void FatalError(const char *fmt,...) id_attribute((format(printf
void R_LightProjectionMatrix(const idVec3 &origin, const idPlane &rearPlane, idVec4 mat[4])
virtual void VPCALL Dot(float *dst, const idVec3 &constant, const idVec3 *src, const int count)=0
void R_AllocStaticTriSurfShadowVerts(srfTriangles_t *tri, int numVerts)
shadowCache_t * shadowVertexes
GLubyte GLubyte GLubyte a
virtual void Printf(const char *fmt,...) id_attribute((format(printf
float Normalize(bool fixDegenerate=true)
#define MAX_SHADOW_INDEXES
virtual void VPCALL Memcpy(void *dst, const void *src, const int count)=0
int numShadowIndexesNoCaps
idCVar r_useTurboShadow("r_useTurboShadow","1", CVAR_RENDERER|CVAR_BOOL,"use the infinite projection with W technique for dynamic shadows")
void R_GlobalPointToLocal(const float modelMatrix[16], const idVec3 &in, idVec3 &out)
#define TRIANGLE_CLIPPED(p1, p2, p3)
srfTriangles_t * R_CreateTurboShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
optimizedShadow_t SuperOptimizeOccluders(idVec4 *verts, glIndex_t *indexes, int numIndexes, idPlane projectionPlane, idVec3 projectionOrigin)
const idVec3 & ToVec3(void) const
virtual void VPCALL CmpGT(byte *dst, const float *src0, const float constant, const int count)=0
void R_AllocStaticTriSurfIndexes(srfTriangles_t *tri, int numIndexes)
float dot(float a[], float b[])
#define LIGHT_CLIP_EPSILON
virtual void Error(const char *fmt,...) id_attribute((format(printf
srfTriangles_t * R_CreateShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, shadowGen_t optimize, srfCullInfo_t &cullInfo)
void R_GlobalPlaneToLocal(const float modelMatrix[16], const idPlane &in, idPlane &out)
idSIMDProcessor * SIMDProcessor