]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/tr_turboshadow.cpp
Use the same OpenAL headers on all platforms.
[icculus/iodoom3.git] / neo / renderer / tr_turboshadow.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
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.
13
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.
18
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/>.
21
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.
23
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.
25
26 ===========================================================================
27 */
28
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "tr_local.h"
33
34 int     c_turboUsedVerts;
35 int c_turboUnusedVerts;
36
37
38 /*
39 =====================
40 R_CreateVertexProgramTurboShadowVolume
41
42 are dangling edges that are outside the light frustum still making planes?
43 =====================
44 */
45 srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent, 
46                                                                                                                 const srfTriangles_t *tri, const idRenderLightLocal *light,
47                                                                                                                 srfCullInfo_t &cullInfo ) {
48         int             i, j;
49         srfTriangles_t  *newTri;
50         silEdge_t       *sil;
51         const glIndex_t *indexes;
52         const byte *facing;
53
54         R_CalcInteractionFacing( ent, tri, light, cullInfo );
55         if ( r_useShadowProjectedCull.GetBool() ) {
56                 R_CalcInteractionCullBits( ent, tri, light, cullInfo );
57         }
58
59         int numFaces = tri->numIndexes / 3;
60         int     numShadowingFaces = 0;
61         facing = cullInfo.facing;
62
63         // if all the triangles are inside the light frustum
64         if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
65
66                 // count the number of shadowing faces
67                 for ( i = 0; i < numFaces; i++ ) {
68                         numShadowingFaces += facing[i];
69                 }
70                 numShadowingFaces = numFaces - numShadowingFaces;
71
72         } else {
73
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] ) {
84                                         modifyFacing[j] = 1;
85                                 } else {
86                                         numShadowingFaces++;
87                                 }
88                         }
89                 }
90         }
91
92         if ( !numShadowingFaces ) {
93                 // no faces are inside the light frustum and still facing the right way
94                 return NULL;
95         }
96
97         // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
98         newTri = R_AllocStaticTriSurf();
99
100         newTri->numVerts = tri->numVerts * 2;
101
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;
107 #else
108         glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
109         glIndex_t *shadowIndexes = tempIndexes;
110 #endif
111
112         // create new triangles along sil planes
113         for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
114
115                 int f1 = facing[sil->p1];
116                 int f2 = facing[sil->p2];
117
118                 if ( !( f1 ^ f2 ) ) {
119                         continue;
120                 }
121
122                 int v1 = sil->v1 << 1;
123                 int v2 = sil->v2 << 1;
124
125                 // set the two triangle winding orders based on facing
126                 // without using a poorly-predictable branch
127
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;
134
135                 shadowIndexes += 6;
136         }
137
138         int     numShadowIndexes = shadowIndexes - tempIndexes;
139
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;
144
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 );
148 #else
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] ) );
153 #endif
154
155         // these have no effect, because they extend to infinity
156         newTri->bounds.Clear();
157
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++ ) {
162                 if ( facing[j] ) {
163                         continue;
164                 }
165
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;
175
176                 shadowIndexes += 6;
177         }
178
179         return newTri;
180 }
181
182 /*
183 =====================
184 R_CreateTurboShadowVolume
185 =====================
186 */
187 srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
188                                                                                         const srfTriangles_t *tri, const idRenderLightLocal *light,
189                                                                                         srfCullInfo_t &cullInfo ) {
190         int             i, j;
191         idVec3  localLightOrigin;
192         srfTriangles_t  *newTri;
193         silEdge_t       *sil;
194         const glIndex_t *indexes;
195         const byte *facing;
196
197         R_CalcInteractionFacing( ent, tri, light, cullInfo );
198         if ( r_useShadowProjectedCull.GetBool() ) {
199                 R_CalcInteractionCullBits( ent, tri, light, cullInfo );
200         }
201
202         int numFaces = tri->numIndexes / 3;
203         int     numShadowingFaces = 0;
204         facing = cullInfo.facing;
205
206         // if all the triangles are inside the light frustum
207         if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
208
209                 // count the number of shadowing faces
210                 for ( i = 0; i < numFaces; i++ ) {
211                         numShadowingFaces += facing[i];
212                 }
213                 numShadowingFaces = numFaces - numShadowingFaces;
214
215         } else {
216
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] ) {
227                                         modifyFacing[j] = 1;
228                                 } else {
229                                         numShadowingFaces++;
230                                 }
231                         }
232                 }
233         }
234
235         if ( !numShadowingFaces ) {
236                 // no faces are inside the light frustum and still facing the right way
237                 return NULL;
238         }
239
240         newTri = R_AllocStaticTriSurf();
241
242 #ifdef USE_TRI_DATA_ALLOCATOR
243         R_AllocStaticTriSurfShadowVerts( newTri, tri->numVerts * 2 );
244         shadowCache_t *shadowVerts = newTri->shadowVertexes;
245 #else
246         shadowCache_t *shadowVerts = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowVerts[0] ) );
247 #endif
248
249         R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
250
251         int     *vertRemap = (int *)_alloca16( tri->numVerts * sizeof( vertRemap[0] ) );
252
253         SIMDProcessor->Memset( vertRemap, -1, tri->numVerts * sizeof( vertRemap[0] ) );
254
255         for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
256                 if ( facing[j] ) {
257                         continue;
258                 }
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;
264         }
265
266         newTri->numVerts = SIMDProcessor->CreateShadowCache( &shadowVerts->xyz, vertRemap, localLightOrigin, tri->verts, tri->numVerts );
267
268         c_turboUsedVerts += newTri->numVerts;
269         c_turboUnusedVerts += tri->numVerts * 2 - newTri->numVerts;
270
271 #ifdef USE_TRI_DATA_ALLOCATOR
272         R_ResizeStaticTriSurfShadowVerts( newTri, newTri->numVerts );
273 #else
274         R_AllocStaticTriSurfShadowVerts( newTri, newTri->numVerts );
275         SIMDProcessor->Memcpy( newTri->shadowVertexes, shadowVerts, newTri->numVerts * sizeof( shadowVerts[0] ) );
276 #endif
277
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;
283 #else
284         glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
285         glIndex_t *shadowIndexes = tempIndexes;
286 #endif
287
288         // create new triangles along sil planes
289         for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
290
291                 int f1 = facing[sil->p1];
292                 int f2 = facing[sil->p2];
293
294                 if ( !( f1 ^ f2 ) ) {
295                         continue;
296                 }
297
298                 int v1 = vertRemap[sil->v1];
299                 int v2 = vertRemap[sil->v2];
300
301                 // set the two triangle winding orders based on facing
302                 // without using a poorly-predictable branch
303
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;
310
311                 shadowIndexes += 6;
312         }
313
314         int numShadowIndexes = shadowIndexes - tempIndexes;
315
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;
320
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 );
324 #else
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] ) );
329 #endif
330
331         // these have no effect, because they extend to infinity
332         newTri->bounds.Clear();
333
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++ ) {
338                 if ( facing[j] ) {
339                         continue;
340                 }
341
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;
351
352                 shadowIndexes += 6;
353         }
354
355         return newTri;
356 }