1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein single player 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 single player GPL Source Code (“RTCW SP Source Code”).
8 
9 RTCW SP 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 SP 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 SP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW SP 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 SP 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 // tr_shade.c
30 
31 #include "tr_local.h"
32 
33 /*
34 
35   THIS ENTIRE FILE IS BACK END
36 
37   This file deals with applying shaders to surface data in the tess struct.
38 */
39 
40 /*
41 ================
42 R_ArrayElementDiscrete
43 
44 This is just for OpenGL conformance testing, it should never be the fastest
45 ================
46 */
47 #ifndef USE_OPENGLES
R_ArrayElementDiscrete(GLint index)48 static void APIENTRY R_ArrayElementDiscrete( GLint index ) {
49 	qglColor4ubv( tess.svars.colors[ index ] );
50 	if ( glState.currenttmu ) {
51 		qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] );
52 		qglMultiTexCoord2fARB( 1, tess.svars.texcoords[ 1 ][ index ][0], tess.svars.texcoords[ 1 ][ index ][1] );
53 	} else {
54 		qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] );
55 	}
56 	qglVertex3fv( tess.xyz[ index ] );
57 }
58 #endif
59 
60 /*
61 ===================
62 R_DrawStripElements
63 
64 ===================
65 */
66 #ifdef USE_OPENGLES
67 #define MAX_INDEX 4096
68 glIndex_t sindexes[MAX_INDEX];
69 int num_sindexed;
70 
AddIndexe(GLint idx)71 void AddIndexe(GLint idx) {
72 	sindexes[num_sindexed++]=idx;
73 }
74 #endif
75 
76 #ifndef USE_OPENGLES
77 static int c_vertexes;          // for seeing how long our average strips are
78 static int c_begins;
R_DrawStripElements(int numIndexes,const glIndex_t * indexes,void (APIENTRY * element)(GLint))79 static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )( GLint ) ) {
80 	int i;
81 	int last[3] = { -1, -1, -1 };
82 	qboolean even;
83 
84 	c_begins++;
85 
86 	if ( numIndexes <= 0 ) {
87 		return;
88 	}
89 
90 	qglBegin( GL_TRIANGLE_STRIP );
91 
92 	// prime the strip
93 	element( indexes[0] );
94 	element( indexes[1] );
95 	element( indexes[2] );
96 	c_vertexes += 3;
97 
98 	last[0] = indexes[0];
99 	last[1] = indexes[1];
100 	last[2] = indexes[2];
101 
102 	even = qfalse;
103 
104 	for ( i = 3; i < numIndexes; i += 3 )
105 	{
106 		// odd numbered triangle in potential strip
107 		if ( !even ) {
108 			// check previous triangle to see if we're continuing a strip
109 			if ( ( indexes[i + 0] == last[2] ) && ( indexes[i + 1] == last[1] ) ) {
110 				element( indexes[i + 2] );
111 				c_vertexes++;
112 				assert( indexes[i + 2] < tess.numVertexes );
113 				even = qtrue;
114 			}
115 			// otherwise we're done with this strip so finish it and start
116 			// a new one
117 			else
118 			{
119 				qglEnd();
120 
121 				qglBegin( GL_TRIANGLE_STRIP );
122 				c_begins++;
123 
124 				element( indexes[i + 0] );
125 				element( indexes[i + 1] );
126 				element( indexes[i + 2] );
127 
128 				c_vertexes += 3;
129 
130 				even = qfalse;
131 			}
132 		} else
133 		{
134 			// check previous triangle to see if we're continuing a strip
135 			if ( ( last[2] == indexes[i + 1] ) && ( last[0] == indexes[i + 0] ) ) {
136 				element( indexes[i + 2] );
137 				c_vertexes++;
138 
139 				even = qfalse;
140 			}
141 			// otherwise we're done with this strip so finish it and start
142 			// a new one
143 			else
144 			{
145 				qglEnd();
146 
147 				qglBegin( GL_TRIANGLE_STRIP );
148 				c_begins++;
149 
150 				element( indexes[i + 0] );
151 				element( indexes[i + 1] );
152 				element( indexes[i + 2] );
153 				c_vertexes += 3;
154 
155 				even = qfalse;
156 			}
157 		}
158 
159 		// cache the last three vertices
160 		last[0] = indexes[i + 0];
161 		last[1] = indexes[i + 1];
162 		last[2] = indexes[i + 2];
163 	}
164 
165 	qglEnd();
166 }
167 #endif // USE_OPENGLES
168 
169 
170 /*
171 ==================
172 R_DrawElements
173 
174 Optionally performs our own glDrawElements that looks for strip conditions
175 instead of using the single glDrawElements call that may be inefficient
176 without compiled vertex arrays.
177 ==================
178 */
R_DrawElements(int numIndexes,const glIndex_t * indexes)179 void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
180 #ifdef USE_OPENGLES
181 	qglDrawElements( GL_TRIANGLES,
182 						numIndexes,
183 						GL_INDEX_TYPE,
184 						indexes );
185 		return;
186 #else
187 	int primitives;
188 
189 	primitives = r_primitives->integer;
190 
191 	// default is to use triangles if compiled vertex arrays are present
192 	if ( primitives == 0 ) {
193 		if ( qglLockArraysEXT ) {
194 			primitives = 2;
195 		} else {
196 			primitives = 1;
197 		}
198 	}
199 
200 	if ( primitives == 2 ) {
201 		qglDrawElements( GL_TRIANGLES,
202 						 numIndexes,
203 						 GL_INDEX_TYPE,
204 						 indexes );
205 		return;
206 	}
207 
208 	if ( primitives == 1 ) {
209 		R_DrawStripElements( numIndexes,  indexes, qglArrayElement );
210 		return;
211 	}
212 
213 	if ( primitives == 3 ) {
214 		R_DrawStripElements( numIndexes,  indexes, R_ArrayElementDiscrete );
215 		return;
216 	}
217 
218 	// anything else will cause no drawing
219 #endif
220 }
221 
222 
223 /*
224 =============================================================
225 
226 SURFACE SHADERS
227 
228 =============================================================
229 */
230 
231 shaderCommands_t tess;
232 static qboolean setArraysOnce;
233 
234 /*
235 =================
236 R_BindAnimatedImage
237 
238 =================
239 */
R_BindAnimatedImage(textureBundle_t * bundle)240 void R_BindAnimatedImage( textureBundle_t *bundle ) {
241 	int64_t index;
242 
243 	if ( bundle->isVideoMap ) {
244 		ri.CIN_RunCinematic( bundle->videoMapHandle );
245 		ri.CIN_UploadCinematic( bundle->videoMapHandle );
246 		return;
247 	}
248 
249 	if ( bundle->numImageAnimations <= 1 ) {
250 		if ( bundle->isLightmap && ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) ) {
251 			GL_Bind( tr.whiteImage );
252 		} else {
253 			GL_Bind( bundle->image[0] );
254 		}
255 		return;
256 	}
257 
258 	// it is necessary to do this messy calc to make sure animations line up
259 	// exactly with waveforms of the same frequency
260 	index = tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE;
261 	index >>= FUNCTABLE_SIZE2;
262 
263 	if ( index < 0 ) {
264 		index = 0;  // may happen with shader time offsets
265 	}
266 
267 	// Windows x86 doesn't load renderer DLL with 64 bit modulus
268 	//index %= bundle->numImageAnimations;
269 	while ( index >= bundle->numImageAnimations ) {
270 		index -= bundle->numImageAnimations;
271 	}
272 
273 	if ( bundle->isLightmap && ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) ) {
274 		GL_Bind( tr.whiteImage );
275 	} else {
276 		GL_Bind( bundle->image[ index ] );
277 	}
278 }
279 
280 /*
281 ================
282 DrawTris
283 
284 Draws triangle outlines for debugging
285 ================
286 */
DrawTris(shaderCommands_t * input)287 static void DrawTris( shaderCommands_t *input ) {
288 	GL_Bind( tr.whiteImage );
289 	qglColor3f( 1,1,1 );
290 
291 	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
292 
293 	if ( r_showtris->integer == 1 ) {
294 		qglDepthRange( 0, 0 );
295 	}
296 
297 	qglDisableClientState( GL_COLOR_ARRAY );
298 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
299 
300 	qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); // padded for SIMD
301 
302 	if ( qglLockArraysEXT ) {
303 		qglLockArraysEXT( 0, input->numVertexes );
304 		GLimp_LogComment( "glLockArraysEXT\n" );
305 	}
306 
307 #ifdef USE_OPENGLES
308 	qglDrawElements( GL_LINE_STRIP,
309 					input->numIndexes,
310 					GL_INDEX_TYPE,
311 					input->indexes );
312 #else
313 	R_DrawElements( input->numIndexes, input->indexes );
314 #endif
315 
316 	if ( qglUnlockArraysEXT ) {
317 		qglUnlockArraysEXT();
318 		GLimp_LogComment( "glUnlockArraysEXT\n" );
319 	}
320 	qglDepthRange( 0, 1 );
321 }
322 
323 
324 /*
325 ================
326 DrawNormals
327 
328 Draws vertex normals for debugging
329 ================
330 */
DrawNormals(shaderCommands_t * input)331 static void DrawNormals( shaderCommands_t *input ) {
332 	int i;
333 	vec3_t temp;
334 
335 	GL_Bind( tr.whiteImage );
336 	qglColor3f( 1,1,1 );
337 
338 	if ( r_shownormals->integer == 1 ) {
339 		qglDepthRange( 0, 0 );  // never occluded
340 	}
341 	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
342 
343 #ifdef USE_OPENGLES
344 	vec3_t vtx[2];
345 	//*TODO* save states for texture & color array
346 #else
347 	qglBegin( GL_LINES );
348 #endif
349 	for ( i = 0 ; i < input->numVertexes ; i++ ) {
350 #ifndef USE_OPENGLES
351 		qglVertex3fv( input->xyz[i] );
352 #endif
353 		VectorMA( input->xyz[i], 2, input->normal[i], temp );
354 #ifdef USE_OPENGLES
355 		memcpy(vtx, input->xyz[i], sizeof(GLfloat)*3);
356 		memcpy(vtx+1, temp, sizeof(GLfloat)*3);
357 		qglVertexPointer (3, GL_FLOAT, 16, vtx);
358 		qglDrawArrays(GL_LINES, 0, 2);
359 #else
360 		qglVertex3fv( temp );
361 #endif
362 	}
363 #ifdef USE_OPENGLES
364 	//*TODO* restaure state for texture & color
365 #else
366 	qglEnd();
367 #endif
368 
369 	qglDepthRange( 0, 1 );
370 }
371 
372 /*
373 ==============
374 RB_BeginSurface
375 
376 We must set some things up before beginning any tesselation,
377 because a surface may be forced to perform a RB_End due
378 to overflow.
379 ==============
380 */
RB_BeginSurface(shader_t * shader,int fogNum)381 void RB_BeginSurface( shader_t *shader, int fogNum ) {
382 
383 	shader_t *state = ( shader->remappedShader ) ? shader->remappedShader : shader;
384 
385 	tess.ATI_tess = qfalse;     //----(SA)	added
386 	tess.numIndexes = 0;
387 	tess.numVertexes = 0;
388 	tess.shader = state;
389 	tess.fogNum = fogNum;
390 	tess.dlightBits = 0;        // will be OR'd in by surface functions
391 	tess.xstages = state->stages;
392 	tess.numPasses = state->numUnfoggedPasses;
393 	tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
394 
395 	tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
396 	if ( tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime ) {
397 		tess.shaderTime = tess.shader->clampTime;
398 	}
399 	// done.
400 }
401 
402 /*
403 ===================
404 DrawMultitextured
405 
406 output = t0 * t1 or t0 + t1
407 
408 t0 = most upstream according to spec
409 t1 = most downstream according to spec
410 ===================
411 */
DrawMultitextured(shaderCommands_t * input,int stage)412 static void DrawMultitextured( shaderCommands_t *input, int stage ) {
413 	shaderStage_t   *pStage;
414 
415 	pStage = tess.xstages[stage];
416 
417 	// Ridah
418 	if ( tess.shader->noFog && pStage->isFogged ) {
419 		R_FogOn();
420 	} else if ( tess.shader->noFog && !pStage->isFogged ) {
421 		R_FogOff(); // turn it back off
422 	} else if ( backEnd.projection2D ) {
423 		R_FogOff();
424 	} else {    // make sure it's on
425 		R_FogOn();
426 	}
427 	// done.
428 
429 	GL_State( pStage->stateBits );
430 
431 	// this is an ugly hack to work around a GeForce driver
432 	// bug with multitexture and clip planes
433 #ifndef USE_OPENGLES
434 	if ( backEnd.viewParms.isPortal ) {
435 		qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
436 	}
437 #endif
438 
439 	//
440 	// base
441 	//
442 	GL_SelectTexture( 0 );
443 	qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
444 	R_BindAnimatedImage( &pStage->bundle[0] );
445 
446 	//
447 	// lightmap/secondary pass
448 	//
449 	GL_SelectTexture( 1 );
450 	qglEnable( GL_TEXTURE_2D );
451 	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
452 
453 	if ( r_lightmap->integer ) {
454 		GL_TexEnv( GL_REPLACE );
455 	} else {
456 		GL_TexEnv( tess.shader->multitextureEnv );
457 	}
458 
459 	qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[1] );
460 
461 	R_BindAnimatedImage( &pStage->bundle[1] );
462 
463 	R_DrawElements( input->numIndexes, input->indexes );
464 
465 	//
466 	// disable texturing on TEXTURE1, then select TEXTURE0
467 	//
468 	//qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
469 	qglDisable( GL_TEXTURE_2D );
470 
471 	GL_SelectTexture( 0 );
472 }
473 
474 
475 /*
476 ===================
477 ProjectDlightTexture
478 
479 Perform dynamic lighting with another rendering pass
480 ===================
481 */
ProjectDlightTexture_scalar(void)482 static void ProjectDlightTexture_scalar( void ) {
483 	int		i, l;
484 	vec3_t	origin;
485 	float	*texCoords;
486 	byte	*colors;
487 	byte	clipBits[SHADER_MAX_VERTEXES];
488 	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
489 	byte	colorArray[SHADER_MAX_VERTEXES][4];
490 	glIndex_t	hitIndexes[SHADER_MAX_INDEXES];
491 	int		numIndexes;
492 	float	scale;
493 	float	radius;
494 	vec3_t	floatColor;
495 	float	modulate = 0.0f;
496 
497 	if ( !backEnd.refdef.num_dlights ) {
498 		return;
499 	}
500 
501 	if ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) {  // no dlights for snooper
502 		return;
503 	}
504 
505 	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
506 		dlight_t	*dl;
507 
508 		if ( !( tess.dlightBits & ( 1 << l ) ) ) {
509 			continue;	// this surface definately doesn't have any of this light
510 		}
511 		texCoords = texCoordsArray[0];
512 		colors = colorArray[0];
513 
514 		dl = &backEnd.refdef.dlights[l];
515 		VectorCopy( dl->transformed, origin );
516 		radius = dl->radius;
517 		scale = 1.0f / radius;
518 
519 		if(r_greyscale->integer)
520 		{
521 			float luminance;
522 
523 			luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f;
524 			floatColor[0] = floatColor[1] = floatColor[2] = luminance;
525 		}
526 		else if(r_greyscale->value)
527 		{
528 			float luminance;
529 
530 			luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f;
531 			floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value);
532 			floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value);
533 			floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value);
534 		}
535 		else
536 		{
537 			floatColor[0] = dl->color[0] * 255.0f;
538 			floatColor[1] = dl->color[1] * 255.0f;
539 			floatColor[2] = dl->color[2] * 255.0f;
540 		}
541 
542 		for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
543 			int		clip = 0;
544 			vec3_t	dist;
545 
546 			VectorSubtract( origin, tess.xyz[i], dist );
547 
548 			backEnd.pc.c_dlightVertexes++;
549 
550 			texCoords[0] = 0.5f + dist[0] * scale;
551 			texCoords[1] = 0.5f + dist[1] * scale;
552 
553 			if( !r_dlightBacks->integer &&
554 					// dist . tess.normal[i]
555 					( dist[0] * tess.normal[i][0] +
556 					dist[1] * tess.normal[i][1] +
557 					dist[2] * tess.normal[i][2] ) < 0.0f ) {
558 				clip = 63;
559 			} else {
560 				if ( texCoords[0] < 0.0f ) {
561 					clip |= 1;
562 				} else if ( texCoords[0] > 1.0f ) {
563 					clip |= 2;
564 				}
565 				if ( texCoords[1] < 0.0f ) {
566 					clip |= 4;
567 				} else if ( texCoords[1] > 1.0f ) {
568 					clip |= 8;
569 				}
570 				texCoords[0] = texCoords[0];
571 				texCoords[1] = texCoords[1];
572 
573 				// modulate the strength based on the height and color
574 				if ( dist[2] > radius ) {
575 					clip |= 16;
576 					modulate = 0.0f;
577 				} else if ( dist[2] < -radius ) {
578 					clip |= 32;
579 					modulate = 0.0f;
580 				} else {
581 					dist[2] = Q_fabs(dist[2]);
582 					if ( dist[2] < radius * 0.5f ) {
583 						modulate = 1.0f;
584 					} else {
585 						modulate = 2.0f * (radius - dist[2]) * scale;
586 					}
587 				}
588 			}
589 			clipBits[i] = clip;
590 			colors[0] = ri.ftol(floatColor[0] * modulate);
591 			colors[1] = ri.ftol(floatColor[1] * modulate);
592 			colors[2] = ri.ftol(floatColor[2] * modulate);
593 			colors[3] = 255;
594 		}
595 
596 		// build a list of triangles that need light
597 		numIndexes = 0;
598 		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
599 			int		a, b, c;
600 
601 			a = tess.indexes[i];
602 			b = tess.indexes[i+1];
603 			c = tess.indexes[i+2];
604 			if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
605 				continue;	// not lighted
606 			}
607 			hitIndexes[numIndexes] = a;
608 			hitIndexes[numIndexes+1] = b;
609 			hitIndexes[numIndexes+2] = c;
610 			numIndexes += 3;
611 		}
612 
613 		if ( !numIndexes ) {
614 			continue;
615 		}
616 
617 		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
618 		qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
619 
620 		qglEnableClientState( GL_COLOR_ARRAY );
621 		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
622 
623 		//----(SA) creating dlight shader to allow for special blends or alternate dlight texture
624 		{
625 			shader_t *dls = dl->dlshader;
626 			if ( dls ) {
627 				for ( i = 0; i < dls->numUnfoggedPasses; i++ )
628 				{
629 					shaderStage_t *stage = dls->stages[i];
630 					R_BindAnimatedImage( &dls->stages[i]->bundle[0] );
631 					GL_State( stage->stateBits | GLS_DEPTHFUNC_EQUAL );
632 					R_DrawElements( numIndexes, hitIndexes );
633 					backEnd.pc.c_totalIndexes += numIndexes;
634 					backEnd.pc.c_dlightIndexes += numIndexes;
635 				}
636 
637 			} else
638 			{
639 				R_FogOff();
640 
641 				GL_Bind( tr.dlightImage );
642 				// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
643 				// where they aren't rendered
644 				GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
645 				R_DrawElements( numIndexes, hitIndexes );
646 				backEnd.pc.c_totalIndexes += numIndexes;
647 				backEnd.pc.c_dlightIndexes += numIndexes;
648 
649 				// Ridah, overdraw lights several times, rather than sending
650 				//	multiple lights through
651 				for ( i = 0; i < dl->overdraw; i++ ) {
652 					R_DrawElements( numIndexes, hitIndexes );
653 					backEnd.pc.c_totalIndexes += numIndexes;
654 					backEnd.pc.c_dlightIndexes += numIndexes;
655 				}
656 
657 				R_FogOn();
658 			}
659 		}
660 	}
661 }
662 
ProjectDlightTexture(void)663 static void ProjectDlightTexture( void ) {
664 #if idppc_altivec
665 	if (com_altivec->integer) {
666 		// must be in a separate translation unit or G3 systems will crash.
667 		ProjectDlightTexture_altivec();
668 		return;
669 	}
670 #endif
671 	ProjectDlightTexture_scalar();
672 }
673 
674 
675 /*
676 ===================
677 RB_FogPass
678 
679 Blends a fog texture on top of everything else
680 ===================
681 */
RB_FogPass(void)682 static void RB_FogPass( void ) {
683 	fog_t       *fog;
684 	int i;
685 
686 	if ( tr.refdef.rdflags & RDF_SNOOPERVIEW ) { // no fog pass in snooper
687 		return;
688 	}
689 
690 	qglEnableClientState( GL_COLOR_ARRAY );
691 	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
692 
693 	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
694 	qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
695 
696 	fog = tr.world->fogs + tess.fogNum;
697 
698 	for ( i = 0; i < tess.numVertexes; i++ ) {
699 		*( int * )&tess.svars.colors[i] = fog->colorInt;
700 	}
701 
702 	RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] );
703 
704 	GL_Bind( tr.fogImage );
705 
706 	if ( tess.shader->fogPass == FP_EQUAL ) {
707 		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
708 	} else {
709 		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
710 	}
711 
712 	R_DrawElements( tess.numIndexes, tess.indexes );
713 }
714 
715 /*
716 ===============
717 ComputeColors
718 ===============
719 */
ComputeColors(shaderStage_t * pStage)720 static void ComputeColors( shaderStage_t *pStage ) {
721 	int i;
722 
723 	//
724 	// rgbGen
725 	//
726 	switch ( pStage->rgbGen )
727 	{
728 	case CGEN_IDENTITY:
729 		memset( tess.svars.colors, 0xff, tess.numVertexes * 4 );
730 		break;
731 	default:
732 	case CGEN_IDENTITY_LIGHTING:
733 		memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 );
734 		break;
735 	case CGEN_LIGHTING_DIFFUSE:
736 		RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
737 		break;
738 	case CGEN_EXACT_VERTEX:
739 		memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
740 		break;
741 	case CGEN_CONST:
742 		for ( i = 0; i < tess.numVertexes; i++ ) {
743 			*(int *)tess.svars.colors[i] = *(int *)pStage->constantColor;
744 		}
745 		break;
746 	case CGEN_VERTEX:
747 		if ( tr.identityLight == 1 ) {
748 			memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) );
749 		} else
750 		{
751 			for ( i = 0; i < tess.numVertexes; i++ )
752 			{
753 				tess.svars.colors[i][0] = tess.vertexColors[i][0] * tr.identityLight;
754 				tess.svars.colors[i][1] = tess.vertexColors[i][1] * tr.identityLight;
755 				tess.svars.colors[i][2] = tess.vertexColors[i][2] * tr.identityLight;
756 				tess.svars.colors[i][3] = tess.vertexColors[i][3];
757 			}
758 		}
759 		break;
760 	case CGEN_ONE_MINUS_VERTEX:
761 		if ( tr.identityLight == 1 ) {
762 			for ( i = 0; i < tess.numVertexes; i++ )
763 			{
764 				tess.svars.colors[i][0] = 255 - tess.vertexColors[i][0];
765 				tess.svars.colors[i][1] = 255 - tess.vertexColors[i][1];
766 				tess.svars.colors[i][2] = 255 - tess.vertexColors[i][2];
767 			}
768 		} else
769 		{
770 			for ( i = 0; i < tess.numVertexes; i++ )
771 			{
772 				tess.svars.colors[i][0] = ( 255 - tess.vertexColors[i][0] ) * tr.identityLight;
773 				tess.svars.colors[i][1] = ( 255 - tess.vertexColors[i][1] ) * tr.identityLight;
774 				tess.svars.colors[i][2] = ( 255 - tess.vertexColors[i][2] ) * tr.identityLight;
775 			}
776 		}
777 		break;
778 	case CGEN_FOG:
779 	{
780 		fog_t       *fog;
781 
782 		fog = tr.world->fogs + tess.fogNum;
783 
784 		for ( i = 0; i < tess.numVertexes; i++ ) {
785 			*( int * )&tess.svars.colors[i] = fog->colorInt;
786 		}
787 	}
788 	break;
789 	case CGEN_WAVEFORM:
790 		RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess.svars.colors );
791 		break;
792 	case CGEN_ENTITY:
793 		RB_CalcColorFromEntity( ( unsigned char * ) tess.svars.colors );
794 		break;
795 	case CGEN_ONE_MINUS_ENTITY:
796 		RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
797 		break;
798 	}
799 
800 	//
801 	// alphaGen
802 	//
803 	switch ( pStage->alphaGen )
804 	{
805 	case AGEN_SKIP:
806 		break;
807 	case AGEN_IDENTITY:
808 		if ( pStage->rgbGen != CGEN_IDENTITY ) {
809 			if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) ||
810 				 pStage->rgbGen != CGEN_VERTEX ) {
811 				for ( i = 0; i < tess.numVertexes; i++ ) {
812 					tess.svars.colors[i][3] = 0xff;
813 				}
814 			}
815 		}
816 		break;
817 	case AGEN_CONST:
818 		if ( pStage->rgbGen != CGEN_CONST ) {
819 			for ( i = 0; i < tess.numVertexes; i++ ) {
820 				tess.svars.colors[i][3] = pStage->constantColor[3];
821 			}
822 		}
823 		break;
824 	case AGEN_WAVEFORM:
825 		RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess.svars.colors );
826 		break;
827 	case AGEN_LIGHTING_SPECULAR:
828 		RB_CalcSpecularAlpha( ( unsigned char * ) tess.svars.colors );
829 		break;
830 	case AGEN_ENTITY:
831 		RB_CalcAlphaFromEntity( ( unsigned char * ) tess.svars.colors );
832 		break;
833 	case AGEN_ONE_MINUS_ENTITY:
834 		RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess.svars.colors );
835 		break;
836 		// Ridah
837 	case AGEN_NORMALZFADE:
838 	{
839 		float alpha, range, lowest, highest, dot;
840 		vec3_t worldUp;
841 		qboolean zombieEffect = qfalse;
842 
843 		if ( VectorCompare( backEnd.currentEntity->e.fireRiseDir, vec3_origin ) ) {
844 			VectorSet( backEnd.currentEntity->e.fireRiseDir, 0, 0, 1 );
845 		}
846 
847 		if ( backEnd.currentEntity->e.hModel ) {    // world surfaces dont have an axis
848 			VectorRotate( backEnd.currentEntity->e.fireRiseDir, backEnd.currentEntity->e.axis, worldUp );
849 		} else {
850 			VectorCopy( backEnd.currentEntity->e.fireRiseDir, worldUp );
851 		}
852 
853 		lowest = pStage->zFadeBounds[0];
854 		if ( lowest == -1000 ) {    // use entity alpha
855 			lowest = backEnd.currentEntity->e.shaderTime;
856 			zombieEffect = qtrue;
857 		}
858 		highest = pStage->zFadeBounds[1];
859 		if ( highest == -1000 ) {   // use entity alpha
860 			highest = backEnd.currentEntity->e.shaderTime;
861 			zombieEffect = qtrue;
862 		}
863 		range = highest - lowest;
864 		for ( i = 0; i < tess.numVertexes; i++ ) {
865 			dot = DotProduct( tess.normal[i], worldUp );
866 
867 			// special handling for Zombie fade effect
868 			if ( zombieEffect ) {
869 				alpha = (float)backEnd.currentEntity->e.shaderRGBA[3] * ( dot + 1.0 ) / 2.0;
870 				alpha += ( 2.0 * (float)backEnd.currentEntity->e.shaderRGBA[3] ) * ( 1.0 - ( dot + 1.0 ) / 2.0 );
871 				if ( alpha > 255.0 ) {
872 					alpha = 255.0;
873 				} else if ( alpha < 0.0 ) {
874 					alpha = 0.0;
875 				}
876 				tess.svars.colors[i][3] = (byte)( alpha );
877 				continue;
878 			}
879 
880 			if ( dot < highest ) {
881 				if ( dot > lowest ) {
882 					if ( dot < lowest + range / 2 ) {
883 						alpha = ( (float)pStage->constantColor[3] * ( ( dot - lowest ) / ( range / 2 ) ) );
884 					} else {
885 						alpha = ( (float)pStage->constantColor[3] * ( 1.0 - ( ( dot - lowest - range / 2 ) / ( range / 2 ) ) ) );
886 					}
887 					if ( alpha > 255.0 ) {
888 						alpha = 255.0;
889 					} else if ( alpha < 0.0 ) {
890 						alpha = 0.0;
891 					}
892 
893 					// finally, scale according to the entity's alpha
894 					if ( backEnd.currentEntity->e.hModel ) {
895 						alpha *= (float)backEnd.currentEntity->e.shaderRGBA[3] / 255.0;
896 					}
897 
898 					tess.svars.colors[i][3] = (byte)( alpha );
899 				} else {
900 					tess.svars.colors[i][3] = 0;
901 				}
902 			} else {
903 				tess.svars.colors[i][3] = 0;
904 			}
905 		}
906 	}
907 	break;
908 		// done.
909 	case AGEN_VERTEX:
910 		if ( pStage->rgbGen != CGEN_VERTEX ) {
911 			for ( i = 0; i < tess.numVertexes; i++ ) {
912 				tess.svars.colors[i][3] = tess.vertexColors[i][3];
913 			}
914 		}
915 		break;
916 	case AGEN_ONE_MINUS_VERTEX:
917 		for ( i = 0; i < tess.numVertexes; i++ )
918 		{
919 			tess.svars.colors[i][3] = 255 - tess.vertexColors[i][3];
920 		}
921 		break;
922 	case AGEN_PORTAL:
923 	{
924 		unsigned char alpha;
925 
926 		for ( i = 0; i < tess.numVertexes; i++ )
927 		{
928 			float len;
929 			vec3_t v;
930 
931 			VectorSubtract( tess.xyz[i], backEnd.viewParms.or.origin, v );
932 			len = VectorLength( v );
933 
934 			len /= tess.shader->portalRange;
935 
936 			if ( len < 0 ) {
937 				alpha = 0;
938 			} else if ( len > 1 )   {
939 				alpha = 0xff;
940 			} else
941 			{
942 				alpha = len * 0xff;
943 			}
944 
945 			tess.svars.colors[i][3] = alpha;
946 		}
947 	}
948 	break;
949 	}
950 
951 	//
952 	// fog adjustment for colors to fade out as fog increases
953 	//
954 	if ( tess.fogNum ) {
955 		switch ( pStage->adjustColorsForFog )
956 		{
957 		case ACFF_MODULATE_RGB:
958 			RB_CalcModulateColorsByFog( ( unsigned char * ) tess.svars.colors );
959 			break;
960 		case ACFF_MODULATE_ALPHA:
961 			RB_CalcModulateAlphasByFog( ( unsigned char * ) tess.svars.colors );
962 			break;
963 		case ACFF_MODULATE_RGBA:
964 			RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess.svars.colors );
965 			break;
966 		case ACFF_NONE:
967 			break;
968 		}
969 	}
970 
971 	// if in greyscale rendering mode turn all color values into greyscale.
972 	if(r_greyscale->integer)
973 	{
974 		int scale;
975 		for(i = 0; i < tess.numVertexes; i++)
976 		{
977 			scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]);
978 			tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale;
979 		}
980 	}
981 	else if(r_greyscale->value)
982 	{
983 		float scale;
984 
985 		for(i = 0; i < tess.numVertexes; i++)
986 		{
987 			scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]);
988 			tess.svars.colors[i][0] = LERP(tess.svars.colors[i][0], scale, r_greyscale->value);
989 			tess.svars.colors[i][1] = LERP(tess.svars.colors[i][1], scale, r_greyscale->value);
990 			tess.svars.colors[i][2] = LERP(tess.svars.colors[i][2], scale, r_greyscale->value);
991 		}
992 	}
993 }
994 
995 /*
996 ===============
997 ComputeTexCoords
998 ===============
999 */
ComputeTexCoords(shaderStage_t * pStage)1000 static void ComputeTexCoords( shaderStage_t *pStage ) {
1001 	int i;
1002 	int b;
1003 
1004 	for ( b = 0; b < NUM_TEXTURE_BUNDLES; b++ ) {
1005 		int tm;
1006 
1007 		//
1008 		// generate the texture coordinates
1009 		//
1010 		switch ( pStage->bundle[b].tcGen )
1011 		{
1012 		case TCGEN_IDENTITY:
1013 			memset( tess.svars.texcoords[b], 0, sizeof( float ) * 2 * tess.numVertexes );
1014 			break;
1015 		case TCGEN_TEXTURE:
1016 			for ( i = 0 ; i < tess.numVertexes ; i++ ) {
1017 				tess.svars.texcoords[b][i][0] = tess.texCoords[i][0][0];
1018 				tess.svars.texcoords[b][i][1] = tess.texCoords[i][0][1];
1019 			}
1020 			break;
1021 		case TCGEN_LIGHTMAP:
1022 			for ( i = 0 ; i < tess.numVertexes ; i++ ) {
1023 				tess.svars.texcoords[b][i][0] = tess.texCoords[i][1][0];
1024 				tess.svars.texcoords[b][i][1] = tess.texCoords[i][1][1];
1025 			}
1026 			break;
1027 		case TCGEN_VECTOR:
1028 			for ( i = 0 ; i < tess.numVertexes ; i++ ) {
1029 				tess.svars.texcoords[b][i][0] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[0] );
1030 				tess.svars.texcoords[b][i][1] = DotProduct( tess.xyz[i], pStage->bundle[b].tcGenVectors[1] );
1031 			}
1032 			break;
1033 		case TCGEN_FOG:
1034 			RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[b] );
1035 			break;
1036 		case TCGEN_ENVIRONMENT_MAPPED:
1037 			RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] );
1038 			break;
1039 		case TCGEN_FIRERISEENV_MAPPED:
1040 			RB_CalcFireRiseEnvTexCoords( ( float * ) tess.svars.texcoords[b] );
1041 			break;
1042 		case TCGEN_BAD:
1043 			return;
1044 		}
1045 
1046 		//
1047 		// alter texture coordinates
1048 		//
1049 		for ( tm = 0; tm < pStage->bundle[b].numTexMods ; tm++ ) {
1050 			switch ( pStage->bundle[b].texMods[tm].type )
1051 			{
1052 			case TMOD_NONE:
1053 				tm = TR_MAX_TEXMODS;        // break out of for loop
1054 				break;
1055 
1056 			case TMOD_SWAP:
1057 				RB_CalcSwapTexCoords( ( float * ) tess.svars.texcoords[b] );
1058 				break;
1059 
1060 			case TMOD_TURBULENT:
1061 				RB_CalcTurbulentTexCoords( &pStage->bundle[b].texMods[tm].wave,
1062 										   ( float * ) tess.svars.texcoords[b] );
1063 				break;
1064 
1065 			case TMOD_ENTITY_TRANSLATE:
1066 				RB_CalcScrollTexCoords( backEnd.currentEntity->e.shaderTexCoord,
1067 										( float * ) tess.svars.texcoords[b] );
1068 				break;
1069 
1070 			case TMOD_SCROLL:
1071 				RB_CalcScrollTexCoords( pStage->bundle[b].texMods[tm].scroll,
1072 										( float * ) tess.svars.texcoords[b] );
1073 				break;
1074 
1075 			case TMOD_SCALE:
1076 				RB_CalcScaleTexCoords( pStage->bundle[b].texMods[tm].scale,
1077 									   ( float * ) tess.svars.texcoords[b] );
1078 				break;
1079 
1080 			case TMOD_STRETCH:
1081 				RB_CalcStretchTexCoords( &pStage->bundle[b].texMods[tm].wave,
1082 										 ( float * ) tess.svars.texcoords[b] );
1083 				break;
1084 
1085 			case TMOD_TRANSFORM:
1086 				RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm],
1087 										   ( float * ) tess.svars.texcoords[b] );
1088 				break;
1089 
1090 			case TMOD_ROTATE:
1091 				RB_CalcRotateTexCoords( pStage->bundle[b].texMods[tm].rotateSpeed,
1092 										( float * ) tess.svars.texcoords[b] );
1093 				break;
1094 
1095 			default:
1096 				ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", pStage->bundle[b].texMods[tm].type, tess.shader->name );
1097 				break;
1098 			}
1099 		}
1100 	}
1101 }
1102 
1103 
1104 
1105 extern void R_Fog( glfog_t *curfog );
1106 
1107 /*
1108 ==============
1109 SetIteratorFog
1110 	set the fog parameters for this pass
1111 ==============
1112 */
SetIteratorFog(void)1113 void SetIteratorFog( void ) {
1114 	// changed for problem when you start the game with r_fastsky set to '1'
1115 //	if(r_fastsky->integer || backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) {
1116 	if ( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) {
1117 		R_FogOff();
1118 		return;
1119 	}
1120 
1121 	if ( backEnd.refdef.rdflags & RDF_DRAWINGSKY ) {
1122 		if ( glfogsettings[FOG_SKY].registered ) {
1123 			R_Fog( &glfogsettings[FOG_SKY] );
1124 		} else {
1125 			R_FogOff();
1126 		}
1127 
1128 		return;
1129 	}
1130 
1131 	if ( skyboxportal && backEnd.refdef.rdflags & RDF_SKYBOXPORTAL ) {
1132 		if ( glfogsettings[FOG_PORTALVIEW].registered ) {
1133 			R_Fog( &glfogsettings[FOG_PORTALVIEW] );
1134 		} else {
1135 			R_FogOff();
1136 		}
1137 	} else {
1138 		if ( glfogNum > FOG_NONE ) {
1139 			R_Fog( &glfogsettings[FOG_CURRENT] );
1140 		} else {
1141 			R_FogOff();
1142 		}
1143 	}
1144 }
1145 
1146 
1147 /*
1148 ** RB_IterateStagesGeneric
1149 */
RB_IterateStagesGeneric(shaderCommands_t * input)1150 static void RB_IterateStagesGeneric( shaderCommands_t *input ) {
1151 	int stage;
1152 
1153 	for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
1154 	{
1155 		shaderStage_t *pStage = tess.xstages[stage];
1156 
1157 		if ( !pStage ) {
1158 			break;
1159 		}
1160 
1161 		ComputeColors( pStage );
1162 		ComputeTexCoords( pStage );
1163 
1164 		if ( !setArraysOnce ) {
1165 			qglEnableClientState( GL_COLOR_ARRAY );
1166 			qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors );
1167 		}
1168 
1169 		//
1170 		// do multitexture
1171 		//
1172 		if ( pStage->bundle[1].image[0] != 0 ) {
1173 			DrawMultitextured( input, stage );
1174 		} else
1175 		{
1176 			int fadeStart, fadeEnd;
1177 
1178 			if ( !setArraysOnce ) {
1179 				qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] );
1180 			}
1181 
1182 			//
1183 			// set state
1184 			//
1185 			R_BindAnimatedImage( &pStage->bundle[0] );
1186 
1187 			// Ridah, per stage fogging (detail textures)
1188 			if ( tess.shader->noFog && pStage->isFogged ) {
1189 				R_FogOn();
1190 			} else if ( tess.shader->noFog && !pStage->isFogged ) {
1191 				R_FogOff(); // turn it back off
1192 			} else if ( backEnd.projection2D ) {
1193 				R_FogOff();
1194 			} else {    // make sure it's on
1195 				R_FogOn();
1196 			}
1197 			// done.
1198 
1199 			//----(SA)	fading model stuff
1200 			fadeStart = backEnd.currentEntity->e.fadeStartTime;
1201 
1202 			if ( fadeStart ) {
1203 				fadeEnd = backEnd.currentEntity->e.fadeEndTime;
1204 				if ( fadeStart > tr.refdef.time ) {       // has not started to fade yet
1205 					GL_State( pStage->stateBits );
1206 				} else
1207 				{
1208 					int i;
1209 					unsigned int tempState;
1210 					float alphaval;
1211 
1212 					if ( fadeEnd < tr.refdef.time ) {     // entity faded out completely
1213 						continue;
1214 					}
1215 
1216 					alphaval = (float)( fadeEnd - tr.refdef.time ) / (float)( fadeEnd - fadeStart );
1217 
1218 					tempState = pStage->stateBits;
1219 					// remove the current blend, and don't write to Z buffer
1220 					tempState &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_DEPTHMASK_TRUE );
1221 					// set the blend to src_alpha, dst_one_minus_src_alpha
1222 					tempState |= ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
1223 					GL_State( tempState );
1224 					GL_Cull( CT_FRONT_SIDED );
1225 					// modulate the alpha component of each vertex in the render list
1226 					for ( i = 0; i < tess.numVertexes; i++ ) {
1227 						tess.svars.colors[i][0] *= alphaval;
1228 						tess.svars.colors[i][1] *= alphaval;
1229 						tess.svars.colors[i][2] *= alphaval;
1230 						tess.svars.colors[i][3] *= alphaval;
1231 					}
1232 				}
1233 			} else {
1234 				GL_State( pStage->stateBits );
1235 			}
1236 			//----(SA)	end
1237 
1238 			//
1239 			// draw
1240 			//
1241 			R_DrawElements( input->numIndexes, input->indexes );
1242 		}
1243 		// allow skipping out to show just lightmaps during development
1244 		if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) {
1245 			break;
1246 		}
1247 	}
1248 }
1249 
1250 
1251 /*
1252 ** RB_StageIteratorGeneric
1253 */
RB_StageIteratorGeneric(void)1254 void RB_StageIteratorGeneric( void ) {
1255 	shaderCommands_t *input;
1256 	shader_t		*shader;
1257 
1258 	input = &tess;
1259 	shader = input->shader;
1260 
1261 	RB_DeformTessGeometry();
1262 
1263 	//
1264 	// log this call
1265 	//
1266 	if ( r_logFile->integer ) {
1267 		// don't just call LogComment, or we will get
1268 		// a call to va() every frame!
1269 		GLimp_LogComment( va( "--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name ) );
1270 	}
1271 
1272 	// set GL fog
1273 	SetIteratorFog();
1274 
1275 #ifndef USE_OPENGLES
1276 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1277 		// RF< so we can send the normals as an array
1278 		qglEnableClientState( GL_NORMAL_ARRAY );
1279 		qglEnable( GL_PN_TRIANGLES_ATI ); // ATI PN-Triangles extension
1280 	}
1281 #endif
1282 
1283 	//
1284 	// set face culling appropriately
1285 	//
1286 	GL_Cull( shader->cullType );
1287 
1288 	// set polygon offset if necessary
1289 	if ( shader->polygonOffset ) {
1290 		qglEnable( GL_POLYGON_OFFSET_FILL );
1291 		qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value );
1292 	}
1293 
1294 	//
1295 	// if there is only a single pass then we can enable color
1296 	// and texture arrays before we compile, otherwise we need
1297 	// to avoid compiling those arrays since they will change
1298 	// during multipass rendering
1299 	//
1300 	if ( tess.numPasses > 1 || shader->multitextureEnv ) {
1301 		setArraysOnce = qfalse;
1302 		qglDisableClientState( GL_COLOR_ARRAY );
1303 		qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1304 	} else
1305 	{
1306 		setArraysOnce = qtrue;
1307 
1308 		qglEnableClientState( GL_COLOR_ARRAY );
1309 		qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
1310 
1311 		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1312 		qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
1313 	}
1314 
1315 	// RF, send normals only if required
1316 	// This must be done first, since we can't change the arrays once they have been
1317 	// locked
1318 #ifndef USE_OPENGLES
1319 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1320 		qglNormalPointer( GL_FLOAT, 16, input->normal );
1321 	}
1322 #endif
1323 
1324 	//
1325 	// lock XYZ
1326 	//
1327 	qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); // padded for SIMD
1328 	if ( qglLockArraysEXT ) {
1329 		qglLockArraysEXT( 0, input->numVertexes );
1330 		GLimp_LogComment( "glLockArraysEXT\n" );
1331 	}
1332 
1333 	//
1334 	// enable color and texcoord arrays after the lock if necessary
1335 	//
1336 	if ( !setArraysOnce ) {
1337 		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1338 		qglEnableClientState( GL_COLOR_ARRAY );
1339 	}
1340 
1341 	//
1342 	// call shader function
1343 	//
1344 	RB_IterateStagesGeneric( input );
1345 
1346 	//
1347 	// now do any dynamic lighting needed
1348 	//
1349 	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE
1350 		 && !( tess.shader->surfaceFlags & ( SURF_NODLIGHT | SURF_SKY ) ) ) {
1351 		ProjectDlightTexture();
1352 	}
1353 
1354 	//
1355 	// now do fog
1356 	//
1357 	if ( tess.fogNum && tess.shader->fogPass ) {
1358 		RB_FogPass();
1359 	}
1360 
1361 	//
1362 	// unlock arrays
1363 	//
1364 	if ( qglUnlockArraysEXT ) {
1365 		qglUnlockArraysEXT();
1366 		GLimp_LogComment( "glUnlockArraysEXT\n" );
1367 	}
1368 
1369 	//
1370 	// reset polygon offset
1371 	//
1372 	if ( shader->polygonOffset ) {
1373 		qglDisable( GL_POLYGON_OFFSET_FILL );
1374 	}
1375 
1376 	// turn truform back off
1377 #ifndef USE_OPENGLES
1378 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1379 		qglDisable( GL_PN_TRIANGLES_ATI );    // ATI PN-Triangles extension
1380 		qglDisableClientState( GL_NORMAL_ARRAY );
1381 	}
1382 #endif
1383 }
1384 
1385 
1386 /*
1387 ** RB_StageIteratorVertexLitTexture
1388 */
RB_StageIteratorVertexLitTexture(void)1389 void RB_StageIteratorVertexLitTexture( void ) {
1390 	shaderCommands_t *input;
1391 	shader_t        *shader;
1392 
1393 	input = &tess;
1394 
1395 	shader = input->shader;
1396 
1397 	//
1398 	// compute colors
1399 	//
1400 	RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors );
1401 
1402 	//
1403 	// log this call
1404 	//
1405 	if ( r_logFile->integer ) {
1406 		// don't just call LogComment, or we will get
1407 		// a call to va() every frame!
1408 		GLimp_LogComment( va( "--- RB_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess.shader->name ) );
1409 	}
1410 
1411 
1412 	// set GL fog
1413 	SetIteratorFog();
1414 
1415 	//
1416 	// set face culling appropriately
1417 	//
1418 	GL_Cull( shader->cullType );
1419 
1420 	//
1421 	// set arrays and lock
1422 	//
1423 	qglEnableClientState( GL_COLOR_ARRAY );
1424 	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1425 
1426 #ifndef USE_OPENGLES
1427 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1428 		qglEnable( GL_PN_TRIANGLES_ATI ); // ATI PN-Triangles extension
1429 		qglEnableClientState( GL_NORMAL_ARRAY );         // RF< so we can send the normals as an array
1430 		qglNormalPointer( GL_FLOAT, 16, input->normal );
1431 	}
1432 #endif
1433 
1434 	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors );
1435 	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );
1436 	qglVertexPointer( 3, GL_FLOAT, 16, input->xyz );
1437 
1438 
1439 	if ( qglLockArraysEXT ) {
1440 		qglLockArraysEXT( 0, input->numVertexes );
1441 		GLimp_LogComment( "glLockArraysEXT\n" );
1442 	}
1443 
1444 	//
1445 	// call special shade routine
1446 	//
1447 	R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
1448 	GL_State( tess.xstages[0]->stateBits );
1449 	R_DrawElements( input->numIndexes, input->indexes );
1450 
1451 	//
1452 	// now do any dynamic lighting needed
1453 	//
1454 	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
1455 		ProjectDlightTexture();
1456 	}
1457 
1458 	//
1459 	// now do fog
1460 	//
1461 	if ( tess.fogNum && tess.shader->fogPass ) {
1462 		RB_FogPass();
1463 	}
1464 
1465 	//
1466 	// unlock arrays
1467 	//
1468 	if ( qglUnlockArraysEXT ) {
1469 		qglUnlockArraysEXT();
1470 		GLimp_LogComment( "glUnlockArraysEXT\n" );
1471 	}
1472 
1473 #ifndef USE_OPENGLES
1474 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1475 		qglDisable( GL_PN_TRIANGLES_ATI );    // ATI PN-Triangles extension
1476 	}
1477 #endif
1478 }
1479 
1480 //define	REPLACE_MODE
1481 
RB_StageIteratorLightmappedMultitexture(void)1482 void RB_StageIteratorLightmappedMultitexture( void ) {
1483 	shaderCommands_t *input;
1484 	shader_t		*shader;
1485 
1486 	input = &tess;
1487 	shader = input->shader;
1488 
1489 	//
1490 	// log this call
1491 	//
1492 	if ( r_logFile->integer ) {
1493 		// don't just call LogComment, or we will get
1494 		// a call to va() every frame!
1495 		GLimp_LogComment( va( "--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name ) );
1496 	}
1497 
1498 	// set GL fog
1499 	SetIteratorFog();
1500 
1501 	//
1502 	// set face culling appropriately
1503 	//
1504 	GL_Cull( shader->cullType );
1505 
1506 	//
1507 	// set color, pointers, and lock
1508 	//
1509 	GL_State( GLS_DEFAULT );
1510 	qglVertexPointer( 3, GL_FLOAT, 16, input->xyz );
1511 
1512 #ifndef USE_OPENGLES
1513 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1514 		qglEnable( GL_PN_TRIANGLES_ATI ); // ATI PN-Triangles extension
1515 		qglNormalPointer( GL_FLOAT, 16, input->normal );
1516 	}
1517 #endif
1518 
1519 #ifdef REPLACE_MODE
1520 	qglDisableClientState( GL_COLOR_ARRAY );
1521 	qglColor3f( 1, 1, 1 );
1522 	qglShadeModel( GL_FLAT );
1523 #else
1524 	qglEnableClientState( GL_COLOR_ARRAY );
1525 	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 );
1526 #endif
1527 
1528 	//
1529 	// select base stage
1530 	//
1531 	GL_SelectTexture( 0 );
1532 
1533 	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1534 	R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
1535 	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );
1536 
1537 	//
1538 	// configure second stage
1539 	//
1540 	GL_SelectTexture( 1 );
1541 	qglEnable( GL_TEXTURE_2D );
1542 	if ( r_lightmap->integer ) {
1543 		GL_TexEnv( GL_REPLACE );
1544 	} else {
1545 		GL_TexEnv( GL_MODULATE );
1546 	}
1547 
1548 //----(SA)	modified for snooper
1549 	if ( tess.xstages[0]->bundle[1].isLightmap && ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) ) {
1550 		GL_Bind( tr.whiteImage );
1551 	} else {
1552 		R_BindAnimatedImage( &tess.xstages[0]->bundle[1] );
1553 	}
1554 
1555 	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1556 	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] );
1557 
1558 	//
1559 	// lock arrays
1560 	//
1561 	if ( qglLockArraysEXT ) {
1562 		qglLockArraysEXT( 0, input->numVertexes );
1563 		GLimp_LogComment( "glLockArraysEXT\n" );
1564 	}
1565 
1566 	R_DrawElements( input->numIndexes, input->indexes );
1567 
1568 	//
1569 	// disable texturing on TEXTURE1, then select TEXTURE0
1570 	//
1571 	qglDisable( GL_TEXTURE_2D );
1572 	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1573 
1574 	GL_SelectTexture( 0 );
1575 #ifdef REPLACE_MODE
1576 	GL_TexEnv( GL_MODULATE );
1577 	qglShadeModel( GL_SMOOTH );
1578 #endif
1579 
1580 	//
1581 	// now do any dynamic lighting needed
1582 	//
1583 	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
1584 		ProjectDlightTexture();
1585 	}
1586 
1587 	//
1588 	// now do fog
1589 	//
1590 	if ( tess.fogNum && tess.shader->fogPass ) {
1591 		RB_FogPass();
1592 	}
1593 
1594 	//
1595 	// unlock arrays
1596 	//
1597 	if ( qglUnlockArraysEXT ) {
1598 		qglUnlockArraysEXT();
1599 		GLimp_LogComment( "glUnlockArraysEXT\n" );
1600 	}
1601 
1602 #ifndef USE_OPENGLES
1603 	if ( qglPNTrianglesiATI && tess.ATI_tess ) {
1604 		qglDisable( GL_PN_TRIANGLES_ATI );    // ATI PN-Triangles extension
1605 	}
1606 #endif
1607 }
1608 
1609 /*
1610 ** RB_EndSurface
1611 */
RB_EndSurface(void)1612 void RB_EndSurface( void ) {
1613 	shaderCommands_t *input;
1614 
1615 	input = &tess;
1616 
1617 	if ( input->numIndexes == 0 ) {
1618 		return;
1619 	}
1620 
1621 	if ( input->indexes[SHADER_MAX_INDEXES - 1] != 0 ) {
1622 		ri.Error( ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit" );
1623 	}
1624 	if ( input->xyz[SHADER_MAX_VERTEXES - 1][0] != 0 ) {
1625 		ri.Error( ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit" );
1626 	}
1627 
1628 	if ( tess.shader == tr.shadowShader ) {
1629 		RB_ShadowTessEnd();
1630 		return;
1631 	}
1632 
1633 	// for debugging of sort order issues, stop rendering after a given sort value
1634 	if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) {
1635 		return;
1636 	}
1637 
1638 	if ( skyboxportal ) {
1639 		// world
1640 		if ( !( backEnd.refdef.rdflags & RDF_SKYBOXPORTAL ) ) {
1641 			if ( tess.currentStageIteratorFunc == RB_StageIteratorSky ) {  // don't process these tris at all
1642 				return;
1643 			}
1644 		}
1645 		// portal sky
1646 		else {
1647 			if ( !drawskyboxportal ) {
1648 				if ( !( tess.currentStageIteratorFunc == RB_StageIteratorSky ) ) {  // /only/ process sky tris
1649 					return;
1650 				}
1651 			}
1652 		}
1653 	}
1654 
1655 	//
1656 	// update performance counters
1657 	//
1658 	backEnd.pc.c_shaders++;
1659 	backEnd.pc.c_vertexes += tess.numVertexes;
1660 	backEnd.pc.c_indexes += tess.numIndexes;
1661 	backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses;
1662 
1663 	//
1664 	// call off to shader specific tess end function
1665 	//
1666 	tess.currentStageIteratorFunc();
1667 
1668 	//
1669 	// draw debugging stuff
1670 	//
1671 	if ( r_showtris->integer ) {
1672 		DrawTris( input );
1673 	}
1674 	if ( r_shownormals->integer ) {
1675 		DrawNormals( input );
1676 	}
1677 
1678 
1679 	// clear shader so we can tell we don't have any unclosed surfaces
1680 	tess.numIndexes = 0;
1681 
1682 	GLimp_LogComment( "----------\n" );
1683 }
1684 
1685