/* ================== R_AddClipSilEdges Add sil edges for each triangle clipped to the side of the frustum. Only done for simple projected lights, not point lights. ================== */ static void R_AddClipSilEdges( void ) { int v1, v2; int v1_back, v2_back; int i; // don't allow it to overflow if ( numShadowIndexes + numClipSilEdges * 6 > MAX_SHADOW_INDEXES ) { overflowed = true; return; } for ( i = 0 ; i < numClipSilEdges ; i++ ) { v1 = clipSilEdges[i][0]; v2 = clipSilEdges[i][1]; v1_back = v1 + 1; v2_back = v2 + 1; if ( PointsOrdered( shadowVerts[ v1 ].ToVec3(), shadowVerts[ v2 ].ToVec3() ) ) { shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v1_back; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v2_back; shadowIndexes[numShadowIndexes++] = v1_back; } else { shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v2_back; shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2_back; shadowIndexes[numShadowIndexes++] = v1_back; } } }
/* ================== R_AddClipSilEdges Add sil edges for each triangle clipped to the side of the frustum. Only done for simple projected lights, not point lights. ================== */ static void R_AddClipSilEdges(stencilRef_t *st) { int v1, v2; int v1_back, v2_back; int i; // don't allow it to overflow if (st->numShadowIndexes + st->numClipSilEdges * 6 > MAX_SHADOW_INDEXES) { st->overflowed = true; return; } for (i = 0; i < st->numClipSilEdges; i++) { v1 = st->clipSilEdges[i][0]; v2 = st->clipSilEdges[i][1]; v1_back = v1 + 1; v2_back = v2 + 1; if (PointsOrdered(st->shadowVerts[v1].ToVec3(), st->shadowVerts[v2].ToVec3())) { st->shadowIndexes[st->numShadowIndexes++] = v1; st->shadowIndexes[st->numShadowIndexes++] = v2; st->shadowIndexes[st->numShadowIndexes++] = v1_back; st->shadowIndexes[st->numShadowIndexes++] = v2; st->shadowIndexes[st->numShadowIndexes++] = v2_back; st->shadowIndexes[st->numShadowIndexes++] = v1_back; } else { st->shadowIndexes[st->numShadowIndexes++] = v1; st->shadowIndexes[st->numShadowIndexes++] = v2; st->shadowIndexes[st->numShadowIndexes++] = v2_back; st->shadowIndexes[st->numShadowIndexes++] = v1; st->shadowIndexes[st->numShadowIndexes++] = v2_back; st->shadowIndexes[st->numShadowIndexes++] = v1_back; } } }
/* ================= R_AddSilEdges Add quads from the front points to the projected points for each silhouette edge in the light ================= */ static void R_AddSilEdges( const srfTriangles_t *tri, unsigned short *pointCull, const idPlane frustum[6] ) { int v1, v2; int i; silEdge_t *sil; int numPlanes; numPlanes = tri->numIndexes / 3; // add sil edges for any true silhouette boundaries on the surface for ( i = 0 ; i < tri->numSilEdges ; i++ ) { sil = tri->silEdges + i; if ( sil->p1 < 0 || sil->p1 > numPlanes || sil->p2 < 0 || sil->p2 > numPlanes ) { common->Error( "Bad sil planes" ); } // an edge will be a silhouette edge if the face on one side // casts a shadow, but the face on the other side doesn't. // "casts a shadow" means that it has some surface in the projection, // not just that it has the correct facing direction // This will cause edges that are exactly on the frustum plane // to be considered sil edges if the face inside casts a shadow. if ( !( faceCastsShadow[ sil->p1 ] ^ faceCastsShadow[ sil->p2 ] ) ) { continue; } // if the edge is completely off the negative side of // a frustum plane, don't add it at all. This can still // happen even if the face is visible and casting a shadow // if it is partially clipped if ( EDGE_CULLED( sil->v1, sil->v2 ) ) { continue; } // see if the edge needs to be clipped if ( EDGE_CLIPPED( sil->v1, sil->v2 ) ) { if ( numShadowVerts + 4 > MAX_SHADOW_VERTS ) { overflowed = true; return; } v1 = numShadowVerts; v2 = v1 + 2; if ( !R_ClipLineToLight( tri->verts[ sil->v1 ].xyz, tri->verts[ sil->v2 ].xyz, frustum, shadowVerts[v1].ToVec3(), shadowVerts[v2].ToVec3() ) ) { continue; // clipped away } numShadowVerts += 4; } else { // use the entire edge v1 = remap[ sil->v1 ]; v2 = remap[ sil->v2 ]; if ( v1 < 0 || v2 < 0 ) { common->Error( "R_AddSilEdges: bad remap[]" ); } } // don't overflow if ( numShadowIndexes + 6 > MAX_SHADOW_INDEXES ) { overflowed = true; return; } // we need to choose the correct way of triangulating the silhouette quad // consistantly between any two points, no matter which order they are specified. // If this wasn't done, slight rasterization cracks would show in the shadow // volume when two sil edges were exactly coincident if ( faceCastsShadow[ sil->p2 ] ) { if ( PointsOrdered( shadowVerts[ v1 ].ToVec3(), shadowVerts[ v2 ].ToVec3() ) ) { shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v1+1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v1+1; shadowIndexes[numShadowIndexes++] = v2+1; } else { shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2 + 1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v1 + 1; shadowIndexes[numShadowIndexes++] = v2 + 1; } } else { if ( PointsOrdered( shadowVerts[ v1 ].ToVec3(), shadowVerts[ v2 ].ToVec3() ) ) { shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v1+1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v2+1; shadowIndexes[numShadowIndexes++] = v1+1; } else { shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2; shadowIndexes[numShadowIndexes++] = v2+1; shadowIndexes[numShadowIndexes++] = v1; shadowIndexes[numShadowIndexes++] = v2+1; shadowIndexes[numShadowIndexes++] = v1+1; } } } }