doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tr_turboshadow.cpp
Go to the documentation of this file.
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 
36 
37 
38 /*
39 =====================
40 R_CreateVertexProgramTurboShadowVolume
41 
42 are dangling edges that are outside the light frustum still making planes?
43 =====================
44 */
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 );
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
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;
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 */
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 );
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
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;
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 }
int numShadowIndexesNoFrontCaps
Definition: Model.h:119
int shadowCapPlaneBits
Definition: Model.h:122
void R_CalcInteractionCullBits(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
Definition: Interaction.cpp:92
glIndex_t p1
Definition: Model.h:64
byte * facing
Definition: Interaction.h:51
#define LIGHT_CULL_ALL_FRONT
Definition: Interaction.h:45
glIndex_t * silIndexes
Definition: Model.h:104
int numVerts
Definition: Model.h:98
idVec4 xyz
Definition: Model.h:80
void R_CalcInteractionFacing(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
Definition: Interaction.cpp:55
int c_turboUsedVerts
Definition: Vector.h:316
glIndex_t p2
Definition: Model.h:64
silEdge_t * silEdges
Definition: Model.h:113
idCVar r_useShadowProjectedCull("r_useShadowProjectedCull","1", CVAR_RENDERER|CVAR_BOOL,"discard triangles outside light volume before shadowing")
float modelMatrix[16]
Definition: tr_local.h:253
void Clear(void)
Definition: Bounds.h:201
void R_ResizeStaticTriSurfShadowVerts(srfTriangles_t *tri, int numVerts)
Definition: tr_trisurf.cpp:623
srfTriangles_t * R_AllocStaticTriSurf(void)
Definition: tr_trisurf.cpp:523
virtual void VPCALL Memset(void *dst, const int val, const int count)=0
int i
Definition: process.py:33
byte * cullBits
Definition: Interaction.h:57
int numSilEdges
Definition: Model.h:112
srfTriangles_t * R_CreateVertexProgramTurboShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
GLfloat GLfloat GLfloat v2
Definition: glext.h:3608
glIndex_t v2
Definition: Model.h:65
int c_turboUnusedVerts
idBounds bounds
Definition: Model.h:87
#define NULL
Definition: Lib.h:88
int glIndex_t
Definition: Model.h:52
const int SHADOW_CAP_INFINITE
Definition: Model.h:83
void R_AllocStaticTriSurfShadowVerts(srfTriangles_t *tri, int numVerts)
Definition: tr_trisurf.cpp:575
shadowCache_t * shadowVertexes
Definition: Model.h:127
GLfloat GLfloat v1
Definition: glext.h:3607
virtual void VPCALL Memcpy(void *dst, const void *src, const int count)=0
int numShadowIndexesNoCaps
Definition: Model.h:120
void R_GlobalPointToLocal(const float modelMatrix[16], const idVec3 &in, idVec3 &out)
Definition: tr_main.cpp:522
bool GetBool(void) const
Definition: CVarSystem.h:142
GLint GLint i2
Definition: qgl.h:261
glIndex_t v1
Definition: Model.h:65
unsigned char byte
Definition: Lib.h:75
GLint i1
Definition: qgl.h:261
glIndex_t * indexes
Definition: Model.h:102
srfTriangles_t * R_CreateTurboShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
void R_AllocStaticTriSurfIndexes(srfTriangles_t *tri, int numIndexes)
Definition: tr_trisurf.cpp:565
GLint j
Definition: qgl.h:264
int numIndexes
Definition: Model.h:101
void R_ResizeStaticTriSurfIndexes(srfTriangles_t *tri, int numIndexes)
Definition: tr_trisurf.cpp:610
idDrawVert * verts
Definition: Model.h:99
idVec3 globalLightOrigin
Definition: tr_local.h:216
virtual int VPCALL CreateShadowCache(idVec4 *vertexCache, int *vertRemap, const idVec3 &lightOrigin, const idDrawVert *verts, const int numVerts)=0
idSIMDProcessor * SIMDProcessor
Definition: Simd.cpp:43