123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "tr_local.h"
- int c_turboUsedVerts;
- int c_turboUnusedVerts;
- /*
- =====================
- R_CreateVertexProgramTurboShadowVolume
- are dangling edges that are outside the light frustum still making planes?
- =====================
- */
- srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent,
- const srfTriangles_t *tri, const idRenderLightLocal *light,
- srfCullInfo_t &cullInfo ) {
- int i, j;
- srfTriangles_t *newTri;
- silEdge_t *sil;
- const glIndex_t *indexes;
- const byte *facing;
- R_CalcInteractionFacing( ent, tri, light, cullInfo );
- if ( r_useShadowProjectedCull.GetBool() ) {
- R_CalcInteractionCullBits( ent, tri, light, cullInfo );
- }
- int numFaces = tri->numIndexes / 3;
- int numShadowingFaces = 0;
- facing = cullInfo.facing;
- // if all the triangles are inside the light frustum
- if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
- // count the number of shadowing faces
- for ( i = 0; i < numFaces; i++ ) {
- numShadowingFaces += facing[i];
- }
- numShadowingFaces = numFaces - numShadowingFaces;
- } else {
- // make all triangles that are outside the light frustum "facing", so they won't cast shadows
- indexes = tri->indexes;
- byte *modifyFacing = cullInfo.facing;
- const byte *cullBits = cullInfo.cullBits;
- for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
- if ( !modifyFacing[j] ) {
- int i1 = indexes[i+0];
- int i2 = indexes[i+1];
- int i3 = indexes[i+2];
- if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
- modifyFacing[j] = 1;
- } else {
- numShadowingFaces++;
- }
- }
- }
- }
- if ( !numShadowingFaces ) {
- // no faces are inside the light frustum and still facing the right way
- return NULL;
- }
- // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
- newTri = R_AllocStaticTriSurf();
- newTri->numVerts = tri->numVerts * 2;
- // alloc the max possible size
- #ifdef USE_TRI_DATA_ALLOCATOR
- R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
- glIndex_t *tempIndexes = newTri->indexes;
- glIndex_t *shadowIndexes = newTri->indexes;
- #else
- glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
- glIndex_t *shadowIndexes = tempIndexes;
- #endif
- // create new triangles along sil planes
- for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
- int f1 = facing[sil->p1];
- int f2 = facing[sil->p2];
- if ( !( f1 ^ f2 ) ) {
- continue;
- }
- int v1 = sil->v1 << 1;
- int v2 = sil->v2 << 1;
- // set the two triangle winding orders based on facing
- // without using a poorly-predictable branch
- shadowIndexes[0] = v1;
- shadowIndexes[1] = v2 ^ f1;
- shadowIndexes[2] = v2 ^ f2;
- shadowIndexes[3] = v1 ^ f2;
- shadowIndexes[4] = v1 ^ f1;
- shadowIndexes[5] = v2 ^ 1;
- shadowIndexes += 6;
- }
- int numShadowIndexes = shadowIndexes - tempIndexes;
- // we aren't bothering to separate front and back caps on these
- newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
- newTri->numShadowIndexesNoCaps = numShadowIndexes;
- newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
- #ifdef USE_TRI_DATA_ALLOCATOR
- // decrease the size of the memory block to only store the used indexes
- R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
- #else
- // allocate memory for the indexes
- R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
- // copy the indexes we created for the sil planes
- SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
- #endif
- // these have no effect, because they extend to infinity
- newTri->bounds.Clear();
- // put some faces on the model and some on the distant projection
- indexes = tri->indexes;
- shadowIndexes = newTri->indexes + numShadowIndexes;
- for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
- if ( facing[j] ) {
- continue;
- }
- int i0 = indexes[i+0] << 1;
- shadowIndexes[2] = i0;
- shadowIndexes[3] = i0 ^ 1;
- int i1 = indexes[i+1] << 1;
- shadowIndexes[1] = i1;
- shadowIndexes[4] = i1 ^ 1;
- int i2 = indexes[i+2] << 1;
- shadowIndexes[0] = i2;
- shadowIndexes[5] = i2 ^ 1;
- shadowIndexes += 6;
- }
- return newTri;
- }
- /*
- =====================
- R_CreateTurboShadowVolume
- =====================
- */
- srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
- const srfTriangles_t *tri, const idRenderLightLocal *light,
- srfCullInfo_t &cullInfo ) {
- int i, j;
- idVec3 localLightOrigin;
- srfTriangles_t *newTri;
- silEdge_t *sil;
- const glIndex_t *indexes;
- const byte *facing;
- R_CalcInteractionFacing( ent, tri, light, cullInfo );
- if ( r_useShadowProjectedCull.GetBool() ) {
- R_CalcInteractionCullBits( ent, tri, light, cullInfo );
- }
- int numFaces = tri->numIndexes / 3;
- int numShadowingFaces = 0;
- facing = cullInfo.facing;
- // if all the triangles are inside the light frustum
- if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
- // count the number of shadowing faces
- for ( i = 0; i < numFaces; i++ ) {
- numShadowingFaces += facing[i];
- }
- numShadowingFaces = numFaces - numShadowingFaces;
- } else {
- // make all triangles that are outside the light frustum "facing", so they won't cast shadows
- indexes = tri->indexes;
- byte *modifyFacing = cullInfo.facing;
- const byte *cullBits = cullInfo.cullBits;
- for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
- if ( !modifyFacing[j] ) {
- int i1 = indexes[i+0];
- int i2 = indexes[i+1];
- int i3 = indexes[i+2];
- if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
- modifyFacing[j] = 1;
- } else {
- numShadowingFaces++;
- }
- }
- }
- }
- if ( !numShadowingFaces ) {
- // no faces are inside the light frustum and still facing the right way
- return NULL;
- }
- newTri = R_AllocStaticTriSurf();
- #ifdef USE_TRI_DATA_ALLOCATOR
- R_AllocStaticTriSurfShadowVerts( newTri, tri->numVerts * 2 );
- shadowCache_t *shadowVerts = newTri->shadowVertexes;
- #else
- shadowCache_t *shadowVerts = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowVerts[0] ) );
- #endif
- R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
- int *vertRemap = (int *)_alloca16( tri->numVerts * sizeof( vertRemap[0] ) );
- SIMDProcessor->Memset( vertRemap, -1, tri->numVerts * sizeof( vertRemap[0] ) );
- for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
- if ( facing[j] ) {
- continue;
- }
- // this may pull in some vertexes that are outside
- // the frustum, because they connect to vertexes inside
- vertRemap[tri->silIndexes[i+0]] = 0;
- vertRemap[tri->silIndexes[i+1]] = 0;
- vertRemap[tri->silIndexes[i+2]] = 0;
- }
- newTri->numVerts = SIMDProcessor->CreateShadowCache( &shadowVerts->xyz, vertRemap, localLightOrigin, tri->verts, tri->numVerts );
- c_turboUsedVerts += newTri->numVerts;
- c_turboUnusedVerts += tri->numVerts * 2 - newTri->numVerts;
- #ifdef USE_TRI_DATA_ALLOCATOR
- R_ResizeStaticTriSurfShadowVerts( newTri, newTri->numVerts );
- #else
- R_AllocStaticTriSurfShadowVerts( newTri, newTri->numVerts );
- SIMDProcessor->Memcpy( newTri->shadowVertexes, shadowVerts, newTri->numVerts * sizeof( shadowVerts[0] ) );
- #endif
- // alloc the max possible size
- #ifdef USE_TRI_DATA_ALLOCATOR
- R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
- glIndex_t *tempIndexes = newTri->indexes;
- glIndex_t *shadowIndexes = newTri->indexes;
- #else
- glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
- glIndex_t *shadowIndexes = tempIndexes;
- #endif
- // create new triangles along sil planes
- for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
- int f1 = facing[sil->p1];
- int f2 = facing[sil->p2];
- if ( !( f1 ^ f2 ) ) {
- continue;
- }
- int v1 = vertRemap[sil->v1];
- int v2 = vertRemap[sil->v2];
- // set the two triangle winding orders based on facing
- // without using a poorly-predictable branch
- shadowIndexes[0] = v1;
- shadowIndexes[1] = v2 ^ f1;
- shadowIndexes[2] = v2 ^ f2;
- shadowIndexes[3] = v1 ^ f2;
- shadowIndexes[4] = v1 ^ f1;
- shadowIndexes[5] = v2 ^ 1;
- shadowIndexes += 6;
- }
- int numShadowIndexes = shadowIndexes - tempIndexes;
- // we aren't bothering to separate front and back caps on these
- newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
- newTri->numShadowIndexesNoCaps = numShadowIndexes;
- newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
- #ifdef USE_TRI_DATA_ALLOCATOR
- // decrease the size of the memory block to only store the used indexes
- R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
- #else
- // allocate memory for the indexes
- R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
- // copy the indexes we created for the sil planes
- SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
- #endif
- // these have no effect, because they extend to infinity
- newTri->bounds.Clear();
- // put some faces on the model and some on the distant projection
- indexes = tri->silIndexes;
- shadowIndexes = newTri->indexes + numShadowIndexes;
- for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
- if ( facing[j] ) {
- continue;
- }
- int i0 = vertRemap[indexes[i+0]];
- shadowIndexes[2] = i0;
- shadowIndexes[3] = i0 ^ 1;
- int i1 = vertRemap[indexes[i+1]];
- shadowIndexes[1] = i1;
- shadowIndexes[4] = i1 ^ 1;
- int i2 = vertRemap[indexes[i+2]];
- shadowIndexes[0] = i2;
- shadowIndexes[5] = i2 ^ 1;
- shadowIndexes += 6;
- }
- return newTri;
- }
|