mirror of
https://github.com/TTimo/doom3.gpl.git
synced 2026-03-19 16:39:24 +01:00
hello world
This commit is contained in:
356
neo/renderer/tr_turboshadow.cpp
Normal file
356
neo/renderer/tr_turboshadow.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user