1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
8
9 RTCW MP 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 RTCW MP 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW MP 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 RTCW MP 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 "tr_local.h"
30
31
32 /*
33
34 for a projection shadow:
35
36 point[x] += light vector * ( z - shadow plane )
37 point[y] +=
38 point[z] = shadow plane
39
40 1 0 light[x] / light[z]
41
42 */
43
44 typedef struct {
45 int i2;
46 int facing;
47 } edgeDef_t;
48
49 #define MAX_EDGE_DEFS 32
50
51 static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
52 static int numEdgeDefs[SHADER_MAX_VERTEXES];
53 //static int facing[SHADER_MAX_INDEXES / 3];
54 //static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
55
R_AddEdgeDef(int i1,int i2,int facing)56 void R_AddEdgeDef( int i1, int i2, int facing ) {
57 int c;
58
59 c = numEdgeDefs[ i1 ];
60 if ( c == MAX_EDGE_DEFS ) {
61 return; // overflow
62 }
63 edgeDefs[ i1 ][ c ].i2 = i2;
64 edgeDefs[ i1 ][ c ].facing = facing;
65
66 numEdgeDefs[ i1 ]++;
67 }
68
R_RenderShadowEdges(void)69 void R_RenderShadowEdges( void ) {
70 // FIXME: implement this
71 #if 0
72 int i;
73
74 #if 0
75 int numTris;
76
77 // dumb way -- render every triangle's edges
78 numTris = tess.numIndexes / 3;
79
80 for ( i = 0 ; i < numTris ; i++ ) {
81 int i1, i2, i3;
82
83 if ( !facing[i] ) {
84 continue;
85 }
86
87 i1 = tess.indexes[ i * 3 + 0 ];
88 i2 = tess.indexes[ i * 3 + 1 ];
89 i3 = tess.indexes[ i * 3 + 2 ];
90
91 qglBegin( GL_TRIANGLE_STRIP );
92 qglVertex3fv( tess.xyz[ i1 ] );
93 qglVertex3fv( shadowXyz[ i1 ] );
94 qglVertex3fv( tess.xyz[ i2 ] );
95 qglVertex3fv( shadowXyz[ i2 ] );
96 qglVertex3fv( tess.xyz[ i3 ] );
97 qglVertex3fv( shadowXyz[ i3 ] );
98 qglVertex3fv( tess.xyz[ i1 ] );
99 qglVertex3fv( shadowXyz[ i1 ] );
100 qglEnd();
101 }
102 #else
103 int c, c2;
104 int j, k;
105 int i2;
106 int c_edges, c_rejected;
107 int hit[2];
108
109 // an edge is NOT a silhouette edge if its face doesn't face the light,
110 // or if it has a reverse paired edge that also faces the light.
111 // A well behaved polyhedron would have exactly two faces for each edge,
112 // but lots of models have dangling edges or overfanned edges
113 c_edges = 0;
114 c_rejected = 0;
115
116 for ( i = 0 ; i < tess.numVertexes ; i++ ) {
117 c = numEdgeDefs[ i ];
118 for ( j = 0 ; j < c ; j++ ) {
119 if ( !edgeDefs[ i ][ j ].facing ) {
120 continue;
121 }
122
123 hit[0] = 0;
124 hit[1] = 0;
125
126 i2 = edgeDefs[ i ][ j ].i2;
127 c2 = numEdgeDefs[ i2 ];
128 for ( k = 0 ; k < c2 ; k++ ) {
129 if ( edgeDefs[ i2 ][ k ].i2 == i ) {
130 hit[ edgeDefs[ i2 ][ k ].facing ]++;
131 }
132 }
133
134 // if it doesn't share the edge with another front facing
135 // triangle, it is a sil edge
136 if ( hit[ 1 ] == 0 ) {
137 qglBegin( GL_TRIANGLE_STRIP );
138 qglVertex3fv( tess.xyz[ i ] );
139 qglVertex3fv( shadowXyz[ i ] );
140 qglVertex3fv( tess.xyz[ i2 ] );
141 qglVertex3fv( shadowXyz[ i2 ] );
142 qglEnd();
143 c_edges++;
144 } else {
145 c_rejected++;
146 }
147 }
148 }
149 #endif
150 #endif
151 }
152
153 /*
154 =================
155 RB_ShadowTessEnd
156
157 triangleFromEdge[ v1 ][ v2 ]
158
159
160 set triangle from edge( v1, v2, tri )
161 if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
162 }
163 =================
164 */
RB_ShadowTessEnd(void)165 void RB_ShadowTessEnd( void ) {
166 // FIXME: implement this
167 #if 0
168 int i;
169 int numTris;
170 vec3_t lightDir;
171 GLboolean rgba[4];
172
173 if ( glConfig.stencilBits < 4 ) {
174 return;
175 }
176
177 VectorCopy( backEnd.currentEntity->lightDir, lightDir );
178
179 // project vertexes away from light direction
180 for ( i = 0 ; i < tess.numVertexes ; i++ ) {
181 VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] );
182 }
183
184 // decide which triangles face the light
185 memset( numEdgeDefs, 0, 4 * tess.numVertexes );
186
187 numTris = tess.numIndexes / 3;
188 for ( i = 0 ; i < numTris ; i++ ) {
189 int i1, i2, i3;
190 vec3_t d1, d2, normal;
191 float *v1, *v2, *v3;
192 float d;
193
194 i1 = tess.indexes[ i * 3 + 0 ];
195 i2 = tess.indexes[ i * 3 + 1 ];
196 i3 = tess.indexes[ i * 3 + 2 ];
197
198 v1 = tess.xyz[ i1 ];
199 v2 = tess.xyz[ i2 ];
200 v3 = tess.xyz[ i3 ];
201
202 VectorSubtract( v2, v1, d1 );
203 VectorSubtract( v3, v1, d2 );
204 CrossProduct( d1, d2, normal );
205
206 d = DotProduct( normal, lightDir );
207 if ( d > 0 ) {
208 facing[ i ] = 1;
209 } else {
210 facing[ i ] = 0;
211 }
212
213 // create the edges
214 R_AddEdgeDef( i1, i2, facing[ i ] );
215 R_AddEdgeDef( i2, i3, facing[ i ] );
216 R_AddEdgeDef( i3, i1, facing[ i ] );
217 }
218
219 // draw the silhouette edges
220
221 GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
222 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
223 qglColor3f( 0.2f, 0.2f, 0.2f );
224
225 // don't write to the color buffer
226 qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
227 qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
228
229 qglEnable( GL_STENCIL_TEST );
230 qglStencilFunc( GL_ALWAYS, 1, 255 );
231
232 GL_Cull( CT_BACK_SIDED );
233 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
234
235 R_RenderShadowEdges();
236
237 GL_Cull( CT_FRONT_SIDED );
238 qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
239
240 R_RenderShadowEdges();
241
242 // reenable writing to the color buffer
243 qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
244 #endif
245 }
246
247
248 /*
249 =================
250 RB_ShadowFinish
251
252 Darken everything that is is a shadow volume.
253 We have to delay this until everything has been shadowed,
254 because otherwise shadows from different body parts would
255 overlap and double darken.
256 =================
257 */
RB_ShadowFinish(void)258 void RB_ShadowFinish( void ) {
259 // FIXME: implement this
260 #if 0
261 if ( r_shadows->integer != 2 ) {
262 return;
263 }
264 if ( glConfig.stencilBits < 4 ) {
265 return;
266 }
267 qglEnable( GL_STENCIL_TEST );
268 qglStencilFunc( GL_NOTEQUAL, 0, 255 );
269
270 GL_Cull( CT_TWO_SIDED );
271
272 GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
273
274 qglLoadIdentity();
275
276 qglColor3f( 0.6f, 0.6f, 0.6f );
277 GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
278
279 // qglColor3f( 1, 0, 0 );
280 // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
281
282 qglBegin( GL_QUADS );
283 qglVertex3f( -100, 100, -10 );
284 qglVertex3f( 100, 100, -10 );
285 qglVertex3f( 100, -100, -10 );
286 qglVertex3f( -100, -100, -10 );
287 qglEnd();
288
289 qglColor4f( 1,1,1,1 );
290 qglDisable( GL_STENCIL_TEST );
291 #endif
292 }
293
294
295 /*
296 =================
297 RB_ProjectionShadowDeform
298
299 =================
300 */
RB_ProjectionShadowDeform(void)301 void RB_ProjectionShadowDeform( void ) {
302 float *xyz;
303 int i;
304 float h;
305 vec3_t ground;
306 vec3_t light;
307 float groundDist;
308 float d;
309 vec3_t lightDir;
310
311 xyz = ( float * ) tess.xyz;
312
313 ground[0] = backEnd.or.axis[0][2];
314 ground[1] = backEnd.or.axis[1][2];
315 ground[2] = backEnd.or.axis[2][2];
316
317 groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
318
319 VectorCopy( backEnd.currentEntity->lightDir, lightDir );
320 d = DotProduct( lightDir, ground );
321 // don't let the shadows get too long or go negative
322 if ( d < 0.5 ) {
323 VectorMA( lightDir, ( 0.5 - d ), ground, lightDir );
324 d = DotProduct( lightDir, ground );
325 }
326 d = 1.0 / d;
327
328 light[0] = lightDir[0] * d;
329 light[1] = lightDir[1] * d;
330 light[2] = lightDir[2] * d;
331
332 for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
333 h = DotProduct( xyz, ground ) + groundDist;
334
335 xyz[0] -= light[0] * h;
336 xyz[1] -= light[1] * h;
337 xyz[2] -= light[2] * h;
338 }
339 }
340