tr_shade.c 27 KB
Newer Older
Rinnegatamante's avatar
Rinnegatamante committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.

This file is part of Quake III Arena source code.

Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.

Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/
// tr_shade.c

#include "tr_local.h" 

/*

  THIS ENTIRE FILE IS BACK END

  This file deals with applying shaders to surface data in the tess struct.
*/

/*
==================
R_DrawElements

Optionally performs our own glDrawElements that looks for strip conditions
instead of using the single glDrawElements call that may be inefficient
without compiled vertex arrays.
==================
*/
static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
Rinnegatamante's avatar
Rinnegatamante committed
43
	vglIndexPointerMapped(indexes);
Rinnegatamante's avatar
Rinnegatamante committed
44
	vglDrawObjects(GL_TRIANGLES, numIndexes, GL_TRUE);
Rinnegatamante's avatar
Rinnegatamante committed
45
46
47
48
49
50
51
52
53
54
55
}


/*
=============================================================

SURFACE SHADERS

=============================================================
*/

Rinnegatamante's avatar
Rinnegatamante committed
56
shaderCommands_t	*tess;
Rinnegatamante's avatar
Rinnegatamante committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
static qboolean	setArraysOnce;

/*
=================
R_BindAnimatedImage

=================
*/
static void R_BindAnimatedImage( textureBundle_t *bundle ) {
	int64_t index;

	if ( bundle->isVideoMap ) {
		ri.CIN_RunCinematic(bundle->videoMapHandle);
		ri.CIN_UploadCinematic(bundle->videoMapHandle);
		return;
	}

	if ( bundle->numImageAnimations <= 1 ) {
		GL_Bind( bundle->image[0] );
		return;
	}

	// it is necessary to do this messy calc to make sure animations line up
	// exactly with waveforms of the same frequency
Rinnegatamante's avatar
Rinnegatamante committed
81
	index = tess->shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE;
Rinnegatamante's avatar
Rinnegatamante committed
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
	index >>= FUNCTABLE_SIZE2;

	if ( index < 0 ) {
		index = 0;	// may happen with shader time offsets
	}

	while ( index >= bundle->numImageAnimations ) {
		index -= bundle->numImageAnimations;
	}

	GL_Bind( bundle->image[ index ] );
}

/*
================
DrawTris

Draws triangle outlines for debugging
================
*/
static void DrawTris (shaderCommands_t *input) {
	GL_Bind( tr.whiteImage );
	qglColor3f (1,1,1);

	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
	qglDepthRange( 0, 0 );

	qglDisableClientState (GL_COLOR_ARRAY);
	qglDisableClientState (GL_TEXTURE_COORD_ARRAY);

Rinnegatamante's avatar
Rinnegatamante committed
112
113
114
	float *vertices = gVertexBuffer;
	int i;
	for (i=0;i<input->numIndexes;i++){
115
116
		memcpy(gVertexBuffer, input->xyz[input->indexes[i]], sizeof(vec3_t));
		gVertexBuffer += 3;
Rinnegatamante's avatar
Rinnegatamante committed
117
	}
Rinnegatamante's avatar
Rinnegatamante committed
118
	//->vglVertexPointerMapped(vertices);
Rinnegatamante's avatar
Rinnegatamante committed
119
	
Rinnegatamante's avatar
Rinnegatamante committed
120
121
122
123
	//->if (qglLockArraysEXT) {
	//->	qglLockArraysEXT(0, input->numVertexes);
	//->	GLimp_LogComment( "glLockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
124
125
126

	R_DrawElements( input->numIndexes, input->indexes );

Rinnegatamante's avatar
Rinnegatamante committed
127
128
129
130
	//->if (qglUnlockArraysEXT) {
	//->	qglUnlockArraysEXT();
	//->	GLimp_LogComment( "glUnlockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
	qglDepthRange( 0, 1 );
}


/*
================
DrawNormals

Draws vertex normals for debugging
================
*/
static void DrawNormals (shaderCommands_t *input) {
	int		i;
	vec3_t	temp;

	GL_Bind( tr.whiteImage );
	qglColor3f (1,1,1);
	qglDepthRange( 0, 0 );	// never occluded
	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );

Rinnegatamante's avatar
Rinnegatamante committed
151
	float *vertices = gVertexBuffer;
Rinnegatamante's avatar
Rinnegatamante committed
152
	for (i = 0 ; i < input->numVertexes ; i++) {
153
154
		memcpy(gVertexBuffer, input->xyz[input->indexes[i]], sizeof(vec3_t));
		gVertexBuffer += 3;
Rinnegatamante's avatar
Rinnegatamante committed
155
		VectorMA (input->xyz[input->indexes[i]], 2, input->normal[input->indexes[i]], temp);
156
157
		memcpy(gVertexBuffer, temp, sizeof(vec3_t));
		gVertexBuffer += 3;
Rinnegatamante's avatar
Rinnegatamante committed
158
	}
Rinnegatamante's avatar
Rinnegatamante committed
159
	//->vglVertexPointerMapped(vertices);
Rinnegatamante's avatar
Rinnegatamante committed
160
	vglDrawObjects(GL_LINES, input->numVertexes * 2, GL_TRUE);
Rinnegatamante's avatar
Rinnegatamante committed
161
162
163
164
165
166
167
168
169
170
171
172
173

	qglDepthRange( 0, 1 );
}

/*
==============
RB_BeginSurface

We must set some things up before beginning any tesselation,
because a surface may be forced to perform a RB_End due
to overflow.
==============
*/
Rinnegatamante's avatar
Rinnegatamante committed
174
uint8_t tess_idx = 0;
Rinnegatamante's avatar
Rinnegatamante committed
175
176
177
void RB_BeginSurface( shader_t *shader, int fogNum ) {

	shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader;
Rinnegatamante's avatar
Rinnegatamante committed
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	
	tess_idx = (tess_idx + 1) % 256;
	tess = tess_pool[tess_idx];
	tess->numIndexes = 0;
	tess->numVertexes = 0;
	tess->shader = state;
	tess->fogNum = fogNum;
	tess->dlightBits = 0;		// will be OR'd in by surface functions
	tess->xstages = state->stages;
	tess->numPasses = state->numUnfoggedPasses;
	tess->currentStageIteratorFunc = state->optimalStageIteratorFunc;

	tess->shaderTime = backEnd.refdef.floatTime - tess->shader->timeOffset;
	if (tess->shader->clampTime && tess->shaderTime >= tess->shader->clampTime) {
		tess->shaderTime = tess->shader->clampTime;
Rinnegatamante's avatar
Rinnegatamante committed
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	}


}

/*
===================
DrawMultitextured

output = t0 * t1 or t0 + t1

t0 = most upstream according to spec
t1 = most downstream according to spec
===================
*/
static void DrawMultitextured( shaderCommands_t *input, int stage ) {
	shaderStage_t	*pStage;

Rinnegatamante's avatar
Rinnegatamante committed
211
	pStage = tess->xstages[stage];
Rinnegatamante's avatar
Rinnegatamante committed
212
213
214
215
216
217
218
219
220
221
222
223

	GL_State( pStage->stateBits );

	// this is an ugly hack to work around a GeForce driver
	// bug with multitexture and clip planes
	if ( backEnd.viewParms.isPortal ) {
		qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	}

	//
	// base
	//
Rinnegatamante's avatar
Rinnegatamante committed
224
	GL_SelectTexture( 0 );
Rinnegatamante's avatar
Rinnegatamante committed
225
	vglTexCoordPointerMapped(GL_FALSE, input->svars.texcoords[0]);
226

Rinnegatamante's avatar
Rinnegatamante committed
227
	R_BindAnimatedImage( &pStage->bundle[0] );
Rinnegatamante's avatar
Rinnegatamante committed
228
229
	R_DrawElements( input->numIndexes, input->indexes );
	
Rinnegatamante's avatar
Rinnegatamante committed
230
231
232
	//
	// lightmap/secondary pass
	//
Rinnegatamante's avatar
Rinnegatamante committed
233
	GL_SelectTexture( 1 );
234
235
	//->qglEnable( GL_TEXTURE_2D );
	//->qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
Rinnegatamante's avatar
Rinnegatamante committed
236

237
238
239
	//->if ( r_lightmap->integer ) {
	//->	GL_TexEnv( GL_REPLACE );
	//->} else {
Rinnegatamante's avatar
Rinnegatamante committed
240
	//->	GL_TexEnv( tess->shader->multitextureEnv );
241
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
242

Rinnegatamante's avatar
Rinnegatamante committed
243
	vglTexCoordPointerMapped(GL_FALSE, input->svars.texcoords[1]);
Rinnegatamante's avatar
Rinnegatamante committed
244
	R_BindAnimatedImage( &pStage->bundle[1] );
Rinnegatamante's avatar
Rinnegatamante committed
245
	R_DrawElements( input->numIndexes, input->indexes );
Rinnegatamante's avatar
Rinnegatamante committed
246
247
248
249
250

	//
	// disable texturing on TEXTURE1, then select TEXTURE0
	//
	//qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
251
	//->qglDisable( GL_TEXTURE_2D );
Rinnegatamante's avatar
Rinnegatamante committed
252

Rinnegatamante's avatar
Rinnegatamante committed
253
	GL_SelectTexture( 0 );
Rinnegatamante's avatar
Rinnegatamante committed
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
}



/*
===================
ProjectDlightTexture

Perform dynamic lighting with another rendering pass
===================
*/
static void ProjectDlightTexture_scalar( void ) {
	int		i, l;
	vec3_t	origin;
	float	*texCoords;
269
	byte	*colors;
Rinnegatamante's avatar
Rinnegatamante committed
270
271
	byte	clipBits[SHADER_MAX_VERTEXES];
	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
272
	byte	colorArray[SHADER_MAX_VERTEXES][4];
Rinnegatamante's avatar
Rinnegatamante committed
273
274
275
276
277
278
279
280
281
282
283
284
285
286
	glIndex_t	hitIndexes[SHADER_MAX_INDEXES];
	int		numIndexes;
	float	scale;
	float	radius;
	vec3_t	floatColor;
	float	modulate = 0.0f;

	if ( !backEnd.refdef.num_dlights ) {
		return;
	}

	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
		dlight_t	*dl;

Rinnegatamante's avatar
Rinnegatamante committed
287
		if ( !( tess->dlightBits & ( 1 << l ) ) ) {
Rinnegatamante's avatar
Rinnegatamante committed
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
			continue;	// this surface definitely doesn't have any of this light
		}
		texCoords = texCoordsArray[0];
		colors = colorArray[0];

		dl = &backEnd.refdef.dlights[l];
		VectorCopy( dl->transformed, origin );
		radius = dl->radius;
		scale = 1.0f / radius;

		if(r_greyscale->integer)
		{
			float luminance;

			luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f;
			floatColor[0] = floatColor[1] = floatColor[2] = luminance;
		}
		else if(r_greyscale->value)
		{
			float luminance;
			
			luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f;
			floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value);
			floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value);
			floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value);
		}
		else
		{
			floatColor[0] = dl->color[0] * 255.0f;
			floatColor[1] = dl->color[1] * 255.0f;
			floatColor[2] = dl->color[2] * 255.0f;
		}

Rinnegatamante's avatar
Rinnegatamante committed
321
		for ( i = 0 ; i < tess->numVertexes ; i++, texCoords += 2, colors += 4 ) {
Rinnegatamante's avatar
Rinnegatamante committed
322
323
324
			int		clip = 0;
			vec3_t	dist;
			
Rinnegatamante's avatar
Rinnegatamante committed
325
			VectorSubtract( origin, tess->xyz[i], dist );
Rinnegatamante's avatar
Rinnegatamante committed
326
327
328
329
330
331
332

			backEnd.pc.c_dlightVertexes++;

			texCoords[0] = 0.5f + dist[0] * scale;
			texCoords[1] = 0.5f + dist[1] * scale;

			if( !r_dlightBacks->integer &&
Rinnegatamante's avatar
Rinnegatamante committed
333
334
335
336
					// dist . tess->normal[i]
					( dist[0] * tess->normal[i][0] +
					dist[1] * tess->normal[i][1] +
					dist[2] * tess->normal[i][2] ) < 0.0f ) {
Rinnegatamante's avatar
Rinnegatamante committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
				clip = 63;
			} else {
				if ( texCoords[0] < 0.0f ) {
					clip |= 1;
				} else if ( texCoords[0] > 1.0f ) {
					clip |= 2;
				}
				if ( texCoords[1] < 0.0f ) {
					clip |= 4;
				} else if ( texCoords[1] > 1.0f ) {
					clip |= 8;
				}
				texCoords[0] = texCoords[0];
				texCoords[1] = texCoords[1];

				// modulate the strength based on the height and color
				if ( dist[2] > radius ) {
					clip |= 16;
					modulate = 0.0f;
				} else if ( dist[2] < -radius ) {
					clip |= 32;
					modulate = 0.0f;
				} else {
					dist[2] = Q_fabs(dist[2]);
					if ( dist[2] < radius * 0.5f ) {
						modulate = 1.0f;
					} else {
						modulate = 2.0f * (radius - dist[2]) * scale;
					}
				}
			}
			clipBits[i] = clip;
369
370
371
372
			colors[0] = ri.ftol(floatColor[0] * modulate);
			colors[1] = ri.ftol(floatColor[1] * modulate);
			colors[2] = ri.ftol(floatColor[2] * modulate);
			colors[3] = 255;
Rinnegatamante's avatar
Rinnegatamante committed
373
374
375
376
		}

		// build a list of triangles that need light
		numIndexes = 0;
Rinnegatamante's avatar
Rinnegatamante committed
377
		for ( i = 0 ; i < tess->numIndexes ; i += 3 ) {
Rinnegatamante's avatar
Rinnegatamante committed
378
379
			int		a, b, c;

Rinnegatamante's avatar
Rinnegatamante committed
380
381
382
			a = tess->indexes[i];
			b = tess->indexes[i+1];
			c = tess->indexes[i+2];
Rinnegatamante's avatar
Rinnegatamante committed
383
384
385
386
387
388
389
390
391
392
393
394
			if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
				continue;	// not lighted
			}
			hitIndexes[numIndexes] = a;
			hitIndexes[numIndexes+1] = b;
			hitIndexes[numIndexes+2] = c;
			numIndexes += 3;
		}

		if ( !numIndexes ) {
			continue;
		}
Rinnegatamante's avatar
Rinnegatamante committed
395
		
Rinnegatamante's avatar
Rinnegatamante committed
396
397
		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
		qglEnableClientState( GL_COLOR_ARRAY );
Rinnegatamante's avatar
Rinnegatamante committed
398

Rinnegatamante's avatar
Rinnegatamante committed
399
400
		vglColorPointerMapped(GL_UNSIGNED_BYTE, colorArray);
		vglTexCoordPointerMapped(GL_FALSE, texCoordsArray[0]);
Rinnegatamante's avatar
Rinnegatamante committed
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

		GL_Bind( tr.dlightImage );
		// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
		// where they aren't rendered
		if ( dl->additive ) {
			GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
		}
		else {
			GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
		}
		R_DrawElements( numIndexes, hitIndexes );
		backEnd.pc.c_totalIndexes += numIndexes;
		backEnd.pc.c_dlightIndexes += numIndexes;
	}
}

static void ProjectDlightTexture( void ) {
	ProjectDlightTexture_scalar();
}

/*
===================
RB_FogPass

Blends a fog texture on top of everything else
===================
*/
static void RB_FogPass( void ) {
	fog_t		*fog;
	int			i;

	qglEnableClientState( GL_COLOR_ARRAY );
	qglEnableClientState( GL_TEXTURE_COORD_ARRAY);

Rinnegatamante's avatar
Rinnegatamante committed
435
	fog = tr.world->fogs + tess->fogNum;
Rinnegatamante's avatar
Rinnegatamante committed
436

Rinnegatamante's avatar
Rinnegatamante committed
437
438
	for ( i = 0; i < tess->numVertexes; i++ ) {
		* ( int * )&tess->svars.colors[i] = fog->colorInt;
Rinnegatamante's avatar
Rinnegatamante committed
439
440
	}

Rinnegatamante's avatar
Rinnegatamante committed
441
	RB_CalcFogTexCoords( ( float * ) tess->svars.texcoords[0] );
Rinnegatamante's avatar
Rinnegatamante committed
442
443
444

	GL_Bind( tr.fogImage );

Rinnegatamante's avatar
Rinnegatamante committed
445
	if ( tess->shader->fogPass == FP_EQUAL ) {
Rinnegatamante's avatar
Rinnegatamante committed
446
447
448
449
450
		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
	} else {
		GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
	}

Rinnegatamante's avatar
Rinnegatamante committed
451
452
	vglColorPointerMapped(GL_UNSIGNED_BYTE, tess->svars.colors);
	vglTexCoordPointerMapped(GL_FALSE, tess->svars.texcoords[0]);
Rinnegatamante's avatar
Rinnegatamante committed
453
	
Rinnegatamante's avatar
Rinnegatamante committed
454
	R_DrawElements( tess->numIndexes, tess->indexes );
Rinnegatamante's avatar
Rinnegatamante committed
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
}

/*
===============
ComputeColors
===============
*/
static void ComputeColors( shaderStage_t *pStage )
{
	int		i;

	//
	// rgbGen
	//
	switch ( pStage->rgbGen )
	{
		case CGEN_IDENTITY:
Rinnegatamante's avatar
Rinnegatamante committed
472
			Com_Memset( tess->svars.colors, 0xff, tess->numVertexes * 4 );
Rinnegatamante's avatar
Rinnegatamante committed
473
474
475
			break;
		default:
		case CGEN_IDENTITY_LIGHTING:
Rinnegatamante's avatar
Rinnegatamante committed
476
			Com_Memset( tess->svars.colors, tr.identityLightByte, tess->numVertexes * 4 );
Rinnegatamante's avatar
Rinnegatamante committed
477
478
			break;
		case CGEN_LIGHTING_DIFFUSE:
Rinnegatamante's avatar
Rinnegatamante committed
479
			RB_CalcDiffuseColor( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
480
481
			break;
		case CGEN_EXACT_VERTEX:
Rinnegatamante's avatar
Rinnegatamante committed
482
			Com_Memcpy( tess->svars.colors, tess->vertexColors, tess->numVertexes * sizeof( tess->vertexColors[0] ) );
Rinnegatamante's avatar
Rinnegatamante committed
483
484
			break;
		case CGEN_CONST:
Rinnegatamante's avatar
Rinnegatamante committed
485
486
			for ( i = 0; i < tess->numVertexes; i++ ) {
				*(int *)tess->svars.colors[i] = *(int *)pStage->constantColor;
Rinnegatamante's avatar
Rinnegatamante committed
487
488
489
490
491
			}
			break;
		case CGEN_VERTEX:
			if ( tr.identityLight == 1 )
			{
Rinnegatamante's avatar
Rinnegatamante committed
492
				Com_Memcpy( tess->svars.colors, tess->vertexColors, tess->numVertexes * sizeof( tess->vertexColors[0] ) );
Rinnegatamante's avatar
Rinnegatamante committed
493
494
495
			}
			else
			{
Rinnegatamante's avatar
Rinnegatamante committed
496
				for ( i = 0; i < tess->numVertexes; i++ )
Rinnegatamante's avatar
Rinnegatamante committed
497
				{
Rinnegatamante's avatar
Rinnegatamante committed
498
499
500
501
					tess->svars.colors[i][0] = tess->vertexColors[i][0] * tr.identityLight;
					tess->svars.colors[i][1] = tess->vertexColors[i][1] * tr.identityLight;
					tess->svars.colors[i][2] = tess->vertexColors[i][2] * tr.identityLight;
					tess->svars.colors[i][3] = tess->vertexColors[i][3];
Rinnegatamante's avatar
Rinnegatamante committed
502
503
504
505
506
507
				}
			}
			break;
		case CGEN_ONE_MINUS_VERTEX:
			if ( tr.identityLight == 1 )
			{
Rinnegatamante's avatar
Rinnegatamante committed
508
				for ( i = 0; i < tess->numVertexes; i++ )
Rinnegatamante's avatar
Rinnegatamante committed
509
				{
Rinnegatamante's avatar
Rinnegatamante committed
510
511
512
					tess->svars.colors[i][0] = 255 - tess->vertexColors[i][0];
					tess->svars.colors[i][1] = 255 - tess->vertexColors[i][1];
					tess->svars.colors[i][2] = 255 - tess->vertexColors[i][2];
Rinnegatamante's avatar
Rinnegatamante committed
513
514
515
516
				}
			}
			else
			{
Rinnegatamante's avatar
Rinnegatamante committed
517
				for ( i = 0; i < tess->numVertexes; i++ )
Rinnegatamante's avatar
Rinnegatamante committed
518
				{
Rinnegatamante's avatar
Rinnegatamante committed
519
520
521
					tess->svars.colors[i][0] = ( 255 - tess->vertexColors[i][0] ) * tr.identityLight;
					tess->svars.colors[i][1] = ( 255 - tess->vertexColors[i][1] ) * tr.identityLight;
					tess->svars.colors[i][2] = ( 255 - tess->vertexColors[i][2] ) * tr.identityLight;
Rinnegatamante's avatar
Rinnegatamante committed
522
523
524
525
526
527
528
				}
			}
			break;
		case CGEN_FOG:
			{
				fog_t		*fog;

Rinnegatamante's avatar
Rinnegatamante committed
529
				fog = tr.world->fogs + tess->fogNum;
Rinnegatamante's avatar
Rinnegatamante committed
530

Rinnegatamante's avatar
Rinnegatamante committed
531
532
				for ( i = 0; i < tess->numVertexes; i++ ) {
					* ( int * )&tess->svars.colors[i] = fog->colorInt;
Rinnegatamante's avatar
Rinnegatamante committed
533
534
535
536
				}
			}
			break;
		case CGEN_WAVEFORM:
Rinnegatamante's avatar
Rinnegatamante committed
537
			RB_CalcWaveColor( &pStage->rgbWave, ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
538
539
			break;
		case CGEN_ENTITY:
Rinnegatamante's avatar
Rinnegatamante committed
540
			RB_CalcColorFromEntity( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
541
542
			break;
		case CGEN_ONE_MINUS_ENTITY:
Rinnegatamante's avatar
Rinnegatamante committed
543
			RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
544
545
546
547
548
549
550
551
552
553
554
555
556
557
			break;
	}

	//
	// alphaGen
	//
	switch ( pStage->alphaGen )
	{
	case AGEN_SKIP:
		break;
	case AGEN_IDENTITY:
		if ( pStage->rgbGen != CGEN_IDENTITY ) {
			if ( ( pStage->rgbGen == CGEN_VERTEX && tr.identityLight != 1 ) ||
				 pStage->rgbGen != CGEN_VERTEX ) {
Rinnegatamante's avatar
Rinnegatamante committed
558
559
				for ( i = 0; i < tess->numVertexes; i++ ) {
					tess->svars.colors[i][3] = 0xff;
Rinnegatamante's avatar
Rinnegatamante committed
560
561
562
563
564
565
				}
			}
		}
		break;
	case AGEN_CONST:
		if ( pStage->rgbGen != CGEN_CONST ) {
Rinnegatamante's avatar
Rinnegatamante committed
566
567
			for ( i = 0; i < tess->numVertexes; i++ ) {
				tess->svars.colors[i][3] = pStage->constantColor[3];
Rinnegatamante's avatar
Rinnegatamante committed
568
569
570
571
			}
		}
		break;
	case AGEN_WAVEFORM:
Rinnegatamante's avatar
Rinnegatamante committed
572
		RB_CalcWaveAlpha( &pStage->alphaWave, ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
573
574
		break;
	case AGEN_LIGHTING_SPECULAR:
Rinnegatamante's avatar
Rinnegatamante committed
575
		RB_CalcSpecularAlpha( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
576
577
		break;
	case AGEN_ENTITY:
Rinnegatamante's avatar
Rinnegatamante committed
578
		RB_CalcAlphaFromEntity( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
579
580
		break;
	case AGEN_ONE_MINUS_ENTITY:
Rinnegatamante's avatar
Rinnegatamante committed
581
		RB_CalcAlphaFromOneMinusEntity( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
582
583
584
		break;
    case AGEN_VERTEX:
		if ( pStage->rgbGen != CGEN_VERTEX ) {
Rinnegatamante's avatar
Rinnegatamante committed
585
586
			for ( i = 0; i < tess->numVertexes; i++ ) {
				tess->svars.colors[i][3] = tess->vertexColors[i][3];
Rinnegatamante's avatar
Rinnegatamante committed
587
588
589
590
			}
		}
        break;
    case AGEN_ONE_MINUS_VERTEX:
Rinnegatamante's avatar
Rinnegatamante committed
591
        for ( i = 0; i < tess->numVertexes; i++ )
Rinnegatamante's avatar
Rinnegatamante committed
592
        {
Rinnegatamante's avatar
Rinnegatamante committed
593
			tess->svars.colors[i][3] = 255 - tess->vertexColors[i][3];
Rinnegatamante's avatar
Rinnegatamante committed
594
595
596
597
598
599
        }
        break;
	case AGEN_PORTAL:
		{
			unsigned char alpha;

Rinnegatamante's avatar
Rinnegatamante committed
600
			for ( i = 0; i < tess->numVertexes; i++ )
Rinnegatamante's avatar
Rinnegatamante committed
601
602
603
604
			{
				float len;
				vec3_t v;

Rinnegatamante's avatar
Rinnegatamante committed
605
				VectorSubtract( tess->xyz[i], backEnd.viewParms.or.origin, v );
Rinnegatamante's avatar
Rinnegatamante committed
606
607
				len = VectorLength( v );

Rinnegatamante's avatar
Rinnegatamante committed
608
				len /= tess->shader->portalRange;
Rinnegatamante's avatar
Rinnegatamante committed
609
610
611
612
613
614
615
616
617
618
619
620
621
622

				if ( len < 0 )
				{
					alpha = 0;
				}
				else if ( len > 1 )
				{
					alpha = 0xff;
				}
				else
				{
					alpha = len * 0xff;
				}

Rinnegatamante's avatar
Rinnegatamante committed
623
				tess->svars.colors[i][3] = alpha;
Rinnegatamante's avatar
Rinnegatamante committed
624
625
626
627
628
629
630
631
			}
		}
		break;
	}

	//
	// fog adjustment for colors to fade out as fog increases
	//
Rinnegatamante's avatar
Rinnegatamante committed
632
	if ( tess->fogNum )
Rinnegatamante's avatar
Rinnegatamante committed
633
634
635
636
	{
		switch ( pStage->adjustColorsForFog )
		{
		case ACFF_MODULATE_RGB:
Rinnegatamante's avatar
Rinnegatamante committed
637
			RB_CalcModulateColorsByFog( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
638
639
			break;
		case ACFF_MODULATE_ALPHA:
Rinnegatamante's avatar
Rinnegatamante committed
640
			RB_CalcModulateAlphasByFog( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
641
642
			break;
		case ACFF_MODULATE_RGBA:
Rinnegatamante's avatar
Rinnegatamante committed
643
			RB_CalcModulateRGBAsByFog( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
644
645
646
647
648
649
650
651
652
653
			break;
		case ACFF_NONE:
			break;
		}
	}
	
	// if in greyscale rendering mode turn all color values into greyscale.
	if(r_greyscale->integer)
	{
		int scale;
Rinnegatamante's avatar
Rinnegatamante committed
654
		for(i = 0; i < tess->numVertexes; i++)
Rinnegatamante's avatar
Rinnegatamante committed
655
		{
Rinnegatamante's avatar
Rinnegatamante committed
656
657
			scale = LUMA(tess->svars.colors[i][0], tess->svars.colors[i][1], tess->svars.colors[i][2]);
 			tess->svars.colors[i][0] = tess->svars.colors[i][1] = tess->svars.colors[i][2] = scale;
Rinnegatamante's avatar
Rinnegatamante committed
658
659
660
661
662
663
		}
	}
	else if(r_greyscale->value)
	{
		float scale;
		
Rinnegatamante's avatar
Rinnegatamante committed
664
		for(i = 0; i < tess->numVertexes; i++)
Rinnegatamante's avatar
Rinnegatamante committed
665
		{
Rinnegatamante's avatar
Rinnegatamante committed
666
667
668
669
			scale = LUMA(tess->svars.colors[i][0], tess->svars.colors[i][1], tess->svars.colors[i][2]);
			tess->svars.colors[i][0] = LERP(tess->svars.colors[i][0], scale, r_greyscale->value);
			tess->svars.colors[i][1] = LERP(tess->svars.colors[i][1], scale, r_greyscale->value);
			tess->svars.colors[i][2] = LERP(tess->svars.colors[i][2], scale, r_greyscale->value);
Rinnegatamante's avatar
Rinnegatamante committed
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
		}
	}
}

/*
===============
ComputeTexCoords
===============
*/
static void ComputeTexCoords( shaderStage_t *pStage ) {
	int		i;
	int		b;

	for ( b = 0; b < NUM_TEXTURE_BUNDLES; b++ ) {
		int tm;

		//
		// generate the texture coordinates
		//
		switch ( pStage->bundle[b].tcGen )
		{
		case TCGEN_IDENTITY:
Rinnegatamante's avatar
Rinnegatamante committed
692
			Com_Memset( tess->svars.texcoords[b], 0, sizeof( float ) * 2 * tess->numVertexes );
Rinnegatamante's avatar
Rinnegatamante committed
693
694
			break;
		case TCGEN_TEXTURE:
Rinnegatamante's avatar
Rinnegatamante committed
695
696
697
			for ( i = 0 ; i < tess->numVertexes ; i++ ) {
				tess->svars.texcoords[b][i][0] = tess->texCoords[i][0][0];
				tess->svars.texcoords[b][i][1] = tess->texCoords[i][0][1];
Rinnegatamante's avatar
Rinnegatamante committed
698
699
700
			}
			break;
		case TCGEN_LIGHTMAP:
Rinnegatamante's avatar
Rinnegatamante committed
701
702
703
			for ( i = 0 ; i < tess->numVertexes ; i++ ) {
				tess->svars.texcoords[b][i][0] = tess->texCoords[i][1][0];
				tess->svars.texcoords[b][i][1] = tess->texCoords[i][1][1];
Rinnegatamante's avatar
Rinnegatamante committed
704
705
706
			}
			break;
		case TCGEN_VECTOR:
Rinnegatamante's avatar
Rinnegatamante committed
707
708
709
			for ( i = 0 ; i < tess->numVertexes ; i++ ) {
				tess->svars.texcoords[b][i][0] = DotProduct( tess->xyz[i], pStage->bundle[b].tcGenVectors[0] );
				tess->svars.texcoords[b][i][1] = DotProduct( tess->xyz[i], pStage->bundle[b].tcGenVectors[1] );
Rinnegatamante's avatar
Rinnegatamante committed
710
711
712
			}
			break;
		case TCGEN_FOG:
Rinnegatamante's avatar
Rinnegatamante committed
713
			RB_CalcFogTexCoords( ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
714
715
			break;
		case TCGEN_ENVIRONMENT_MAPPED:
Rinnegatamante's avatar
Rinnegatamante committed
716
			RB_CalcEnvironmentTexCoords( ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
			break;
		case TCGEN_BAD:
			return;
		}

		//
		// alter texture coordinates
		//
		for ( tm = 0; tm < pStage->bundle[b].numTexMods ; tm++ ) {
			switch ( pStage->bundle[b].texMods[tm].type )
			{
			case TMOD_NONE:
				tm = TR_MAX_TEXMODS;		// break out of for loop
				break;

			case TMOD_TURBULENT:
				RB_CalcTurbulentTexCoords( &pStage->bundle[b].texMods[tm].wave, 
Rinnegatamante's avatar
Rinnegatamante committed
734
						                 ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
735
736
737
738
				break;

			case TMOD_ENTITY_TRANSLATE:
				RB_CalcScrollTexCoords( backEnd.currentEntity->e.shaderTexCoord,
Rinnegatamante's avatar
Rinnegatamante committed
739
									 ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
740
741
742
743
				break;

			case TMOD_SCROLL:
				RB_CalcScrollTexCoords( pStage->bundle[b].texMods[tm].scroll,
Rinnegatamante's avatar
Rinnegatamante committed
744
										 ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
745
746
747
748
				break;

			case TMOD_SCALE:
				RB_CalcScaleTexCoords( pStage->bundle[b].texMods[tm].scale,
Rinnegatamante's avatar
Rinnegatamante committed
749
									 ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
750
751
752
753
				break;
			
			case TMOD_STRETCH:
				RB_CalcStretchTexCoords( &pStage->bundle[b].texMods[tm].wave, 
Rinnegatamante's avatar
Rinnegatamante committed
754
						               ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
755
756
757
758
				break;

			case TMOD_TRANSFORM:
				RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm],
Rinnegatamante's avatar
Rinnegatamante committed
759
						                 ( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
760
761
762
763
				break;

			case TMOD_ROTATE:
				RB_CalcRotateTexCoords( pStage->bundle[b].texMods[tm].rotateSpeed,
Rinnegatamante's avatar
Rinnegatamante committed
764
										( float * ) tess->svars.texcoords[b] );
Rinnegatamante's avatar
Rinnegatamante committed
765
766
767
				break;

			default:
Rinnegatamante's avatar
Rinnegatamante committed
768
				ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", pStage->bundle[b].texMods[tm].type, tess->shader->name );
Rinnegatamante's avatar
Rinnegatamante committed
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
				break;
			}
		}
	}
}

/*
** RB_IterateStagesGeneric
*/
static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
	int stage;

	for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
	{
Rinnegatamante's avatar
Rinnegatamante committed
784
		shaderStage_t *pStage = tess->xstages[stage];
Rinnegatamante's avatar
Rinnegatamante committed
785
786
787
788
789
790
791
792
793

		if ( !pStage )
		{
			break;
		}

		ComputeColors( pStage );
		ComputeTexCoords( pStage );

Rinnegatamante's avatar
Rinnegatamante committed
794
795
		//if ( !setArraysOnce )
		//{
Rinnegatamante's avatar
Rinnegatamante committed
796
			qglEnableClientState( GL_COLOR_ARRAY );
Rinnegatamante's avatar
Rinnegatamante committed
797
			vglColorPointerMapped(GL_UNSIGNED_BYTE, input->svars.colors);
Rinnegatamante's avatar
Rinnegatamante committed
798
		//}
Rinnegatamante's avatar
Rinnegatamante committed
799
800
801
802
803
804

		//
		// do multitexture
		//
		if ( pStage->bundle[1].image[0] != 0 )
		{
805
			DrawMultitextured( input, stage );
Rinnegatamante's avatar
Rinnegatamante committed
806
807
808
		}
		else
		{
Rinnegatamante's avatar
Rinnegatamante committed
809
810
			//if ( !setArraysOnce )
			//{
Rinnegatamante's avatar
Rinnegatamante committed
811
				vglTexCoordPointerMapped(GL_FALSE, input->svars.texcoords[0]);
Rinnegatamante's avatar
Rinnegatamante committed
812
			//}
Rinnegatamante's avatar
Rinnegatamante committed
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841

			//
			// set state
			//
			R_BindAnimatedImage( &pStage->bundle[0] );

			GL_State( pStage->stateBits );

			//
			// draw
			//
			R_DrawElements( input->numIndexes, input->indexes );
		}
		// allow skipping out to show just lightmaps during development
		if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
		{
			break;
		}
	}
}

/*
** RB_StageIteratorGeneric
*/
void RB_StageIteratorGeneric( void )
{
	shaderCommands_t *input;
	shader_t		*shader;

Rinnegatamante's avatar
Rinnegatamante committed
842
	input = tess;
Rinnegatamante's avatar
Rinnegatamante committed
843
844
845
846
847
848
849
850
851
852
	shader = input->shader;

	RB_DeformTessGeometry();
	//
	// log this call
	//
	if ( r_logFile->integer ) 
	{
		// don't just call LogComment, or we will get
		// a call to va() every frame!
Rinnegatamante's avatar
Rinnegatamante committed
853
		GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess->shader->name) );
Rinnegatamante's avatar
Rinnegatamante committed
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
	}

	//
	// set face culling appropriately
	//
	GL_Cull( shader->cullType );

	// set polygon offset if necessary
	if ( shader->polygonOffset )
	{
		qglEnable( GL_POLYGON_OFFSET_FILL );
		qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value );
	}

	//
	// lock XYZ
	//
Rinnegatamante's avatar
Rinnegatamante committed
871
	vglVertexPointerMapped(GL_TRUE, input->xyz);
Rinnegatamante's avatar
Rinnegatamante committed
872
	
Rinnegatamante's avatar
Rinnegatamante committed
873
874
875
876
877
	//->if (qglLockArraysEXT)
	//->{
	//->	qglLockArraysEXT(0, input->numVertexes);
	//->	GLimp_LogComment( "glLockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
878
879
880
881
882
883
884
885
886

	//
	// call shader function
	//
	RB_IterateStagesGeneric( input );

	// 
	// now do any dynamic lighting needed
	//
Rinnegatamante's avatar
Rinnegatamante committed
887
888
	if ( tess->dlightBits && tess->shader->sort <= SS_OPAQUE
		&& !(tess->shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
Rinnegatamante's avatar
Rinnegatamante committed
889
890
891
892
893
894
		ProjectDlightTexture();
	}

	//
	// now do fog
	//
Rinnegatamante's avatar
Rinnegatamante committed
895
	if ( tess->fogNum && tess->shader->fogPass ) {
Rinnegatamante's avatar
Rinnegatamante committed
896
897
898
899
900
901
		RB_FogPass();
	}

	// 
	// unlock arrays
	//
Rinnegatamante's avatar
Rinnegatamante committed
902
903
904
905
906
	//->if (qglUnlockArraysEXT) 
	//->{
	//->	qglUnlockArraysEXT();
	//->	GLimp_LogComment( "glUnlockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925

	//
	// reset polygon offset
	//
	if ( shader->polygonOffset )
	{
		qglDisable( GL_POLYGON_OFFSET_FILL );
	}
}


/*
** RB_StageIteratorVertexLitTexture
*/
void RB_StageIteratorVertexLitTexture( void )
{
	shaderCommands_t *input;
	shader_t		*shader;

Rinnegatamante's avatar
Rinnegatamante committed
926
	input = tess;
Rinnegatamante's avatar
Rinnegatamante committed
927
928
929
930
931
	shader = input->shader;

	//
	// compute colors
	//
Rinnegatamante's avatar
Rinnegatamante committed
932
	RB_CalcDiffuseColor( ( unsigned char * ) tess->svars.colors );
Rinnegatamante's avatar
Rinnegatamante committed
933
934
935
936
937
938
939
940

	//
	// log this call
	//
	if ( r_logFile->integer ) 
	{
		// don't just call LogComment, or we will get
		// a call to va() every frame!
Rinnegatamante's avatar
Rinnegatamante committed
941
		GLimp_LogComment( va("--- RB_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess->shader->name) );
Rinnegatamante's avatar
Rinnegatamante committed
942
943
944
945
946
947
948
949
950
951
952
953
954
	}

	//
	// set face culling appropriately
	//
	GL_Cull( shader->cullType );

	//
	// set arrays and lock
	//
	qglEnableClientState( GL_COLOR_ARRAY);
	qglEnableClientState( GL_TEXTURE_COORD_ARRAY);

Rinnegatamante's avatar
Rinnegatamante committed
955
956
957
	vglColorPointerMapped(GL_UNSIGNED_BYTE, tess->svars.colors);
	vglTexCoordPointerMapped(GL_TRUE, tess->texCoords[0][0]);
	vglVertexPointerMapped(GL_TRUE, input->xyz);
Rinnegatamante's avatar
Rinnegatamante committed
958

Rinnegatamante's avatar
Rinnegatamante committed
959
960
961
962
963
	//->if ( qglLockArraysEXT )
	//->{
	//->	qglLockArraysEXT(0, input->numVertexes);
	//->	GLimp_LogComment( "glLockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
964
965
966
967

	//
	// call special shade routine
	//
Rinnegatamante's avatar
Rinnegatamante committed
968
969
	R_BindAnimatedImage( &tess->xstages[0]->bundle[0] );
	GL_State( tess->xstages[0]->stateBits );
Rinnegatamante's avatar
Rinnegatamante committed
970
971
972
973
974
	R_DrawElements( input->numIndexes, input->indexes );

	// 
	// now do any dynamic lighting needed
	//
Rinnegatamante's avatar
Rinnegatamante committed
975
	if ( tess->dlightBits && tess->shader->sort <= SS_OPAQUE ) {
Rinnegatamante's avatar
Rinnegatamante committed
976
977
978
979
980
981
		ProjectDlightTexture();
	}

	//
	// now do fog
	//
Rinnegatamante's avatar
Rinnegatamante committed
982
	if ( tess->fogNum && tess->shader->fogPass ) {
Rinnegatamante's avatar
Rinnegatamante committed
983
984
985
986
987
988
		RB_FogPass();
	}

	// 
	// unlock arrays
	//
Rinnegatamante's avatar
Rinnegatamante committed
989
990
991
992
993
	//->if (qglUnlockArraysEXT) 
	//->{
	//->	qglUnlockArraysEXT();
	//->	GLimp_LogComment( "glUnlockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
994
995
996
997
998
999
1000
1001
}

//define	REPLACE_MODE

void RB_StageIteratorLightmappedMultitexture( void ) {
	shaderCommands_t *input;
	shader_t		*shader;

Rinnegatamante's avatar
Rinnegatamante committed
1002
	input = tess;
Rinnegatamante's avatar
Rinnegatamante committed
1003
1004
1005
1006
1007
1008
1009
1010
	shader = input->shader;

	//
	// log this call
	//
	if ( r_logFile->integer ) {
		// don't just call LogComment, or we will get
		// a call to va() every frame!
Rinnegatamante's avatar
Rinnegatamante committed
1011
		GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess->shader->name) );
Rinnegatamante's avatar
Rinnegatamante committed
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
	}

	//
	// set face culling appropriately
	//
	GL_Cull( shader->cullType );

	//
	// set color, pointers, and lock
	//
	GL_State( GLS_DEFAULT );
Rinnegatamante's avatar
Rinnegatamante committed
1023
	qglEnableClientState( GL_COLOR_ARRAY );
Rinnegatamante's avatar
Rinnegatamante committed
1024
1025
	vglVertexPointerMapped(GL_TRUE, input->xyz);
	vglColorPointerMapped(GL_UNSIGNED_BYTE, tess->constantColor255);
Rinnegatamante's avatar
Rinnegatamante committed
1026
1027
1028
1029

	//
	// select base stage
	//
Rinnegatamante's avatar
Rinnegatamante committed
1030
	GL_SelectTexture( 0 );
Rinnegatamante's avatar
Rinnegatamante committed
1031
1032

	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
Rinnegatamante's avatar
Rinnegatamante committed
1033
	R_BindAnimatedImage( &tess->xstages[0]->bundle[0] );
Rinnegatamante's avatar
Rinnegatamante committed
1034
	
Rinnegatamante's avatar
Rinnegatamante committed
1035
	vglTexCoordPointerMapped(GL_TRUE, tess->texCoords[0][0]);
Rinnegatamante's avatar
Rinnegatamante committed
1036
1037
	R_DrawElements( input->numIndexes, input->indexes );
	
Rinnegatamante's avatar
Rinnegatamante committed
1038
1039
1040
	//
	// configure second stage
	//
Rinnegatamante's avatar
Rinnegatamante committed
1041
	GL_SelectTexture( 1 );
Rinnegatamante's avatar
Rinnegatamante committed
1042
1043
1044
1045
1046
1047
	//->qglEnable( GL_TEXTURE_2D );
	//->if ( r_lightmap->integer ) {
	//->	GL_TexEnv( GL_REPLACE );
	//->} else {
	//->	GL_TexEnv( GL_MODULATE );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
1048
1049
	R_BindAnimatedImage( &tess->xstages[0]->bundle[1] );
	vglTexCoordPointerMapped(GL_TRUE, tess->texCoords[0][1]);
Rinnegatamante's avatar
Rinnegatamante committed
1050
1051
1052
1053

	//
	// lock arrays
	//
Rinnegatamante's avatar
Rinnegatamante committed
1054
1055
1056
1057
	//->if ( qglLockArraysEXT ) {
	//->	qglLockArraysEXT(0, input->numVertexes);
	//->	GLimp_LogComment( "glLockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
1058
1059
1060
1061
1062
1063

	R_DrawElements( input->numIndexes, input->indexes );

	//
	// disable texturing on TEXTURE1, then select TEXTURE0
	//
Rinnegatamante's avatar
Rinnegatamante committed
1064
	//->qglDisable( GL_TEXTURE_2D );
1065
	//->qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
Rinnegatamante's avatar
Rinnegatamante committed
1066

Rinnegatamante's avatar
Rinnegatamante committed
1067
	GL_SelectTexture( 0 );
Rinnegatamante's avatar
Rinnegatamante committed
1068
1069
1070
1071
1072
1073
1074
1075
#ifdef REPLACE_MODE
	GL_TexEnv( GL_MODULATE );
	qglShadeModel( GL_SMOOTH );
#endif

	// 
	// now do any dynamic lighting needed
	//
Rinnegatamante's avatar
Rinnegatamante committed
1076
	if ( tess->dlightBits && tess->shader->sort <= SS_OPAQUE ) {
Rinnegatamante's avatar
Rinnegatamante committed
1077
1078
1079
1080
1081
1082
		ProjectDlightTexture();
	}

	//
	// now do fog
	//
Rinnegatamante's avatar
Rinnegatamante committed
1083
	if ( tess->fogNum && tess->shader->fogPass ) {
Rinnegatamante's avatar
Rinnegatamante committed
1084
1085
1086
1087
1088
1089
		RB_FogPass();
	}

	//
	// unlock arrays
	//
Rinnegatamante's avatar
Rinnegatamante committed
1090
1091
1092
1093
	//->if ( qglUnlockArraysEXT ) {
	//->	qglUnlockArraysEXT();
	//->	GLimp_LogComment( "glUnlockArraysEXT\n" );
	//->}
Rinnegatamante's avatar
Rinnegatamante committed
1094
1095
1096
1097
1098
1099
1100
1101
}

/*
** RB_EndSurface
*/
void RB_EndSurface( void ) {
	shaderCommands_t *input;

Rinnegatamante's avatar
Rinnegatamante committed
1102
	input = tess;
Rinnegatamante's avatar
Rinnegatamante committed
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114

	if (input->numIndexes == 0) {
		return;
	}

	if (input->indexes[SHADER_MAX_INDEXES-1] != 0) {
		ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit");
	}	
	if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) {
		ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit");
	}

Rinnegatamante's avatar
Rinnegatamante committed
1115
	if ( tess->shader == tr.shadowShader ) {
Rinnegatamante's avatar
Rinnegatamante committed
1116
1117
1118
1119
1120
		RB_ShadowTessEnd();
		return;
	}

	// for debugging of sort order issues, stop rendering after a given sort value
Rinnegatamante's avatar
Rinnegatamante committed
1121
	if ( r_debugSort->integer && r_debugSort->integer < tess->shader->sort ) {
Rinnegatamante's avatar
Rinnegatamante committed
1122
1123
1124
1125
1126
1127
1128
		return;
	}

	//
	// update performance counters
	//
	backEnd.pc.c_shaders++;
Rinnegatamante's avatar
Rinnegatamante committed
1129
1130
1131
	backEnd.pc.c_vertexes += tess->numVertexes;
	backEnd.pc.c_indexes += tess->numIndexes;
	backEnd.pc.c_totalIndexes += tess->numIndexes * tess->numPasses;
Rinnegatamante's avatar
Rinnegatamante committed
1132
1133
1134
1135

	//
	// call off to shader specific tess end function
	//
Rinnegatamante's avatar
Rinnegatamante committed
1136
	tess->currentStageIteratorFunc();
Rinnegatamante's avatar
Rinnegatamante committed
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147

	//
	// draw debugging stuff
	//
	if ( r_showtris->integer ) {
		DrawTris (input);
	}
	if ( r_shownormals->integer ) {
		DrawNormals (input);
	}
	// clear shader so we can tell we don't have any unclosed surfaces
Rinnegatamante's avatar
Rinnegatamante committed
1148
	tess->numIndexes = 0;
Rinnegatamante's avatar
Rinnegatamante committed
1149
1150
1151
1152

	GLimp_LogComment( "----------\n" );
}