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 "sys/platform.h"
30
31 #include "renderer/tr_local.h"
32
33 int c_turboUsedVerts;
34 int c_turboUnusedVerts;
35
36 /*
37 =====================
38 R_CreateVertexProgramTurboShadowVolume
39
40 are dangling edges that are outside the light frustum still making planes?
41 =====================
42 */
R_CreateVertexProgramTurboShadowVolume(const idRenderEntityLocal * ent,const srfTriangles_t * tri,const idRenderLightLocal * light,srfCullInfo_t & cullInfo)43 srfTriangles_t *R_CreateVertexProgramTurboShadowVolume( const idRenderEntityLocal *ent,
44 const srfTriangles_t *tri, const idRenderLightLocal *light,
45 srfCullInfo_t &cullInfo ) {
46 int i, j;
47 srfTriangles_t *newTri;
48 silEdge_t *sil;
49 const glIndex_t *indexes;
50 const byte *facing;
51
52 R_CalcInteractionFacing( ent, tri, light, cullInfo );
53 if ( r_useShadowProjectedCull.GetBool() ) {
54 R_CalcInteractionCullBits( ent, tri, light, cullInfo );
55 }
56
57 int numFaces = tri->numIndexes / 3;
58 int numShadowingFaces = 0;
59 facing = cullInfo.facing;
60
61 // if all the triangles are inside the light frustum
62 if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
63
64 // count the number of shadowing faces
65 for ( i = 0; i < numFaces; i++ ) {
66 numShadowingFaces += facing[i];
67 }
68 numShadowingFaces = numFaces - numShadowingFaces;
69
70 } else {
71
72 // make all triangles that are outside the light frustum "facing", so they won't cast shadows
73 indexes = tri->indexes;
74 byte *modifyFacing = cullInfo.facing;
75 const byte *cullBits = cullInfo.cullBits;
76 for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
77 if ( !modifyFacing[j] ) {
78 int i1 = indexes[i+0];
79 int i2 = indexes[i+1];
80 int i3 = indexes[i+2];
81 if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
82 modifyFacing[j] = 1;
83 } else {
84 numShadowingFaces++;
85 }
86 }
87 }
88 }
89
90 if ( !numShadowingFaces ) {
91 // no faces are inside the light frustum and still facing the right way
92 return NULL;
93 }
94
95 // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
96 newTri = R_AllocStaticTriSurf();
97
98 newTri->numVerts = tri->numVerts * 2;
99
100 // alloc the max possible size
101 #ifdef USE_TRI_DATA_ALLOCATOR
102 R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
103 glIndex_t *tempIndexes = newTri->indexes;
104 glIndex_t *shadowIndexes = newTri->indexes;
105 #else
106 glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
107 glIndex_t *shadowIndexes = tempIndexes;
108 #endif
109
110 // create new triangles along sil planes
111 for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
112
113 int f1 = facing[sil->p1];
114 int f2 = facing[sil->p2];
115
116 if ( !( f1 ^ f2 ) ) {
117 continue;
118 }
119
120 int v1 = sil->v1 << 1;
121 int v2 = sil->v2 << 1;
122
123 // set the two triangle winding orders based on facing
124 // without using a poorly-predictable branch
125
126 shadowIndexes[0] = v1;
127 shadowIndexes[1] = v2 ^ f1;
128 shadowIndexes[2] = v2 ^ f2;
129 shadowIndexes[3] = v1 ^ f2;
130 shadowIndexes[4] = v1 ^ f1;
131 shadowIndexes[5] = v2 ^ 1;
132
133 shadowIndexes += 6;
134 }
135
136 int numShadowIndexes = shadowIndexes - tempIndexes;
137
138 // we aren't bothering to separate front and back caps on these
139 newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
140 newTri->numShadowIndexesNoCaps = numShadowIndexes;
141 newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
142
143 #ifdef USE_TRI_DATA_ALLOCATOR
144 // decrease the size of the memory block to only store the used indexes
145 R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
146 #else
147 // allocate memory for the indexes
148 R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
149 // copy the indexes we created for the sil planes
150 SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
151 #endif
152
153 // these have no effect, because they extend to infinity
154 newTri->bounds.Clear();
155
156 // put some faces on the model and some on the distant projection
157 indexes = tri->indexes;
158 shadowIndexes = newTri->indexes + numShadowIndexes;
159 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
160 if ( facing[j] ) {
161 continue;
162 }
163
164 int i0 = indexes[i+0] << 1;
165 shadowIndexes[2] = i0;
166 shadowIndexes[3] = i0 ^ 1;
167 int i1 = indexes[i+1] << 1;
168 shadowIndexes[1] = i1;
169 shadowIndexes[4] = i1 ^ 1;
170 int i2 = indexes[i+2] << 1;
171 shadowIndexes[0] = i2;
172 shadowIndexes[5] = i2 ^ 1;
173
174 shadowIndexes += 6;
175 }
176
177 return newTri;
178 }
179
180 /*
181 =====================
182 R_CreateTurboShadowVolume
183 =====================
184 */
R_CreateTurboShadowVolume(const idRenderEntityLocal * ent,const srfTriangles_t * tri,const idRenderLightLocal * light,srfCullInfo_t & cullInfo)185 srfTriangles_t *R_CreateTurboShadowVolume( const idRenderEntityLocal *ent,
186 const srfTriangles_t *tri, const idRenderLightLocal *light,
187 srfCullInfo_t &cullInfo ) {
188 int i, j;
189 idVec3 localLightOrigin;
190 srfTriangles_t *newTri;
191 silEdge_t *sil;
192 const glIndex_t *indexes;
193 const byte *facing;
194
195 R_CalcInteractionFacing( ent, tri, light, cullInfo );
196 if ( r_useShadowProjectedCull.GetBool() ) {
197 R_CalcInteractionCullBits( ent, tri, light, cullInfo );
198 }
199
200 int numFaces = tri->numIndexes / 3;
201 int numShadowingFaces = 0;
202 facing = cullInfo.facing;
203
204 // if all the triangles are inside the light frustum
205 if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.GetBool() ) {
206
207 // count the number of shadowing faces
208 for ( i = 0; i < numFaces; i++ ) {
209 numShadowingFaces += facing[i];
210 }
211 numShadowingFaces = numFaces - numShadowingFaces;
212
213 } else {
214
215 // make all triangles that are outside the light frustum "facing", so they won't cast shadows
216 indexes = tri->indexes;
217 byte *modifyFacing = cullInfo.facing;
218 const byte *cullBits = cullInfo.cullBits;
219 for ( j = i = 0; i < tri->numIndexes; i += 3, j++ ) {
220 if ( !modifyFacing[j] ) {
221 int i1 = indexes[i+0];
222 int i2 = indexes[i+1];
223 int i3 = indexes[i+2];
224 if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
225 modifyFacing[j] = 1;
226 } else {
227 numShadowingFaces++;
228 }
229 }
230 }
231 }
232
233 if ( !numShadowingFaces ) {
234 // no faces are inside the light frustum and still facing the right way
235 return NULL;
236 }
237
238 newTri = R_AllocStaticTriSurf();
239
240 #ifdef USE_TRI_DATA_ALLOCATOR
241 R_AllocStaticTriSurfShadowVerts( newTri, tri->numVerts * 2 );
242 shadowCache_t *shadowVerts = newTri->shadowVertexes;
243 #else
244 shadowCache_t *shadowVerts = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowVerts[0] ) );
245 #endif
246
247 R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
248
249 int *vertRemap = (int *)_alloca16( tri->numVerts * sizeof( vertRemap[0] ) );
250
251 SIMDProcessor->Memset( vertRemap, -1, tri->numVerts * sizeof( vertRemap[0] ) );
252
253 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
254 if ( facing[j] ) {
255 continue;
256 }
257 // this may pull in some vertexes that are outside
258 // the frustum, because they connect to vertexes inside
259 vertRemap[tri->silIndexes[i+0]] = 0;
260 vertRemap[tri->silIndexes[i+1]] = 0;
261 vertRemap[tri->silIndexes[i+2]] = 0;
262 }
263
264 newTri->numVerts = SIMDProcessor->CreateShadowCache( &shadowVerts->xyz, vertRemap, localLightOrigin, tri->verts, tri->numVerts );
265
266 c_turboUsedVerts += newTri->numVerts;
267 c_turboUnusedVerts += tri->numVerts * 2 - newTri->numVerts;
268
269 #ifdef USE_TRI_DATA_ALLOCATOR
270 R_ResizeStaticTriSurfShadowVerts( newTri, newTri->numVerts );
271 #else
272 R_AllocStaticTriSurfShadowVerts( newTri, newTri->numVerts );
273 SIMDProcessor->Memcpy( newTri->shadowVertexes, shadowVerts, newTri->numVerts * sizeof( shadowVerts[0] ) );
274 #endif
275
276 // alloc the max possible size
277 #ifdef USE_TRI_DATA_ALLOCATOR
278 R_AllocStaticTriSurfIndexes( newTri, ( numShadowingFaces + tri->numSilEdges ) * 6 );
279 glIndex_t *tempIndexes = newTri->indexes;
280 glIndex_t *shadowIndexes = newTri->indexes;
281 #else
282 glIndex_t *tempIndexes = (glIndex_t *)_alloca16( tri->numSilEdges * 6 * sizeof( tempIndexes[0] ) );
283 glIndex_t *shadowIndexes = tempIndexes;
284 #endif
285
286 // create new triangles along sil planes
287 for ( sil = tri->silEdges, i = tri->numSilEdges; i > 0; i--, sil++ ) {
288
289 int f1 = facing[sil->p1];
290 int f2 = facing[sil->p2];
291
292 if ( !( f1 ^ f2 ) ) {
293 continue;
294 }
295
296 int v1 = vertRemap[sil->v1];
297 int v2 = vertRemap[sil->v2];
298
299 // set the two triangle winding orders based on facing
300 // without using a poorly-predictable branch
301
302 shadowIndexes[0] = v1;
303 shadowIndexes[1] = v2 ^ f1;
304 shadowIndexes[2] = v2 ^ f2;
305 shadowIndexes[3] = v1 ^ f2;
306 shadowIndexes[4] = v1 ^ f1;
307 shadowIndexes[5] = v2 ^ 1;
308
309 shadowIndexes += 6;
310 }
311
312 int numShadowIndexes = shadowIndexes - tempIndexes;
313
314 // we aren't bothering to separate front and back caps on these
315 newTri->numIndexes = newTri->numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
316 newTri->numShadowIndexesNoCaps = numShadowIndexes;
317 newTri->shadowCapPlaneBits = SHADOW_CAP_INFINITE;
318
319 #ifdef USE_TRI_DATA_ALLOCATOR
320 // decrease the size of the memory block to only store the used indexes
321 R_ResizeStaticTriSurfIndexes( newTri, newTri->numIndexes );
322 #else
323 // allocate memory for the indexes
324 R_AllocStaticTriSurfIndexes( newTri, newTri->numIndexes );
325 // copy the indexes we created for the sil planes
326 SIMDProcessor->Memcpy( newTri->indexes, tempIndexes, numShadowIndexes * sizeof( tempIndexes[0] ) );
327 #endif
328
329 // these have no effect, because they extend to infinity
330 newTri->bounds.Clear();
331
332 // put some faces on the model and some on the distant projection
333 indexes = tri->silIndexes;
334 shadowIndexes = newTri->indexes + numShadowIndexes;
335 for ( i = 0, j = 0; i < tri->numIndexes; i += 3, j++ ) {
336 if ( facing[j] ) {
337 continue;
338 }
339
340 int i0 = vertRemap[indexes[i+0]];
341 shadowIndexes[2] = i0;
342 shadowIndexes[3] = i0 ^ 1;
343 int i1 = vertRemap[indexes[i+1]];
344 shadowIndexes[1] = i1;
345 shadowIndexes[4] = i1 ^ 1;
346 int i2 = vertRemap[indexes[i+2]];
347 shadowIndexes[0] = i2;
348 shadowIndexes[5] = i2 ^ 1;
349
350 shadowIndexes += 6;
351 }
352
353 return newTri;
354 }
355