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 
56 #ifdef USE_OPENGLES
57 static unsigned short indexes[6*MAX_EDGE_DEFS*SHADER_MAX_VERTEXES];
58 static int idx = 0;
59 #endif
60 
R_AddEdgeDef(int i1,int i2,int facing)61 void R_AddEdgeDef( int i1, int i2, int facing ) {
62 	int c;
63 
64 	c = numEdgeDefs[ i1 ];
65 	if ( c == MAX_EDGE_DEFS ) {
66 		return;     // overflow
67 	}
68 	edgeDefs[ i1 ][ c ].i2 = i2;
69 	edgeDefs[ i1 ][ c ].facing = facing;
70 
71 	numEdgeDefs[ i1 ]++;
72 }
73 
R_RenderShadowEdges(void)74 void R_RenderShadowEdges( void ) {
75 	int i;
76 
77 #if 0
78 	int numTris;
79 
80 	// dumb way -- render every triangle's edges
81 	numTris = tess.numIndexes / 3;
82 
83 	for ( i = 0 ; i < numTris ; i++ ) {
84 		int i1, i2, i3;
85 
86 		if ( !facing[i] ) {
87 			continue;
88 		}
89 
90 		i1 = tess.indexes[ i * 3 + 0 ];
91 		i2 = tess.indexes[ i * 3 + 1 ];
92 		i3 = tess.indexes[ i * 3 + 2 ];
93 
94 		qglBegin( GL_TRIANGLE_STRIP );
95 		qglVertex3fv( tess.xyz[ i1 ] );
96 		qglVertex3fv( shadowXyz[ i1 ] );
97 		qglVertex3fv( tess.xyz[ i2 ] );
98 		qglVertex3fv( shadowXyz[ i2 ] );
99 		qglVertex3fv( tess.xyz[ i3 ] );
100 		qglVertex3fv( shadowXyz[ i3 ] );
101 		qglVertex3fv( tess.xyz[ i1 ] );
102 		qglVertex3fv( shadowXyz[ i1 ] );
103 		qglEnd();
104 	}
105 #else
106 	int c, c2;
107 	int j, k;
108 	int i2;
109 	int c_edges, c_rejected;
110 	int hit[2];
111 #ifdef USE_OPENGLES
112 	idx = 0;
113 #endif
114 
115 	// an edge is NOT a silhouette edge if its face doesn't face the light,
116 	// or if it has a reverse paired edge that also faces the light.
117 	// A well behaved polyhedron would have exactly two faces for each edge,
118 	// but lots of models have dangling edges or overfanned edges
119 	c_edges = 0;
120 	c_rejected = 0;
121 
122 	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
123 		c = numEdgeDefs[ i ];
124 		for ( j = 0 ; j < c ; j++ ) {
125 			if ( !edgeDefs[ i ][ j ].facing ) {
126 				continue;
127 			}
128 
129 			hit[0] = 0;
130 			hit[1] = 0;
131 
132 			i2 = edgeDefs[ i ][ j ].i2;
133 			c2 = numEdgeDefs[ i2 ];
134 			for ( k = 0 ; k < c2 ; k++ ) {
135 				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
136 					hit[ edgeDefs[ i2 ][ k ].facing ]++;
137 				}
138 			}
139 
140 			// if it doesn't share the edge with another front facing
141 			// triangle, it is a sil edge
142 			if ( hit[ 1 ] == 0 ) {
143 #ifdef USE_OPENGLES
144 				// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRAINGLE_STRIP call
145 				// even if it seems less efficiant, it's faster on the PANDORA
146 				indexes[idx++] = i;
147 				indexes[idx++] = i + tess.numVertexes;
148 				indexes[idx++] = i2;
149 				indexes[idx++] = i2;
150 				indexes[idx++] = i + tess.numVertexes;
151 				indexes[idx++] = i2 + tess.numVertexes;
152 #else
153 				qglBegin( GL_TRIANGLE_STRIP );
154 				qglVertex3fv( tess.xyz[ i ] );
155 				qglVertex3fv( shadowXyz[ i ] );
156 				qglVertex3fv( tess.xyz[ i2 ] );
157 				qglVertex3fv( shadowXyz[ i2 ] );
158 				qglEnd();
159 #endif
160 				c_edges++;
161 			} else {
162 				c_rejected++;
163 			}
164 		}
165 	}
166 
167 #ifdef USE_OPENGLES
168 	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
169 #endif
170 
171 #endif
172 }
173 
174 /*
175 =================
176 RB_ShadowTessEnd
177 
178 triangleFromEdge[ v1 ][ v2 ]
179 
180 
181   set triangle from edge( v1, v2, tri )
182   if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
183   }
184 =================
185 */
RB_ShadowTessEnd(void)186 void RB_ShadowTessEnd( void ) {
187 	int i;
188 	int numTris;
189 	vec3_t lightDir;
190 	GLboolean rgba[4];
191 
192 	if ( glConfig.stencilBits < 4 ) {
193 		return;
194 	}
195 
196 	VectorCopy( backEnd.currentEntity->lightDir, lightDir );
197 
198 	// project vertexes away from light direction
199 	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
200 		VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] );
201 	}
202 
203 	// decide which triangles face the light
204 	memset( numEdgeDefs, 0, 4 * tess.numVertexes );
205 
206 	numTris = tess.numIndexes / 3;
207 	for ( i = 0 ; i < numTris ; i++ ) {
208 		int i1, i2, i3;
209 		vec3_t d1, d2, normal;
210 		float   *v1, *v2, *v3;
211 		float d;
212 
213 		i1 = tess.indexes[ i * 3 + 0 ];
214 		i2 = tess.indexes[ i * 3 + 1 ];
215 		i3 = tess.indexes[ i * 3 + 2 ];
216 
217 		v1 = tess.xyz[ i1 ];
218 		v2 = tess.xyz[ i2 ];
219 		v3 = tess.xyz[ i3 ];
220 
221 		VectorSubtract( v2, v1, d1 );
222 		VectorSubtract( v3, v1, d2 );
223 		CrossProduct( d1, d2, normal );
224 
225 		d = DotProduct( normal, lightDir );
226 		if ( d > 0 ) {
227 			facing[ i ] = 1;
228 		} else {
229 			facing[ i ] = 0;
230 		}
231 
232 		// create the edges
233 		R_AddEdgeDef( i1, i2, facing[ i ] );
234 		R_AddEdgeDef( i2, i3, facing[ i ] );
235 		R_AddEdgeDef( i3, i1, facing[ i ] );
236 	}
237 
238 	// draw the silhouette edges
239 
240 	GL_Bind( tr.whiteImage );
241 	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
242 	qglColor3f( 0.2f, 0.2f, 0.2f );
243 
244 	// don't write to the color buffer
245 	qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
246 	qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
247 
248 	qglEnable( GL_STENCIL_TEST );
249 	qglStencilFunc( GL_ALWAYS, 1, 255 );
250 
251 #ifdef USE_OPENGLES
252 	qglVertexPointer (3, GL_FLOAT, 16, tess.xyz);
253 	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
254 	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
255 	if (text)
256 		qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
257 	if (glcol)
258 		qglDisableClientState( GL_COLOR_ARRAY );
259 #endif
260 
261 	GL_Cull( CT_BACK_SIDED );
262 	qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
263 
264 	R_RenderShadowEdges();
265 
266 	GL_Cull( CT_FRONT_SIDED );
267 	qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
268 
269 #ifdef USE_OPENGLES
270 	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
271 #else
272 	R_RenderShadowEdges();
273 #endif
274 
275 #ifdef USE_OPENGLES
276 	if (text)
277 		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
278 	if (glcol)
279 		qglEnableClientState( GL_COLOR_ARRAY );
280 #endif
281 
282 	// reenable writing to the color buffer
283 	qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
284 }
285 
286 
287 /*
288 =================
289 RB_ShadowFinish
290 
291 Darken everything that is is a shadow volume.
292 We have to delay this until everything has been shadowed,
293 because otherwise shadows from different body parts would
294 overlap and double darken.
295 =================
296 */
RB_ShadowFinish(void)297 void RB_ShadowFinish( void ) {
298 	if ( r_shadows->integer != 2 ) {
299 		return;
300 	}
301 	if ( glConfig.stencilBits < 4 ) {
302 		return;
303 	}
304 	qglEnable( GL_STENCIL_TEST );
305 	qglStencilFunc( GL_NOTEQUAL, 0, 255 );
306 
307 	qglDisable( GL_CLIP_PLANE0 );
308 	GL_Cull( CT_TWO_SIDED );
309 
310 	GL_Bind( tr.whiteImage );
311 
312 	qglLoadIdentity();
313 
314 	qglColor3f( 0.6f, 0.6f, 0.6f );
315 	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
316 
317 //	qglColor3f( 1, 0, 0 );
318 //	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
319 
320 #ifdef USE_OPENGLES
321 	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
322 	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
323 	if (text)
324 		qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
325 	if (glcol)
326 		qglDisableClientState( GL_COLOR_ARRAY );
327 	GLfloat vtx[] = {
328 	 -100,  100, -10,
329 	  100,  100, -10,
330 	  100, -100, -10,
331 	 -100, -100, -10
332 	};
333 	qglVertexPointer  ( 3, GL_FLOAT, 0, vtx );
334 	qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
335 	if (text)
336 		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
337 	if (glcol)
338 		qglEnableClientState( GL_COLOR_ARRAY );
339 #else
340 	qglBegin( GL_QUADS );
341 	qglVertex3f( -100, 100, -10 );
342 	qglVertex3f( 100, 100, -10 );
343 	qglVertex3f( 100, -100, -10 );
344 	qglVertex3f( -100, -100, -10 );
345 	qglEnd();
346 #endif
347 
348 	qglColor4f( 1,1,1,1 );
349 	qglDisable( GL_STENCIL_TEST );
350 }
351 
352 
353 /*
354 =================
355 RB_ProjectionShadowDeform
356 
357 =================
358 */
RB_ProjectionShadowDeform(void)359 void RB_ProjectionShadowDeform( void ) {
360 	float   *xyz;
361 	int i;
362 	float h;
363 	vec3_t ground;
364 	vec3_t light;
365 	float groundDist;
366 	float d;
367 	vec3_t lightDir;
368 
369 	xyz = ( float * ) tess.xyz;
370 
371 	ground[0] = backEnd.or.axis[0][2];
372 	ground[1] = backEnd.or.axis[1][2];
373 	ground[2] = backEnd.or.axis[2][2];
374 
375 	groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
376 
377 	VectorCopy( backEnd.currentEntity->lightDir, lightDir );
378 	d = DotProduct( lightDir, ground );
379 	// don't let the shadows get too long or go negative
380 	if ( d < 0.5 ) {
381 		VectorMA( lightDir, ( 0.5 - d ), ground, lightDir );
382 		d = DotProduct( lightDir, ground );
383 	}
384 	d = 1.0 / d;
385 
386 	light[0] = lightDir[0] * d;
387 	light[1] = lightDir[1] * d;
388 	light[2] = lightDir[2] * d;
389 
390 	for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
391 		h = DotProduct( xyz, ground ) + groundDist;
392 
393 		xyz[0] -= light[0] * h;
394 		xyz[1] -= light[1] * h;
395 		xyz[2] -= light[2] * h;
396 	}
397 }
398