2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 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.
24 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.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
35 int c_turboUnusedVerts;
40 R_CreateVertexProgramTurboShadowVolume
42 are dangling edges that are outside the light frustum still making planes?
45 srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent,
46 const srfTriangles_t *tri, const idRenderLightLocal *light,
47 srfCullInfo_t &cullInfo ) {
49 srfTriangles_t *newTri;
51 const glIndex_t *indexes;
54 R_CalcInteractionFacing( ent, tri, light, cullInfo );
55 if ( r_useShadowProjectedCull.GetBool() ) {
56 R_CalcInteractionCullBits( ent, tri, light, cullInfo );
59 int numFaces = tri->numIndexes / 3;
60 int numShadowingFaces = 0;
61 facing = cullInfo.facing;
63 // if all the triangles are inside the light frustum
64 if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
66 // count the number of shadowing faces
67 for ( i = 0; i < numFaces; i++ ) {
68 numShadowingFaces += facing[i];
70 numShadowingFaces = numFaces - numShadowingFaces;
74 // make all triangles that are outside the light frustum "facing", so they won't cast shadows
75 indexes = tri->indexes;
76 byte *modifyFacing = cullInfo.facing;
77 const byte *cullBits = cullInfo.cullBits;
78 for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
79 if ( !modifyFacing[j] ) {
80 int i1 = indexes[i+0];
81 int i2 = indexes[i+1];
82 int i3 = indexes[i+2];
83 if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
92 if ( !numShadowingFaces ) {
93 // no faces are inside the light frustum and still facing the right way
97 // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
98 newTri = R_AllocStaticTriSurf();
100 newTri->numVerts = tri->numVerts * 2;
102 // alloc the max possible size
103 #ifdef USE_TRI_DATA_ALLOCATOR
104 R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
105 glIndex_t *tempIndexes = newTri->indexes;
106 glIndex_t *shadowIndexes = newTri->indexes;
108 glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
109 glIndex_t *shadowIndexes = tempIndexes;
112 // create new triangles along sil planes
113 for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
115 int f1 = facing[sil->p1];
116 int f2 = facing[sil->p2];
118 if ( !( f1 ^ f2 ) ) {
122 int v1 = sil->v1 << 1;
123 int v2 = sil->v2 << 1;
125 // set the two triangle winding orders based on facing
126 // without using a poorly-predictable branch
128 shadowIndexes[0] = v1;
129 shadowIndexes[1] = v2 ^ f1;
130 shadowIndexes[2] = v2 ^ f2;
131 shadowIndexes[3] = v1 ^ f2;
132 shadowIndexes[4] = v1 ^ f1;
133 shadowIndexes[5] = v2 ^ 1;
138 int numShadowIndexes = shadowIndexes - tempIndexes;
140 // we aren't bothering to separate front and back caps on these
141 newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
142 newTri->numShadowIndexesNoCaps = numShadowIndexes;
143 newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
145 #ifdef USE_TRI_DATA_ALLOCATOR
146 // decrease the size of the memory block to only store the used indexes
147 R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
149 // allocate memory for the indexes
150 R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
151 // copy the indexes we created for the sil planes
152 SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
155 // these have no effect, because they extend to infinity
156 newTri->bounds.Clear();
158 // put some faces on the model and some on the distant projection
159 indexes = tri->indexes;
160 shadowIndexes = newTri->indexes + numShadowIndexes;
161 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
166 int i0 = indexes[i+0] << 1;
167 shadowIndexes[2] = i0;
168 shadowIndexes[3] = i0 ^ 1;
169 int i1 = indexes[i+1] << 1;
170 shadowIndexes[1] = i1;
171 shadowIndexes[4] = i1 ^ 1;
172 int i2 = indexes[i+2] << 1;
173 shadowIndexes[0] = i2;
174 shadowIndexes[5] = i2 ^ 1;
183 =====================
184 R_CreateTurboShadowVolume
185 =====================
187 srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
188 const srfTriangles_t *tri, const idRenderLightLocal *light,
189 srfCullInfo_t &cullInfo ) {
191 idVec3 localLightOrigin;
192 srfTriangles_t *newTri;
194 const glIndex_t *indexes;
197 R_CalcInteractionFacing( ent, tri, light, cullInfo );
198 if ( r_useShadowProjectedCull.GetBool() ) {
199 R_CalcInteractionCullBits( ent, tri, light, cullInfo );
202 int numFaces = tri->numIndexes / 3;
203 int numShadowingFaces = 0;
204 facing = cullInfo.facing;
206 // if all the triangles are inside the light frustum
207 if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
209 // count the number of shadowing faces
210 for ( i = 0; i < numFaces; i++ ) {
211 numShadowingFaces += facing[i];
213 numShadowingFaces = numFaces - numShadowingFaces;
217 // make all triangles that are outside the light frustum "facing", so they won't cast shadows
218 indexes = tri->indexes;
219 byte *modifyFacing = cullInfo.facing;
220 const byte *cullBits = cullInfo.cullBits;
221 for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
222 if ( !modifyFacing[j] ) {
223 int i1 = indexes[i+0];
224 int i2 = indexes[i+1];
225 int i3 = indexes[i+2];
226 if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
235 if ( !numShadowingFaces ) {
236 // no faces are inside the light frustum and still facing the right way
240 newTri = R_AllocStaticTriSurf();
242 #ifdef USE_TRI_DATA_ALLOCATOR
243 R_AllocStaticTriSurfShadowVerts( newTri, tri->numVerts * 2 );
244 shadowCache_t *shadowVerts = newTri->shadowVertexes;
246 shadowCache_t *shadowVerts = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowVerts[0] ) );
249 R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
251 int *vertRemap = (int *)_alloca16( tri->numVerts * sizeof( vertRemap[0] ) );
253 SIMDProcessor->Memset( vertRemap, -1, tri->numVerts * sizeof( vertRemap[0] ) );
255 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
259 // this may pull in some vertexes that are outside
260 // the frustum, because they connect to vertexes inside
261 vertRemap[tri->silIndexes[i+0]] = 0;
262 vertRemap[tri->silIndexes[i+1]] = 0;
263 vertRemap[tri->silIndexes[i+2]] = 0;
266 newTri->numVerts = SIMDProcessor->CreateShadowCache( &shadowVerts->xyz, vertRemap, localLightOrigin, tri->verts, tri->numVerts );
268 c_turboUsedVerts += newTri->numVerts;
269 c_turboUnusedVerts += tri->numVerts * 2 - newTri->numVerts;
271 #ifdef USE_TRI_DATA_ALLOCATOR
272 R_ResizeStaticTriSurfShadowVerts( newTri, newTri->numVerts );
274 R_AllocStaticTriSurfShadowVerts( newTri, newTri->numVerts );
275 SIMDProcessor->Memcpy( newTri->shadowVertexes, shadowVerts, newTri->numVerts * sizeof( shadowVerts[0] ) );
278 // alloc the max possible size
279 #ifdef USE_TRI_DATA_ALLOCATOR
280 R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
281 glIndex_t *tempIndexes = newTri->indexes;
282 glIndex_t *shadowIndexes = newTri->indexes;
284 glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
285 glIndex_t *shadowIndexes = tempIndexes;
288 // create new triangles along sil planes
289 for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
291 int f1 = facing[sil->p1];
292 int f2 = facing[sil->p2];
294 if ( !( f1 ^ f2 ) ) {
298 int v1 = vertRemap[sil->v1];
299 int v2 = vertRemap[sil->v2];
301 // set the two triangle winding orders based on facing
302 // without using a poorly-predictable branch
304 shadowIndexes[0] = v1;
305 shadowIndexes[1] = v2 ^ f1;
306 shadowIndexes[2] = v2 ^ f2;
307 shadowIndexes[3] = v1 ^ f2;
308 shadowIndexes[4] = v1 ^ f1;
309 shadowIndexes[5] = v2 ^ 1;
314 int numShadowIndexes = shadowIndexes - tempIndexes;
316 // we aren't bothering to separate front and back caps on these
317 newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
318 newTri->numShadowIndexesNoCaps = numShadowIndexes;
319 newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
321 #ifdef USE_TRI_DATA_ALLOCATOR
322 // decrease the size of the memory block to only store the used indexes
323 R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
325 // allocate memory for the indexes
326 R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
327 // copy the indexes we created for the sil planes
328 SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
331 // these have no effect, because they extend to infinity
332 newTri->bounds.Clear();
334 // put some faces on the model and some on the distant projection
335 indexes = tri->silIndexes;
336 shadowIndexes = newTri->indexes + numShadowIndexes;
337 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
342 int i0 = vertRemap[indexes[i+0]];
343 shadowIndexes[2] = i0;
344 shadowIndexes[3] = i0 ^ 1;
345 int i1 = vertRemap[indexes[i+1]];
346 shadowIndexes[1] = i1;
347 shadowIndexes[4] = i1 ^ 1;
348 int i2 = vertRemap[indexes[i+2]];
349 shadowIndexes[0] = i2;
350 shadowIndexes[5] = i2 ^ 1;