1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 //
21 // rb_render.c
22 //
23 
24 #include "rb_local.h"
25 
26 /*
27 ===============================================================================
28 
29 	ARRAYS
30 
31 ===============================================================================
32 */
33 
34 // Rendering paths
35 static void				(*RB_ModifyTextureCoords) (shaderPass_t *pass, texUnit_t texUnit);
36 
37 // Backend data
38 rbData_t				rb;
39 
40 // Temporary spaces
41 static bvec4_t			rb_outColorArray[RB_MAX_VERTS];
42 static vec2_t			rb_outCoordArray[MAX_TEXUNITS][RB_MAX_VERTS];
43 static vec3_t			rb_outVertexArray[RB_MAX_VERTS];
44 
45 // Dynamic data
46 static shaderPass_t		*rb_accumPasses[MAX_TEXUNITS];
47 static int				rb_numPasses;
48 static int				rb_numOldPasses;
49 
50 static qBool			rb_arraysLocked;
51 static qBool			rb_triangleOutlines;
52 static float			rb_shaderTime;
53 static uint32			rb_stateBits1;
54 
55 // Static data
56 static qBool			rb_matrixCoords;		// Texture coordinate math done using texture matrices
57 static int				rb_identityLighting;
58 
59 static shaderPass_t		rb_dLightPass;
60 static shaderPass_t		rb_fogPass;
61 static shaderPass_t		rb_lightMapPass;
62 
63 float					rb_sinTable[FTABLE_SIZE];
64 float					rb_triangleTable[FTABLE_SIZE];
65 float					rb_squareTable[FTABLE_SIZE];
66 float					rb_sawtoothTable[FTABLE_SIZE];
67 float					rb_inverseSawtoothTable[FTABLE_SIZE];
68 float					rb_noiseTable[FTABLE_SIZE];
69 
70 /*
71 =============
72 RB_LockArrays
73 =============
74 */
RB_LockArrays(int numVerts)75 void RB_LockArrays (int numVerts)
76 {
77 	if (rb_arraysLocked)
78 		return;
79 	if (!ri.config.extCompiledVertArray)
80 		return;
81 
82 	qglLockArraysEXT (0, numVerts);
83 	rb_arraysLocked = qTrue;
84 }
85 
86 
87 /*
88 =============
89 RB_UnlockArrays
90 =============
91 */
RB_UnlockArrays(void)92 void RB_UnlockArrays (void)
93 {
94 	if (!rb_arraysLocked)
95 		return;
96 
97 	qglUnlockArraysEXT ();
98 	rb_arraysLocked = qFalse;
99 }
100 
101 
102 /*
103 =============
104 RB_ResetPointers
105 =============
106 */
RB_ResetPointers(void)107 void RB_ResetPointers (void)
108 {
109 	rb.inColors = NULL;
110 	rb.inCoords = NULL;
111 	rb.inIndices = NULL;
112 	rb.inLMCoords = NULL;
113 	rb.inNormals = NULL;
114 	rb.inSVectors = NULL;
115 	rb.inTVectors = NULL;
116 	rb.inVertices = NULL;
117 
118 #ifdef SHADOW_VOLUMES
119 	rb.inNeighbors = rb.batch.neighbors;
120 	rb.inTrNormals = rb.batch.trNormals;
121 
122 	rb.curTrNeighbor = rb.inNeighbors;
123 	rb.curTrNormal = rb.inTrNormals[0];
124 #endif
125 
126 	rb.curEntity = NULL;
127 	rb.curDLightBits = 0;
128 	rb.curLMTexNum = -1;
129 	rb.curMeshFeatures = 0;
130 	rb.curMeshType = MBT_MAX;
131 	rb.curModel = NULL;
132 	rb.curPatchWidth = 0;
133 	rb.curPatchHeight = 0;
134 	rb.curShader = NULL;
135 
136 	rb.curTexFog = NULL;
137 	rb.curColorFog = NULL;
138 
139 	rb.numIndexes = 0;
140 	rb.numVerts = 0;
141 
142 	rb_arraysLocked = qFalse;
143 	rb_numPasses = 0;
144 }
145 
146 /*
147 ===============================================================================
148 
149 	PASS HANDLING
150 
151 ===============================================================================
152 */
153 
154 /*
155 =============
156 RB_SetupColorFog
157 =============
158 */
RB_SetupColorFog(const shaderPass_t * pass,int numColors)159 static void RB_SetupColorFog (const shaderPass_t *pass, int numColors)
160 {
161 	byte	*bArray;
162 	double	dist, vdist;
163 	cBspPlane_t *fogPlane, globalFogPlane;
164 	vec3_t	viewtofog;
165 	double	fogNormal[3], vpnNormal[3];
166 	double	fogDist, vpnDist, fogShaderDist;
167 	int		fogptype;
168 	qBool	alphaFog;
169 	float	c, a;
170 	int		i;
171 
172 	if ((pass->blendSource != GL_SRC_ALPHA && pass->blendDest != GL_SRC_ALPHA)
173 	&& (pass->blendSource != GL_ONE_MINUS_SRC_ALPHA && pass->blendDest != GL_ONE_MINUS_SRC_ALPHA))
174 		alphaFog = qFalse;
175 	else
176 		alphaFog = qTrue;
177 
178 	fogPlane = rb.curColorFog->visiblePlane;
179 	if (!fogPlane) {
180 		Vec3Set (globalFogPlane.normal, 0, 0, 1);
181 		globalFogPlane.dist = ri.scn.worldModel->bspModel.nodes[0].c.maxs[2] + 1;
182 		globalFogPlane.type = PLANE_Z;
183 		fogPlane = &globalFogPlane;
184 	}
185 
186 	fogShaderDist = rb.curColorFog->shader->fogDist;
187 	dist = PlaneDiff (ri.def.viewOrigin, fogPlane);
188 
189 	if (rb.curShader->flags & SHADER_SKY) {
190 		if (dist > 0)
191 			Vec3Scale (fogPlane->normal, -dist, viewtofog);
192 		else
193 			Vec3Clear (viewtofog);
194 	}
195 	else
196 		Vec3Copy (rb.curEntity->origin, viewtofog);
197 
198 	vpnNormal[0] = DotProduct (rb.curEntity->axis[0], ri.def.viewAxis[0]) * fogShaderDist * rb.curEntity->scale;
199 	vpnNormal[1] = DotProduct (rb.curEntity->axis[1], ri.def.viewAxis[0]) * fogShaderDist * rb.curEntity->scale;
200 	vpnNormal[2] = DotProduct (rb.curEntity->axis[2], ri.def.viewAxis[0]) * fogShaderDist * rb.curEntity->scale;
201 	vpnDist = ((ri.def.viewOrigin[0] - viewtofog[0]) * ri.def.viewAxis[0][0]
202 				+ (ri.def.viewOrigin[1] - viewtofog[1]) * ri.def.viewAxis[0][1]
203 				+ (ri.def.viewOrigin[2] - viewtofog[2]) * ri.def.viewAxis[0][2])
204 				* fogShaderDist;
205 
206 	bArray = rb_outColorArray[0];
207 	if (dist < 0) {
208 		// Camera is inside the fog
209 		for (i=0 ; i<numColors ; i++, bArray+=4) {
210 			c = DotProduct (rb.inVertices[i], vpnNormal) - vpnDist;
211 			a = (1.0f - bound (0, c, 1.0f)) * (1.0 / 255.0);
212 
213 			if (alphaFog) {
214 				bArray[3] = FloatToByte ((float)bArray[3]*a);
215 			}
216 			else {
217 				bArray[0] = FloatToByte ((float)bArray[0]*a);
218 				bArray[1] = FloatToByte ((float)bArray[1]*a);
219 				bArray[2] = FloatToByte ((float)bArray[2]*a);
220 			}
221 		}
222 	}
223 	else {
224 		fogNormal[0] = DotProduct (rb.curEntity->axis[0], fogPlane->normal) * rb.curEntity->scale;
225 		fogNormal[1] = DotProduct (rb.curEntity->axis[1], fogPlane->normal) * rb.curEntity->scale;
226 		fogNormal[2] = DotProduct (rb.curEntity->axis[2], fogPlane->normal) * rb.curEntity->scale;
227 		fogptype = (fogNormal[0] == 1.0 ? PLANE_X : (fogNormal[1] == 1.0 ? PLANE_Y : (fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL)));
228 		if (fogptype > 2)
229 			Vec3Scale (fogNormal, fogShaderDist, fogNormal);
230 		fogDist = (fogPlane->dist - DotProduct (viewtofog, fogPlane->normal)) * fogShaderDist;
231 		dist *= fogShaderDist;
232 
233 		for (i=0 ; i<numColors ; i++, bArray+=4) {
234 			if (fogptype < 3)
235 				vdist = rb.inVertices[i][fogptype] * fogShaderDist - fogDist;
236 			else
237 				vdist = DotProduct (rb.inVertices[i], fogNormal) - fogDist;
238 
239 			if (vdist < 0) {
240 				c = (DotProduct (rb.inVertices[i], vpnNormal) - vpnDist) * vdist / (vdist - dist);
241 				a = (1.0f - bound (0, c, 1.0f)) * (1.0 / 255.0);
242 
243 				if (alphaFog) {
244 					bArray[3] = FloatToByte ((float)bArray[3]*a);
245 				}
246 				else {
247 					bArray[0] = FloatToByte ((float)bArray[0]*a);
248 					bArray[1] = FloatToByte ((float)bArray[1]*a);
249 					bArray[2] = FloatToByte ((float)bArray[2]*a);
250 				}
251 			}
252 		}
253 	}
254 }
255 
256 
257 /*
258 =============
259 RB_SetupColorFast
260 =============
261 */
RB_SetupColorFast(const shaderPass_t * pass)262 static qBool RB_SetupColorFast (const shaderPass_t *pass)
263 {
264 	const shaderFunc_t *rgbGenFunc, *alphaGenFunc;
265 	byte		*inArray;
266 	bvec4_t		color;
267 	float		*table, c, a;
268 
269 	rgbGenFunc = &pass->rgbGen.func;
270 	alphaGenFunc = &pass->alphaGen.func;
271 	inArray = rb.inColors[0];
272 
273 	// Get the RGB
274 	switch (pass->rgbGen.type) {
275 	case RGB_GEN_UNKNOWN:
276 	case RGB_GEN_IDENTITY:
277 		color[0] = color[1] = color[2] = 255;
278 		break;
279 
280 	case RGB_GEN_IDENTITY_LIGHTING:
281 		color[0] = color[1] = color[2] = rb_identityLighting;
282 		break;
283 
284 	case RGB_GEN_CONST:
285 		color[0] = pass->rgbGen.bArgs[0];
286 		color[1] = pass->rgbGen.bArgs[1];
287 		color[2] = pass->rgbGen.bArgs[2];
288 		break;
289 
290 	case RGB_GEN_COLORWAVE:
291 		table = RB_TableForFunc (rgbGenFunc->type);
292 		c = rb_shaderTime * rgbGenFunc->args[3] + rgbGenFunc->args[2];
293 		c = FTABLE_EVALUATE(table, c) * rgbGenFunc->args[1] + rgbGenFunc->args[0];
294 		a = pass->rgbGen.fArgs[0] * c; color[0] = FloatToByte (bound (0, a, 1));
295 		a = pass->rgbGen.fArgs[1] * c; color[1] = FloatToByte (bound (0, a, 1));
296 		a = pass->rgbGen.fArgs[2] * c; color[2] = FloatToByte (bound (0, a, 1));
297 		break;
298 
299 	case RGB_GEN_ENTITY:
300 		color[0] = rb.curEntity->color[0];
301 		color[1] = rb.curEntity->color[1];
302 		color[2] = rb.curEntity->color[2];
303 		break;
304 
305 	case RGB_GEN_ONE_MINUS_ENTITY:
306 		color[0] = 255 - rb.curEntity->color[0];
307 		color[1] = 255 - rb.curEntity->color[1];
308 		color[2] = 255 - rb.curEntity->color[2];
309 		break;
310 
311 	default:
312 		return qFalse;
313 	}
314 
315 	// Get the alpha
316 	switch (pass->alphaGen.type) {
317 	case ALPHA_GEN_UNKNOWN:
318 	case ALPHA_GEN_IDENTITY:
319 		color[3] = 255;
320 		break;
321 
322 	case ALPHA_GEN_CONST:
323 		color[3] = FloatToByte (pass->alphaGen.args[0]);
324 		break;
325 
326 	case ALPHA_GEN_ENTITY:
327 		color[3] = rb.curEntity->color[3];
328 		break;
329 
330 	case ALPHA_GEN_WAVE:
331 		table = RB_TableForFunc (alphaGenFunc->type);
332 		a = alphaGenFunc->args[2] + rb_shaderTime * alphaGenFunc->args[3];
333 		a = FTABLE_EVALUATE(table, a) * alphaGenFunc->args[1] + alphaGenFunc->args[0];
334 		color[3] = FloatToByte (bound (0.0f, a, 1.0f));
335 		break;
336 
337 	default:
338 		return qFalse;
339 	}
340 
341 	qglDisableClientState (GL_COLOR_ARRAY);
342 	qglColor4ubv (color);
343 	return qTrue;
344 }
345 
346 
347 /*
348 =============
349 RB_SetupColor
350 =============
351 */
RB_SetupColor(const shaderPass_t * pass)352 static void RB_SetupColor (const shaderPass_t *pass)
353 {
354 	const shaderFunc_t *rgbGenFunc, *alphaGenFunc;
355 	int		r, g, b;
356 	float	*table, c, a;
357 	byte	*bArray, *inArray;
358 	int		numColors, i;
359 	vec3_t	t, v;
360 
361 	rgbGenFunc = &pass->rgbGen.func;
362 	alphaGenFunc = &pass->alphaGen.func;
363 
364 	// Optimal case
365 	if (pass->flags & SHADER_PASS_NOCOLORARRAY && !rb.curColorFog) {
366 		if (RB_SetupColorFast (pass))
367 			return;
368 		numColors = 1;
369 	}
370 	else
371 		numColors = rb.numVerts;
372 
373 	// Color generation
374 	bArray = rb_outColorArray[0];
375 	inArray = rb.inColors[0];
376 	switch (pass->rgbGen.type) {
377 	case RGB_GEN_UNKNOWN:
378 	case RGB_GEN_IDENTITY:
379 		for (i=0 ; i<numColors ; i++, bArray+=4) {
380 			bArray[0] = 255;
381 			bArray[1] = 255;
382 			bArray[2] = 255;
383 		}
384 		break;
385 
386 	case RGB_GEN_IDENTITY_LIGHTING:
387 		for (i=0 ; i<numColors ; i++, bArray+=4) {
388 			bArray[0] = rb_identityLighting;
389 			bArray[1] = rb_identityLighting;
390 			bArray[2] = rb_identityLighting;
391 		}
392 		break;
393 
394 	case RGB_GEN_CONST:
395 		r = pass->rgbGen.bArgs[0];
396 		g = pass->rgbGen.bArgs[1];
397 		b = pass->rgbGen.bArgs[2];
398 
399 		for (i=0 ; i<numColors ; i++, bArray+=4) {
400 			bArray[0] = r;
401 			bArray[1] = g;
402 			bArray[2] = b;
403 		}
404 		break;
405 
406 	case RGB_GEN_COLORWAVE:
407 		table = RB_TableForFunc (rgbGenFunc->type);
408 		c = rb_shaderTime * rgbGenFunc->args[3] + rgbGenFunc->args[2];
409 		c = FTABLE_EVALUATE(table, c) * rgbGenFunc->args[1] + rgbGenFunc->args[0];
410 		a = pass->rgbGen.fArgs[0] * c; r = FloatToByte (bound (0, a, 1));
411 		a = pass->rgbGen.fArgs[1] * c; g = FloatToByte (bound (0, a, 1));
412 		a = pass->rgbGen.fArgs[2] * c; b = FloatToByte (bound (0, a, 1));
413 
414 		for (i=0 ; i<numColors ; i++, bArray+=4) {
415 			bArray[0] = r;
416 			bArray[1] = g;
417 			bArray[2] = b;
418 		}
419 		break;
420 
421 	case RGB_GEN_ENTITY:
422 		r = *(int *)rb.curEntity->color;
423 		for (i=0 ; i<numColors ; i++, bArray+=4)
424 			*(int *)bArray = r;
425 		break;
426 
427 	case RGB_GEN_ONE_MINUS_ENTITY:
428 		for (i=0 ; i<numColors ; i++, bArray+=4) {
429 			bArray[0] = 255 - rb.curEntity->color[0];
430 			bArray[1] = 255 - rb.curEntity->color[1];
431 			bArray[2] = 255 - rb.curEntity->color[2];
432 		}
433 		break;
434 
435 	case RGB_GEN_VERTEX:
436 		if (intensity->intVal > 0) {
437 			for (i=0 ; i<numColors ; i++, bArray+=4, inArray+=4) {
438 				bArray[0] = inArray[0] >> (intensity->intVal / 2);
439 				bArray[1] = inArray[1] >> (intensity->intVal / 2);
440 				bArray[2] = inArray[2] >> (intensity->intVal / 2);
441 			}
442 			break;
443 		}
444 
445 	// FALL THROUGH
446 	case RGB_GEN_EXACT_VERTEX:
447 		for (i=0 ; i<numColors ; i++, bArray+=4, inArray+=4) {
448 			bArray[0] = inArray[0];
449 			bArray[1] = inArray[1];
450 			bArray[2] = inArray[2];
451 		}
452 		break;
453 
454 	case RGB_GEN_ONE_MINUS_VERTEX:
455 		if (intensity->intVal > 0) {
456 			for (i=0 ; i<numColors ; i++, bArray+=4, inArray+=4) {
457 				bArray[0] = 255 - (inArray[0] >> (intensity->intVal / 2));
458 				bArray[1] = 255 - (inArray[1] >> (intensity->intVal / 2));
459 				bArray[2] = 255 - (inArray[2] >> (intensity->intVal / 2));
460 			}
461 			break;
462 		}
463 
464 	// FALL THROUGH
465 	case RGB_GEN_ONE_MINUS_EXACT_VERTEX:
466 		for (i=0 ; i<numColors ; i++, bArray+=4, inArray+=4) {
467 			bArray[0] = 255 - inArray[0];
468 			bArray[1] = 255 - inArray[1];
469 			bArray[2] = 255 - inArray[2];
470 		}
471 		break;
472 
473 	case RGB_GEN_LIGHTING_DIFFUSE:
474 		R_LightForEntity (rb.curEntity, numColors, bArray);
475 		break;
476 
477 	case RGB_GEN_FOG:
478 		for (i=0 ; i<numColors ; i++, bArray+=4) {
479 			bArray[0] = rb.curTexFog->shader->fogColor[0];
480 			bArray[1] = rb.curTexFog->shader->fogColor[1];
481 			bArray[2] = rb.curTexFog->shader->fogColor[2];
482 		}
483 		break;
484 
485 	default:
486 		assert (0);
487 		break;
488 	}
489 
490 	// Alpha generation
491 	bArray = rb_outColorArray[0];
492 	inArray = rb.inColors[0];
493 	switch (pass->alphaGen.type) {
494 	case ALPHA_GEN_UNKNOWN:
495 	case ALPHA_GEN_IDENTITY:
496 		for (i=0 ; i<numColors ; i++, bArray+=4) {
497 			bArray[3] = 255;
498 		}
499 		break;
500 
501 	case ALPHA_GEN_CONST:
502 		b = FloatToByte (pass->alphaGen.args[0]);
503 		for (i=0 ; i<numColors ; i++, bArray+=4)
504 			bArray[3] = b;
505 		break;
506 
507 	case ALPHA_GEN_WAVE:
508 		table = RB_TableForFunc (alphaGenFunc->type);
509 		a = alphaGenFunc->args[2] + rb_shaderTime * alphaGenFunc->args[3];
510 		a = FTABLE_EVALUATE(table, a) * alphaGenFunc->args[1] + alphaGenFunc->args[0];
511 		b = FloatToByte (bound (0.0f, a, 1.0f));
512 		for (i=0 ; i<numColors ; i++, bArray+=4)
513 			bArray[3] = b;
514 		break;
515 
516 	case ALPHA_GEN_PORTAL:
517 		Vec3Add (rb.inVertices[0], rb.curEntity->origin, v);
518 		Vec3Subtract (ri.def.viewOrigin, v, t);
519 		a = Vec3Length (t) * pass->alphaGen.args[0];
520 		b = FloatToByte (clamp (a, 0.0f, 1.0f));
521 
522 		for (i=0 ; i<numColors ; i++, bArray+=4)
523 			bArray[3] = b;
524 		break;
525 
526 	case ALPHA_GEN_VERTEX:
527 		for (i=0 ; i<numColors ; i++, bArray+=4, inArray+=4)
528 			bArray[3] = inArray[3];
529 		break;
530 
531 	case ALPHA_GEN_ONE_MINUS_VERTEX:
532 		for (i=0 ; i<numColors ; i++, bArray+=4, inArray+=4)
533 			bArray[3] = 255 - inArray[3];
534 
535 	case ALPHA_GEN_ENTITY:
536 		for (i=0 ; i<numColors ; i++, bArray+=4)
537 			bArray[3] = rb.curEntity->color[3];
538 		break;
539 
540 	case ALPHA_GEN_SPECULAR:
541 		Vec3Subtract (ri.def.viewOrigin, rb.curEntity->origin, t);
542 		if (!Matrix3_Compare (rb.curEntity->axis, axisIdentity))
543 			Matrix3_TransformVector (rb.curEntity->axis, t, v);
544 		else
545 			Vec3Copy (t, v);
546 
547 		for (i=0 ; i<numColors ; i++, bArray+=4) {
548 			Vec3Subtract (v, rb.inVertices[i], t);
549 			a = DotProduct (t, rb.inNormals[i]) * Q_RSqrtf (DotProduct (t, t));
550 			a = a * a * a * a * a;
551 			bArray[3] = FloatToByte (bound (0.0f, a, 1.0f));
552 		}
553 		break;
554 
555 	case ALPHA_GEN_DOT:
556 		if (!Matrix3_Compare (rb.curEntity->axis, axisIdentity))
557 			Matrix3_TransformVector (rb.curEntity->axis, ri.def.viewAxis[0], v);
558 		else
559 			Vec3Copy (ri.def.viewAxis[0], v);
560 
561 		for (i=0 ; i<numColors ; i++, bArray+=4) {
562 			a = DotProduct (v, rb.inNormals[i]);
563 			if (a < 0)
564 				a = -a;
565 			bArray[3] = FloatToByte (bound (pass->alphaGen.args[0], a, pass->alphaGen.args[1]));
566 		}
567 		break;
568 
569 	case ALPHA_GEN_ONE_MINUS_DOT:
570 		if (!Matrix3_Compare (rb.curEntity->axis, axisIdentity))
571 			Matrix3_TransformVector (rb.curEntity->axis, ri.def.viewAxis[0], v);
572 		else
573 			Vec3Copy (ri.def.viewAxis[0], v);
574 
575 		for (i=0 ; i<numColors ; i++, bArray+=4) {
576 			a = DotProduct (v, rb.inNormals[i]);
577 			if (a < 0)
578 				a = -a;
579 			a = 1.0f - a;
580 			bArray[3] = FloatToByte (bound (pass->alphaGen.args[0], a, pass->alphaGen.args[1]));
581 		}
582 		break;
583 
584 	case ALPHA_GEN_FOG:
585 		for (i=0 ; i<numColors ; i++, bArray+=4)
586 			bArray[3] = rb.curTexFog->shader->fogColor[3];
587 		break;
588 
589 	default:
590 		assert (0);
591 		break;
592 	}
593 
594 	// Colored fog
595 	if (rb.curColorFog)
596 		RB_SetupColorFog (pass, numColors);
597 
598 	// Set color
599 	if (numColors == 1) {
600 		qglDisableClientState (GL_COLOR_ARRAY);
601 		qglColor4ubv (rb_outColorArray[0]);
602 	}
603 	else {
604 		qglEnableClientState (GL_COLOR_ARRAY);
605 		qglColorPointer (4, GL_UNSIGNED_BYTE, 0, rb_outColorArray);
606 	}
607 }
608 
609 
610 /*
611 =============
612 RB_ModifyTextureCoordsGeneric
613 
614 Standard path
615 =============
616 */
617 static const float r_warpSinTable[] = {
618 	0.000000f,	0.098165f,	0.196270f,	0.294259f,	0.392069f,	0.489643f,	0.586920f,	0.683850f,
619 	0.780360f,	0.876405f,	0.971920f,	1.066850f,	1.161140f,	1.254725f,	1.347560f,	1.439580f,
620 	1.530735f,	1.620965f,	1.710220f,	1.798445f,	1.885585f,	1.971595f,	2.056410f,	2.139990f,
621 	2.222280f,	2.303235f,	2.382795f,	2.460925f,	2.537575f,	2.612690f,	2.686235f,	2.758160f,
622 	2.828425f,	2.896990f,	2.963805f,	3.028835f,	3.092040f,	3.153385f,	3.212830f,	3.270340f,
623 	3.325880f,	3.379415f,	3.430915f,	3.480350f,	3.527685f,	3.572895f,	3.615955f,	3.656840f,
624 	3.695520f,	3.731970f,	3.766175f,	3.798115f,	3.827760f,	3.855105f,	3.880125f,	3.902810f,
625 	3.923140f,	3.941110f,	3.956705f,	3.969920f,	3.980740f,	3.989160f,	3.995180f,	3.998795f,
626 	4.000000f,	3.998795f,	3.995180f,	3.989160f,	3.980740f,	3.969920f,	3.956705f,	3.941110f,
627 	3.923140f,	3.902810f,	3.880125f,	3.855105f,	3.827760f,	3.798115f,	3.766175f,	3.731970f,
628 	3.695520f,	3.656840f,	3.615955f,	3.572895f,	3.527685f,	3.480350f,	3.430915f,	3.379415f,
629 	3.325880f,	3.270340f,	3.212830f,	3.153385f,	3.092040f,	3.028835f,	2.963805f,	2.896990f,
630 	2.828425f,	2.758160f,	2.686235f,	2.612690f,	2.537575f,	2.460925f,	2.382795f,	2.303235f,
631 	2.222280f,	2.139990f,	2.056410f,	1.971595f,	1.885585f,	1.798445f,	1.710220f,	1.620965f,
632 	1.530735f,	1.439580f,	1.347560f,	1.254725f,	1.161140f,	1.066850f,	0.971920f,	0.876405f,
633 	0.780360f,	0.683850f,	0.586920f,	0.489643f,	0.392069f,	0.294259f,	0.196270f,	0.098165f,
634 	0.000000f,	-0.098165f,	-0.196270f,	-0.294259f,	-0.392069f,	-0.489643f,	-0.586920f,	-0.683850f,
635 	-0.780360f,	-0.876405f,	-0.971920f,	-1.066850f,	-1.161140f,	-1.254725f,	-1.347560f,	-1.439580f,
636 	-1.530735f,	-1.620965f,	-1.710220f,	-1.798445f,	-1.885585f,	-1.971595f,	-2.056410f,	-2.139990f,
637 	-2.222280f,	-2.303235f,	-2.382795f,	-2.460925f,	-2.537575f,	-2.612690f,	-2.686235f,	-2.758160f,
638 	-2.828425f,	-2.896990f,	-2.963805f,	-3.028835f,	-3.092040f,	-3.153385f,	-3.212830f,	-3.270340f,
639 	-3.325880f,	-3.379415f,	-3.430915f,	-3.480350f,	-3.527685f,	-3.572895f,	-3.615955f,	 -3.656840f,
640 	-3.695520f,	-3.731970f,	-3.766175f,	-3.798115f,	-3.827760f,	-3.855105f,	-3.880125f,	-3.902810f,
641 	-3.923140f,	-3.941110f,	-3.956705f,	-3.969920f,	-3.980740f,	-3.989160f,	-3.995180f,	-3.998795f,
642 	-4.000000f,	-3.998795f,	-3.995180f,	-3.989160f,	-3.980740f,	-3.969920f,	-3.956705f,	-3.941110f,
643 	-3.923140f,	-3.902810f,	-3.880125f,	-3.855105f,	-3.827760f,	-3.798115f,	-3.766175f,	-3.731970f,
644 	-3.695520f,	-3.656840f,	-3.615955f,	-3.572895f,	-3.527685f,	-3.480350f,	-3.430915f,	-3.379415f,
645 	-3.325880f,	-3.270340f,	-3.212830f,	-3.153385f,	-3.092040f,	-3.028835f,	-2.963805f,	-2.896990f,
646 	-2.828425f,	-2.758160f,	-2.686235f,	-2.612690f,	-2.537575f,	-2.460925f,	-2.382795f,	-2.303235f,
647 	-2.222280f,	-2.139990f,	-2.056410f,	-1.971595f,	-1.885585f,	-1.798445f,	-1.710220f,	-1.620965f,
648 	-1.530735f,	-1.439580f,	-1.347560f,	-1.254725f,	-1.161140f,	-1.066850f,	-0.971920f,	-0.876405f,
649 	-0.780360f,	-0.683850f,	-0.586920f,	-0.489643f,	-0.392069f,	 -0.294259f,-0.196270f,	-0.098165f
650 };
RB_VertexTCBaseGeneric(shaderPass_t * pass,texUnit_t texUnit)651 static void RB_VertexTCBaseGeneric (shaderPass_t *pass, texUnit_t texUnit)
652 {
653 	float		*outCoords, depth;
654 	vec3_t		transform;
655 	vec3_t		n, projection;
656 	mat3x3_t	inverseAxis;
657 	int			i;
658 
659 	outCoords = rb_outCoordArray[texUnit][0];
660 
661 	// State
662 	switch (pass->tcGen) {
663 	case TC_GEN_REFLECTION:
664 		qglEnable (GL_TEXTURE_GEN_S);
665 		qglEnable (GL_TEXTURE_GEN_T);
666 		qglEnable (GL_TEXTURE_GEN_R);
667 		qglEnableClientState (GL_NORMAL_ARRAY);
668 		break;
669 
670 	default:
671 		qglDisable (GL_TEXTURE_GEN_S);
672 		qglDisable (GL_TEXTURE_GEN_T);
673 		qglDisable (GL_TEXTURE_GEN_R);
674 		qglDisableClientState (GL_NORMAL_ARRAY);
675 		break;
676 	}
677 
678 	// tcGen
679 	switch (pass->tcGen) {
680 	case TC_GEN_BASE:
681 		if (pass->numTCMods) {
682 			for (i=0 ; i<rb.numVerts ; i++) {
683 				rb_outCoordArray[texUnit][i][0] = rb.inCoords[i][0];
684 				rb_outCoordArray[texUnit][i][1] = rb.inCoords[i][1];
685 			}
686 			break;
687 		}
688 
689 		qglTexCoordPointer (2, GL_FLOAT, 0, rb.inCoords);
690 		return;
691 
692 	case TC_GEN_LIGHTMAP:
693 		if (pass->numTCMods) {
694 			for (i=0 ; i<rb.numVerts ; i++) {
695 				rb_outCoordArray[texUnit][i][0] = rb.inLMCoords[i][0];
696 				rb_outCoordArray[texUnit][i][1] = rb.inLMCoords[i][1];
697 			}
698 			break;
699 		}
700 
701 		qglTexCoordPointer (2, GL_FLOAT, 0, rb.inLMCoords);
702 		return;
703 
704 	case TC_GEN_ENVIRONMENT:
705 		if (rb_glState.in2D) {
706 			for (i=0 ; i<rb.numVerts ; i++) {
707 				rb_outCoordArray[texUnit][i][0] = rb.inCoords[i][0];
708 				rb_outCoordArray[texUnit][i][1] = rb.inCoords[i][1];
709 			}
710 			return;
711 		}
712 
713 		if (rb.curModel) {
714 			if (rb.curModel == ri.scn.worldModel) {
715 				Vec3Subtract (vec3Origin, ri.def.viewOrigin, transform);
716 			}
717 			else {
718 				Vec3Subtract (rb.curEntity->origin, ri.def.viewOrigin, transform);
719 				Matrix3_Transpose (rb.curEntity->axis, inverseAxis);
720 			}
721 		}
722 		else {
723 			Vec3Clear (transform);
724 			Matrix3_Transpose (axisIdentity, inverseAxis);
725 		}
726 
727 		for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
728 			Vec3Add (rb.inVertices[i], transform, projection);
729 			VectorNormalizeFastf (projection);
730 
731 			// Project vector
732 			if (rb.curModel && rb.curModel == ri.scn.worldModel)
733 				Vec3Copy (rb.inNormals[i], n);
734 			else
735 				Matrix3_TransformVector (inverseAxis, rb.inNormals[i], n);
736 
737 			depth = -2.0f * DotProduct (n, projection);
738 			Vec3MA (projection, depth, n, projection);
739 			depth = Q_FastSqrt (DotProduct (projection, projection) * 4);
740 
741 			outCoords[0] = -((projection[1] * depth) + 0.5f);
742 			outCoords[1] = ((projection[2] * depth) + 0.5f);
743 		}
744 		break;
745 
746 	case TC_GEN_VECTOR:
747 		for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
748 			outCoords[0] = DotProduct (pass->tcGenVec[0], rb.inVertices[i]) + pass->tcGenVec[0][3];
749 			outCoords[1] = DotProduct (pass->tcGenVec[1], rb.inVertices[i]) + pass->tcGenVec[1][3];
750 		}
751 		break;
752 
753 	case TC_GEN_REFLECTION:
754 		qglTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
755 		qglTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
756 		qglTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
757 
758 		qglNormalPointer (GL_FLOAT, 12, rb.inNormals);
759 		break;
760 
761 
762 	case TC_GEN_WARP:
763 		for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
764 			outCoords[0] = rb.inCoords[i][0] + (r_warpSinTable[Q_ftol (((rb.inCoords[i][1]*8.0f + rb_shaderTime) * (256.0f / (M_PI * 2.0f)))) & 255] * (1.0/64));
765 			outCoords[1] = rb.inCoords[i][1] + (r_warpSinTable[Q_ftol (((rb.inCoords[i][0]*8.0f + rb_shaderTime) * (256.0f / (M_PI * 2.0f)))) & 255] * (1.0/64));
766 		}
767 		break;
768 
769 	case TC_GEN_DLIGHT:
770 		return;
771 
772 	case TC_GEN_FOG:
773 		{
774 			int			fogPtype;
775 			cBspPlane_t	*fogPlane, globalFogPlane;
776 			shader_t	*fogShader;
777 			vec3_t		viewtofog;
778 			double		fogNormal[3], vpnNormal[3];
779 			double		dist, vdist, fogDist, vpnDist;
780 			vec3_t		fogVPN;
781 
782 			fogPlane = rb.curTexFog->visiblePlane;
783 			if (!fogPlane) {
784 				Vec3Set (globalFogPlane.normal, 0, 0, 1);
785 				globalFogPlane.dist = ri.scn.worldModel->bspModel.nodes[0].c.maxs[2] + 1;
786 				globalFogPlane.type = PLANE_Z;
787 				fogPlane = &globalFogPlane;
788 			}
789 			fogShader = rb.curTexFog->shader;
790 
791 			// Distance to fog
792 			dist = PlaneDiff (ri.def.viewOrigin, fogPlane);
793 			if (rb.curShader->flags & SHADER_SKY) {
794 				if (dist > 0)
795 					Vec3MA (ri.def.viewOrigin, -dist, fogPlane->normal, viewtofog);
796 				else
797 					Vec3Copy (ri.def.viewOrigin, viewtofog);
798 			}
799 			else
800 				Vec3Copy (rb.curEntity->origin, viewtofog);
801 
802 			Vec3Scale (ri.def.viewAxis[0], fogShader->fogDist, fogVPN);
803 
804 			// Fog settings
805 			fogNormal[0] = DotProduct (rb.curEntity->axis[0], fogPlane->normal) * rb.curEntity->scale;
806 			fogNormal[1] = DotProduct (rb.curEntity->axis[1], fogPlane->normal) * rb.curEntity->scale;
807 			fogNormal[2] = DotProduct (rb.curEntity->axis[2], fogPlane->normal) * rb.curEntity->scale;
808 			fogPtype = (fogNormal[0] == 1.0 ? PLANE_X : (fogNormal[1] == 1.0 ? PLANE_Y : (fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL)));
809 			fogDist = (fogPlane->dist - DotProduct (viewtofog, fogPlane->normal));
810 
811 			// Forward view normal/distance
812 			vpnNormal[0] = DotProduct (rb.curEntity->axis[0], fogVPN) * rb.curEntity->scale;
813 			vpnNormal[1] = DotProduct (rb.curEntity->axis[1], fogVPN) * rb.curEntity->scale;
814 			vpnNormal[2] = DotProduct (rb.curEntity->axis[2], fogVPN) * rb.curEntity->scale;
815 			vpnDist = ((ri.def.viewOrigin[0] - viewtofog[0]) * fogVPN[0]
816 						+ (ri.def.viewOrigin[1] - viewtofog[1]) * fogVPN[1]
817 						+ (ri.def.viewOrigin[2] - viewtofog[2]) * fogVPN[2]);
818 
819 			if (dist < 0) {
820 				// Camera is inside the fog brush
821 				if (fogPtype < 3) {
822 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
823 						outCoords[0] = DotProduct (rb.inVertices[i], vpnNormal) - vpnDist;
824 						outCoords[1] = -(rb.inVertices[i][fogPtype] - fogDist);
825 					}
826 				}
827 				else {
828 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
829 						outCoords[0] = DotProduct (rb.inVertices[i], vpnNormal) - vpnDist;
830 						outCoords[1] = -(DotProduct (rb.inVertices[i], fogNormal) - fogDist);
831 					}
832 				}
833 			}
834 			else {
835 				if (fogPtype < 3) {
836 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
837 						vdist = rb.inVertices[i][fogPtype] - fogDist;
838 						outCoords[0] = ((vdist < 0) ? (DotProduct (rb.inVertices[i], vpnNormal) - vpnDist) * vdist / (vdist - dist) : 0.0f);
839 						outCoords[1] = -vdist;
840 					}
841 				}
842 				else {
843 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
844 						vdist = DotProduct (rb.inVertices[i], fogNormal) - fogDist;
845 						outCoords[0] = ((vdist < 0) ? (DotProduct (rb.inVertices[i], vpnNormal) - vpnDist) * vdist / (vdist - dist) : 0.0f);
846 						outCoords[1] = -vdist;
847 					}
848 				}
849 			}
850 
851 			outCoords = rb_outCoordArray[texUnit][0];
852 			for (i=0 ; i<rb.numVerts ; i++, outCoords+=2)
853 				outCoords[1] *= fogShader->fogDist + 1.5f/(float)FOGTEX_HEIGHT;
854 		}
855 		break;
856 
857 	default:
858 		assert (0);
859 		break;
860 	}
861 
862 	qglTexCoordPointer (2, GL_FLOAT, 0, rb_outCoordArray[texUnit][0]);
863 }
RB_ModifyTextureCoordsGeneric(shaderPass_t * pass,texUnit_t texUnit)864 static void RB_ModifyTextureCoordsGeneric (shaderPass_t *pass, texUnit_t texUnit)
865 {
866 	int		i, j;
867 	float	*table;
868 	float	t1, t2, sint, cost;
869 	float	*tcArray;
870 	tcMod_t	*tcMod;
871 
872 	RB_VertexTCBaseGeneric (pass, texUnit);
873 
874 	for (i=0, tcMod=pass->tcMods ; i<pass->numTCMods ; tcMod++, i++) {
875 		tcArray = rb_outCoordArray[texUnit][0];
876 
877 		switch (tcMod->type) {
878 		case TC_MOD_ROTATE:
879 			cost = tcMod->args[0] * rb_shaderTime;
880 			sint = RB_FastSin (cost);
881 			cost = RB_FastSin (cost + 0.25);
882 
883 			for (j=0 ; j<rb.numVerts ; j++, tcArray+=2) {
884 				t1 = tcArray[0];
885 				t2 = tcArray[1];
886 				tcArray[0] = cost * (t1 - 0.5f) - sint * (t2 - 0.5f) + 0.5f;
887 				tcArray[1] = cost * (t2 - 0.5f) + sint * (t1 - 0.5f) + 0.5f;
888 			}
889 			break;
890 
891 		case TC_MOD_SCALE:
892 			t1 = tcMod->args[0];
893 			t2 = tcMod->args[1];
894 
895 			for (j=0 ; j<rb.numVerts ; j++, tcArray+=2) {
896 				tcArray[0] = tcArray[0] * t1;
897 				tcArray[1] = tcArray[1] * t2;
898 			}
899 			break;
900 
901 		case TC_MOD_TURB:
902 			t1 = tcMod->args[1];
903 			t2 = tcMod->args[2] + rb_shaderTime * tcMod->args[3];
904 
905 			for (j=0 ; j<rb.numVerts ; j++, tcArray+=2) {
906 				tcArray[0] = tcArray[0] + t1 * RB_FastSin (tcArray[0] * t1 + t2);
907 				tcArray[1] = tcArray[1] + t1 * RB_FastSin (tcArray[1] * t1 + t2);
908 			}
909 			break;
910 
911 		case TC_MOD_STRETCH:
912 			table = RB_TableForFunc (tcMod->args[0]);
913 			t2 = tcMod->args[3] + rb_shaderTime * tcMod->args[4];
914 			t1 = FTABLE_EVALUATE(table, t2) * tcMod->args[2] + tcMod->args[1];
915 			t1 = t1 ? 1.0f / t1 : 1.0f;
916 			t2 = 0.5f - 0.5f * t1;
917 
918 			for (j=0 ; j<rb.numVerts ; j++, tcArray+=2) {
919 				tcArray[0] = tcArray[0] * t1 + t2;
920 				tcArray[1] = tcArray[1] * t1 + t2;
921 			}
922 			break;
923 
924 		case TC_MOD_SCROLL:
925 			t1 = tcMod->args[0] * rb_shaderTime; t1 = t1 - floor (t1);
926 			t2 = tcMod->args[1] * rb_shaderTime; t2 = t2 - floor (t2);
927 
928 			for (j=0 ; j<rb.numVerts ; j++, tcArray+=2) {
929 				tcArray[0] = tcArray[0] + t1;
930 				tcArray[1] = tcArray[1] + t2;
931 			}
932 			break;
933 
934 		case TC_MOD_TRANSFORM:
935 			for (j=0 ; j<rb.numVerts ; j++, tcArray+=2) {
936 				t1 = tcArray[0];
937 				t2 = tcArray[1];
938 				tcArray[0] = t1 * tcMod->args[0] + t2 * tcMod->args[2] + tcMod->args[4];
939 				tcArray[1] = t2 * tcMod->args[1] + t1 * tcMod->args[3] + tcMod->args[5];
940 			}
941 			break;
942 
943 		default:
944 			assert (0);
945 			break;
946 		}
947 	}
948 }
949 
950 
951 /*
952 =============
953 RB_ModifyTextureCoordsMatrix
954 
955 Matrix path
956 =============
957 */
RB_ApplyTCModsMatrix(shaderPass_t * pass,mat4x4_t result)958 static void RB_ApplyTCModsMatrix (shaderPass_t *pass, mat4x4_t result)
959 {
960 	mat4x4_t	m1, m2;
961 	float		t1, t2, sint, cost;
962 	float		*table;
963 	tcMod_t		*tcMod;
964 	int			i;
965 
966 	for (i=0, tcMod=pass->tcMods ; i<pass->numTCMods ; tcMod++, i++) {
967 		switch (tcMod->type) {
968 		case TC_MOD_ROTATE:
969 			cost = tcMod->args[0] * rb_shaderTime;
970 			sint = RB_FastSin (cost);
971 			cost = RB_FastSin (cost + 0.25);
972 			m2[0] =  cost, m2[1] = sint, m2[12] =  0.5f * (sint - cost + 1);
973 			m2[4] = -sint, m2[5] = cost, m2[13] = -0.5f * (sint + cost - 1);
974 			Matrix4_Copy2D (result, m1);
975 			Matrix4_Multiply2D (m2, m1, result);
976 			break;
977 
978 		case TC_MOD_SCALE:
979 			Matrix4_Scale2D (result, tcMod->args[0], tcMod->args[1]);
980 			break;
981 
982 		case TC_MOD_TURB:
983 			t1 = (1.0f / 4.0f);
984 			t2 = tcMod->args[2] + rb_shaderTime * tcMod->args[3];
985 			Matrix4_Scale2D (result, 1 + (tcMod->args[1] * RB_FastSin (t2) + tcMod->args[0]) * t1, 1 + (tcMod->args[1] * RB_FastSin (t2 + 0.25f) + tcMod->args[0]) * t1);
986 			break;
987 
988 		case TC_MOD_STRETCH:
989 			table = RB_TableForFunc (tcMod->args[0]);
990 			t2 = tcMod->args[3] + rb_shaderTime * tcMod->args[4];
991 			t1 = FTABLE_EVALUATE (table, t2) * tcMod->args[2] + tcMod->args[1];
992 			t1 = t1 ? 1.0f / t1 : 1.0f;
993 			t2 = 0.5f - 0.5f * t1;
994 			Matrix4_Stretch2D (result, t1, t2);
995 			break;
996 
997 		case TC_MOD_SCROLL:
998 			t1 = tcMod->args[0] * rb_shaderTime; t1 = t1 - floor (t1);
999 			t2 = tcMod->args[1] * rb_shaderTime; t2 = t2 - floor (t2);
1000 			Matrix4_Translate2D (result, t1, t2);
1001 			break;
1002 
1003 		case TC_MOD_TRANSFORM:
1004 			m2[0] = tcMod->args[0], m2[1] = tcMod->args[2], m2[12] = tcMod->args[4],
1005 			m2[5] = tcMod->args[1], m2[4] = tcMod->args[3], m2[13] = tcMod->args[5];
1006 			Matrix4_Copy2D (result, m1);
1007 			Matrix4_Multiply2D (m2, m1, result);
1008 			break;
1009 
1010 		default:
1011 			assert (0);
1012 			break;
1013 		}
1014 	}
1015 }
RB_VertexTCBaseMatrix(shaderPass_t * pass,texUnit_t texUnit,mat4x4_t matrix)1016 static qBool RB_VertexTCBaseMatrix (shaderPass_t *pass, texUnit_t texUnit, mat4x4_t matrix)
1017 {
1018 	vec3_t		transform;
1019 	vec3_t		n, projection;
1020 	mat3x3_t	inverseAxis;
1021 	float		depth;
1022 	int			i;
1023 
1024 	Matrix4_Identity (matrix);
1025 
1026 	// State
1027 	switch (pass->tcGen) {
1028 	case TC_GEN_REFLECTION:
1029 		qglEnable (GL_TEXTURE_GEN_S);
1030 		qglEnable (GL_TEXTURE_GEN_T);
1031 		qglEnable (GL_TEXTURE_GEN_R);
1032 		qglEnableClientState (GL_NORMAL_ARRAY);
1033 		break;
1034 
1035 	case TC_GEN_VECTOR:
1036 		qglEnable (GL_TEXTURE_GEN_S);
1037 		qglEnable (GL_TEXTURE_GEN_T);
1038 		qglDisable (GL_TEXTURE_GEN_R);
1039 		qglDisableClientState (GL_NORMAL_ARRAY);
1040 		break;
1041 
1042 	default:
1043 		qglDisable (GL_TEXTURE_GEN_S);
1044 		qglDisable (GL_TEXTURE_GEN_T);
1045 		qglDisable (GL_TEXTURE_GEN_R);
1046 		qglDisableClientState (GL_NORMAL_ARRAY);
1047 		break;
1048 	}
1049 
1050 	// tcGen
1051 	switch (pass->tcGen) {
1052 	case TC_GEN_BASE:
1053 		qglTexCoordPointer (2, GL_FLOAT, 0, rb.inCoords);
1054 		return qTrue;
1055 
1056 	case TC_GEN_LIGHTMAP:
1057 		qglTexCoordPointer (2, GL_FLOAT, 0, rb.inLMCoords);
1058 		return qTrue;
1059 
1060 	case TC_GEN_ENVIRONMENT:
1061 		if (rb_glState.in2D)
1062 			return qTrue;
1063 
1064 		matrix[0] = matrix[12] = -0.5f;
1065 		matrix[5] = matrix[13] = 0.5f;
1066 
1067 		Vec3Subtract (ri.def.viewOrigin, rb.curEntity->origin, transform);
1068 		Matrix3_Transpose (rb.curEntity->axis, inverseAxis);
1069 
1070 		if (Matrix3_Compare (inverseAxis, axisIdentity)) {
1071 			for (i=0 ; i<rb.numVerts ; i++) {
1072 				Vec3Subtract (rb.inVertices[i], transform, projection);
1073 				VectorNormalizeFastf (projection);
1074 				Vec3Copy (rb.inNormals[i], n);
1075 
1076 				// Project vector
1077 				depth = -DotProduct (n, projection);
1078 				depth += depth;
1079 				Vec3MA (projection, depth, n, projection);
1080 				depth = Q_RSqrtf (DotProduct (projection, projection));
1081 
1082 				rb_outCoordArray[texUnit][i][0] = projection[1] * depth;
1083 				rb_outCoordArray[texUnit][i][1] = projection[2] * depth;
1084 			}
1085 		}
1086 		else {
1087 			for (i=0 ; i<rb.numVerts ; i++) {
1088 				Vec3Subtract (rb.inVertices[i], transform, projection);
1089 				VectorNormalizeFastf (projection);
1090 				Matrix3_TransformVector (inverseAxis, rb.inNormals[i], n);
1091 
1092 				// Project vector
1093 				depth = -DotProduct (n, projection);
1094 				depth += depth;
1095 				Vec3MA (projection, depth, n, projection);
1096 				depth = Q_RSqrtf (DotProduct (projection, projection));
1097 
1098 				rb_outCoordArray[texUnit][i][0] = projection[1] * depth;
1099 				rb_outCoordArray[texUnit][i][1] = projection[2] * depth;
1100 			}
1101 		}
1102 
1103 		qglTexCoordPointer (2, GL_FLOAT, 0, rb_outCoordArray[texUnit][0]);
1104 		return qFalse;
1105 
1106 	case TC_GEN_VECTOR:
1107 		{
1108 			GLfloat genVector[2][4];
1109 
1110 			for (i=0 ; i<3 ; i++) {
1111 				genVector[0][i] = pass->tcGenVec[0][i];
1112 				genVector[1][i] = pass->tcGenVec[1][i];
1113 				genVector[0][3] = genVector[1][3] = 0;
1114 			}
1115 
1116 			matrix[12] = pass->tcGenVec[0][3];
1117 			matrix[13] = pass->tcGenVec[1][3];
1118 
1119 			qglTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1120 			qglTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1121 			qglTexGenfv (GL_S, GL_OBJECT_PLANE, genVector[0]);
1122 			qglTexGenfv (GL_T, GL_OBJECT_PLANE, genVector[1]);
1123 			return qFalse;
1124 		}
1125 
1126 	case TC_GEN_REFLECTION:
1127 		qglTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
1128 		qglTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
1129 		qglTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
1130 
1131 		qglNormalPointer (GL_FLOAT, 12, rb.inNormals);
1132 		return qTrue;
1133 
1134 	case TC_GEN_WARP:
1135 		for (i=0 ; i<rb.numVerts ; i++) {
1136 			rb_outCoordArray[texUnit][i][0] = rb.inCoords[i][0] + (r_warpSinTable[Q_ftol (((rb.inCoords[i][1]*8.0f + rb_shaderTime) * (256.0f / (M_PI * 2.0f)))) & 255] * (1.0/64));
1137 			rb_outCoordArray[texUnit][i][1] = rb.inCoords[i][1] + (r_warpSinTable[Q_ftol (((rb.inCoords[i][0]*8.0f + rb_shaderTime) * (256.0f / (M_PI * 2.0f)))) & 255] * (1.0/64));
1138 		}
1139 
1140 		qglTexCoordPointer (2, GL_FLOAT, 0, rb_outCoordArray[texUnit][0]);
1141 		return qTrue;
1142 
1143 	case TC_GEN_DLIGHT:
1144 		return qTrue;
1145 
1146 	case TC_GEN_FOG:
1147 		{
1148 			int			fogPtype;
1149 			cBspPlane_t	*fogPlane, globalFogPlane;
1150 			shader_t	*fogShader;
1151 			vec3_t		viewtofog;
1152 			double		fogNormal[3], vpnNormal[3];
1153 			double		dist, vdist, fogDist, vpnDist;
1154 			float		*outCoords;
1155 
1156 			fogPlane = rb.curTexFog->visiblePlane;
1157 			if (!fogPlane) {
1158 				Vec3Set (globalFogPlane.normal, 0, 0, 1);
1159 				globalFogPlane.dist = ri.scn.worldModel->bspModel.nodes[0].c.maxs[2] + 1;
1160 				globalFogPlane.type = PLANE_Z;
1161 				fogPlane = &globalFogPlane;
1162 			}
1163 			fogShader = rb.curTexFog->shader;
1164 
1165 			matrix[0] = matrix[5] = fogShader->fogDist;
1166 			matrix[13] = 1.5/(float)FOGTEX_HEIGHT;
1167 
1168 			// Distance to fog
1169 			dist = PlaneDiff (ri.def.viewOrigin, fogPlane);
1170 
1171 			if (rb.curShader->flags & SHADER_SKY) {
1172 				if (dist > 0)
1173 					Vec3MA (ri.def.viewOrigin, -dist, fogPlane->normal, viewtofog);
1174 				else
1175 					Vec3Copy (ri.def.viewOrigin, viewtofog);
1176 			}
1177 			else
1178 				Vec3Copy (rb.curEntity->origin, viewtofog);
1179 
1180 			// Fog settings
1181 			fogNormal[0] = DotProduct (rb.curEntity->axis[0], fogPlane->normal) * rb.curEntity->scale;
1182 			fogNormal[1] = DotProduct (rb.curEntity->axis[1], fogPlane->normal) * rb.curEntity->scale;
1183 			fogNormal[2] = DotProduct (rb.curEntity->axis[2], fogPlane->normal) * rb.curEntity->scale;
1184 			fogPtype = (fogNormal[0] == 1.0 ? PLANE_X : (fogNormal[1] == 1.0 ? PLANE_Y : (fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL)));
1185 			fogDist = (fogPlane->dist - DotProduct (viewtofog, fogPlane->normal));
1186 
1187 			// Forward view normal/distance
1188 			vpnNormal[0] = DotProduct (rb.curEntity->axis[0], ri.def.viewAxis[0]) * rb.curEntity->scale;
1189 			vpnNormal[1] = DotProduct (rb.curEntity->axis[1], ri.def.viewAxis[0]) * rb.curEntity->scale;
1190 			vpnNormal[2] = DotProduct (rb.curEntity->axis[2], ri.def.viewAxis[0]) * rb.curEntity->scale;
1191 			vpnDist = ((ri.def.viewOrigin[0] - viewtofog[0]) * ri.def.viewAxis[0][0]
1192 						+ (ri.def.viewOrigin[1] - viewtofog[1]) * ri.def.viewAxis[0][1]
1193 						+ (ri.def.viewOrigin[2] - viewtofog[2]) * ri.def.viewAxis[0][2]);
1194 
1195 			outCoords = rb_outCoordArray[texUnit][0];
1196 			if (dist < 0) {
1197 				// Camera is inside the fog brush
1198 				if (fogPtype < 3) {
1199 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
1200 						outCoords[0] = DotProduct (rb.inVertices[i], vpnNormal) - vpnDist;
1201 						outCoords[1] = -(rb.inVertices[i][fogPtype] - fogDist);
1202 					}
1203 				}
1204 				else {
1205 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
1206 						outCoords[0] = DotProduct (rb.inVertices[i], vpnNormal) - vpnDist;
1207 						outCoords[1] = -(DotProduct (rb.inVertices[i], fogNormal) - fogDist);
1208 					}
1209 				}
1210 			}
1211 			else {
1212 				if (fogPtype < 3) {
1213 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
1214 						vdist = rb.inVertices[i][fogPtype] - fogDist;
1215 						outCoords[0] = ((vdist < 0) ? (DotProduct (rb.inVertices[i], vpnNormal) - vpnDist) * vdist / (vdist - dist) : 0.0f);
1216 						outCoords[1] = -vdist;
1217 					}
1218 				}
1219 				else {
1220 					for (i=0 ; i<rb.numVerts ; i++, outCoords+=2) {
1221 						vdist = DotProduct (rb.inVertices[i], fogNormal) - fogDist;
1222 						outCoords[0] = ((vdist < 0) ? (DotProduct (rb.inVertices[i], vpnNormal) - vpnDist) * vdist / (vdist - dist) : 0.0f);
1223 						outCoords[1] = -vdist;
1224 					}
1225 				}
1226 			}
1227 
1228 			qglTexCoordPointer (2, GL_FLOAT, 0, rb_outCoordArray[texUnit][0]);
1229 			return qFalse;
1230 		}
1231 	}
1232 
1233 	// Should never reach here...
1234 	assert (0);
1235 	return qTrue;
1236 }
RB_ModifyTextureCoordsMatrix(shaderPass_t * pass,texUnit_t texUnit)1237 static void RB_ModifyTextureCoordsMatrix (shaderPass_t *pass, texUnit_t texUnit)
1238 {
1239 	mat4x4_t	m1, m2, result;
1240 	qBool		identityMatrix;
1241 
1242 	// Texture coordinate base
1243 	identityMatrix = RB_VertexTCBaseMatrix (pass, texUnit, result);
1244 
1245 	// Texture coordinate modifications
1246 	qglMatrixMode (GL_TEXTURE);
1247 
1248 	if (pass->numTCMods) {
1249 		identityMatrix = qFalse;
1250 		RB_ApplyTCModsMatrix (pass, result);
1251 	}
1252 
1253 	if (pass->tcGen == TC_GEN_REFLECTION) {
1254 		Matrix4_Transpose (ri.scn.modelViewMatrix, m1);
1255 		Matrix4_Copy (result, m2);
1256 		Matrix4_Multiply (m2, m1, result);
1257 		RB_LoadTexMatrix (result);
1258 		return;
1259 	}
1260 
1261 	// Load identity
1262 	if (identityMatrix)
1263 		RB_LoadIdentityTexMatrix ();
1264 	else
1265 		RB_LoadTexMatrix (result);
1266 }
1267 
1268 
1269 /*
1270 =============
1271 RB_DeformVertices
1272 =============
1273 */
RB_DeformVertices(void)1274 static void RB_DeformVertices (void)
1275 {
1276 	vertDeform_t	*vertDeform;
1277 	float			args[4], deflect;
1278 	float			*quadIn[4], *quadOut[4], *table, now;
1279 	int				i, j, k;
1280 	uint32			l, m, p;
1281 	vec3_t			tv, rot_centre;
1282 
1283 	// Deformations
1284 	vertDeform = &rb.curShader->deforms[0];
1285 	for (i=0 ; i<rb.curShader->numDeforms ; i++, vertDeform++) {
1286 		switch (vertDeform->type) {
1287 		case DEFORMV_NONE:
1288 			break;
1289 
1290 		case DEFORMV_WAVE:
1291 			table = RB_TableForFunc (vertDeform->func.type);
1292 			now = vertDeform->func.args[2] + vertDeform->func.args[3] * rb_shaderTime;
1293 
1294 			for (j=0 ; j<rb.numVerts ; j++) {
1295 				deflect = (rb.inVertices[j][0] + rb.inVertices[j][1] + rb.inVertices[j][2]) * vertDeform->args[0] + now;
1296 				deflect = FTABLE_EVALUATE (table, deflect) * vertDeform->func.args[1] + vertDeform->func.args[0];
1297 
1298 				// Deflect vertex along its normal by wave amount
1299 				Vec3MA (rb.inVertices[j], deflect, rb.inNormals[j], rb_outVertexArray[j]);
1300 			}
1301 			break;
1302 
1303 		case DEFORMV_NORMAL:
1304 			args[0] = vertDeform->args[1] * rb_shaderTime;
1305 
1306 			for (j=0 ; j<rb.numVerts ; j++) {
1307 				args[1] = rb.inNormals[j][2] * args[0];
1308 
1309 				deflect = vertDeform->args[0] * RB_FastSin (args[1]);
1310 				rb.inNormals[j][0] *= deflect;
1311 				deflect = vertDeform->args[0] * RB_FastSin (args[1] + 0.25);
1312 				rb.inNormals[j][1] *= deflect;
1313 
1314 				VectorNormalizeFastf (rb.inNormals[j]);
1315 			}
1316 			break;
1317 
1318 		case DEFORMV_BULGE:
1319 			args[0] = vertDeform->args[0] / (float)rb.curPatchHeight;
1320 			args[1] = vertDeform->args[1];
1321 			args[2] = rb_shaderTime / (vertDeform->args[2] * rb.curPatchWidth);
1322 
1323 			for (l=0, p=0 ; l<rb.curPatchHeight ; l++) {
1324 				deflect = RB_FastSin ((float)l * args[0] + args[2]) * args[1];
1325 				for (m=0 ; m<rb.curPatchWidth ; m++, p++)
1326 					Vec3MA (rb.inVertices[p], deflect, rb.inNormals[p], rb_outVertexArray[p]);
1327 			}
1328 			break;
1329 
1330 		case DEFORMV_MOVE:
1331 			table = RB_TableForFunc (vertDeform->func.type);
1332 			deflect = vertDeform->func.args[2] + rb_shaderTime * vertDeform->func.args[3];
1333 			deflect = FTABLE_EVALUATE(table, deflect) * vertDeform->func.args[1] + vertDeform->func.args[0];
1334 
1335 			for (j=0 ; j<rb.numVerts ; j++)
1336 				Vec3MA (rb.inVertices[j], deflect, vertDeform->args, rb_outVertexArray[j]);
1337 			break;
1338 
1339 		case DEFORMV_AUTOSPRITE:
1340 			{
1341 				mat3x3_t	m0, m1, m2, result;
1342 
1343 				if (rb.numIndexes % 6)
1344 					break;
1345 
1346 				if (rb.curModel && rb.curModel == ri.scn.worldModel)
1347 					Matrix4_Matrix3 (ri.scn.worldViewMatrix, m1);
1348 				else
1349 					Matrix4_Matrix3 (ri.scn.modelViewMatrix, m1);
1350 
1351 				Matrix3_Transpose (m1, m2);
1352 
1353 				for (k=0 ; k<rb.numIndexes ; k+=6) {
1354 					quadIn[0] = (float *)(rb.inVertices + rb.inIndices[k+0]);
1355 					quadIn[1] = (float *)(rb.inVertices + rb.inIndices[k+1]);
1356 					quadIn[2] = (float *)(rb.inVertices + rb.inIndices[k+2]);
1357 
1358 					quadOut[0] = (float *)(rb_outVertexArray + rb.inIndices[k+0]);
1359 					quadOut[1] = (float *)(rb_outVertexArray + rb.inIndices[k+1]);
1360 					quadOut[2] = (float *)(rb_outVertexArray + rb.inIndices[k+2]);
1361 
1362 					for (j=2 ; j>=0 ; j--) {
1363 						quadIn[3] = (float *)(rb.inVertices + rb.inIndices[k+3+j]);
1364 						if (!Vec3Compare (quadIn[3], quadIn[0])
1365 						&& !Vec3Compare (quadIn[3], quadIn[1])
1366 						&& !Vec3Compare (quadIn[3], quadIn[2])) {
1367 							quadOut[3] = (float *)(rb_outVertexArray + rb.inIndices[k+3+j]);
1368 							break;
1369 						}
1370 					}
1371 
1372 					Matrix3_FromPoints (quadIn[0], quadIn[1], quadIn[2], m0);
1373 
1374 					// Swap m0[0] an m0[1] - FIXME?
1375 					Vec3Copy (m0[1], rot_centre);
1376 					Vec3Copy (m0[0], m0[1]);
1377 					Vec3Copy (rot_centre, m0[0]);
1378 
1379 					Matrix3_Multiply (m2, m0, result);
1380 
1381 					rot_centre[0] = (quadIn[0][0] + quadIn[1][0] + quadIn[2][0] + quadIn[3][0]) * 0.25f;
1382 					rot_centre[1] = (quadIn[0][1] + quadIn[1][1] + quadIn[2][1] + quadIn[3][1]) * 0.25f;
1383 					rot_centre[2] = (quadIn[0][2] + quadIn[1][2] + quadIn[2][2] + quadIn[3][2]) * 0.25f;
1384 
1385 					for (j=0 ; j<4 ; j++) {
1386 						Vec3Subtract (quadIn[j], rot_centre, tv);
1387 						Matrix3_TransformVector (result, tv, quadOut[j]);
1388 						Vec3Add (rot_centre, quadOut[j], quadOut[j]);
1389 					}
1390 				}
1391 			}
1392 			break;
1393 
1394 		case DEFORMV_AUTOSPRITE2:
1395 			if (rb.numIndexes % 6)
1396 				break;
1397 
1398 			for (k=0 ; k<rb.numIndexes ; k+=6) {
1399 				int			long_axis, short_axis;
1400 				vec3_t		axis, tmp, len;
1401 				mat3x3_t	m0, m1, m2, result;
1402 
1403 				quadIn[0] = (float *)(rb.inVertices + rb.inIndices[k+0]);
1404 				quadIn[1] = (float *)(rb.inVertices + rb.inIndices[k+1]);
1405 				quadIn[2] = (float *)(rb.inVertices + rb.inIndices[k+2]);
1406 
1407 				quadOut[0] = (float *)(rb_outVertexArray + rb.inIndices[k+0]);
1408 				quadOut[1] = (float *)(rb_outVertexArray + rb.inIndices[k+1]);
1409 				quadOut[2] = (float *)(rb_outVertexArray + rb.inIndices[k+2]);
1410 
1411 				for (j=2 ; j>=0 ; j--) {
1412 					quadIn[3] = (float *)(rb.inVertices + rb.inIndices[k+3+j]);
1413 
1414 					if (!Vec3Compare (quadIn[3], quadIn[0])
1415 					&& !Vec3Compare (quadIn[3], quadIn[1])
1416 					&& !Vec3Compare (quadIn[3], quadIn[2])) {
1417 						quadOut[3] = (float *)(rb_outVertexArray + rb.inIndices[k+3+j]);
1418 						break;
1419 					}
1420 				}
1421 
1422 				// Build a matrix were the longest axis of the billboard is the Y-Axis
1423 				Vec3Subtract (quadIn[1], quadIn[0], m0[0]);
1424 				Vec3Subtract (quadIn[2], quadIn[0], m0[1]);
1425 				Vec3Subtract (quadIn[2], quadIn[1], m0[2]);
1426 				len[0] = DotProduct (m0[0], m0[0]);
1427 				len[1] = DotProduct (m0[1], m0[1]);
1428 				len[2] = DotProduct (m0[2], m0[2]);
1429 
1430 				if (len[2] > len[1] && len[2] > len[0]) {
1431 					if (len[1] > len[0]) {
1432 						long_axis = 1;
1433 						short_axis = 0;
1434 					}
1435 					else {
1436 						long_axis = 0;
1437 						short_axis = 1;
1438 					}
1439 				}
1440 				else if (len[1] > len[2] && len[1] > len[0]) {
1441 					if (len[2] > len[0]) {
1442 						long_axis = 2;
1443 						short_axis = 0;
1444 					}
1445 					else {
1446 						long_axis = 0;
1447 						short_axis = 2;
1448 					}
1449 				}
1450 				else if (len[0] > len[1] && len[0] > len[2]) {
1451 					if (len[2] > len[1]) {
1452 						long_axis = 2;
1453 						short_axis = 1;
1454 					}
1455 					else {
1456 						long_axis = 1;
1457 						short_axis = 2;
1458 					}
1459 				}
1460 				else {
1461 					// FIXME
1462 					long_axis = 0;
1463 					short_axis = 0;
1464 				}
1465 
1466 				if (!len[long_axis])
1467 					break;
1468 				len[long_axis] = Q_RSqrtf (len[long_axis]);
1469 				Vec3Scale (m0[long_axis], len[long_axis], axis);
1470 
1471 				if (DotProduct (m0[long_axis], m0[short_axis])) {
1472 					Vec3Copy (axis, m0[1]);
1473 					if (axis[0] || axis[1])
1474 						MakeNormalVectorsf (m0[1], m0[0], m0[2]);
1475 					else
1476 						MakeNormalVectorsf (m0[1], m0[2], m0[0]);
1477 				}
1478 				else {
1479 					if (!len[short_axis])
1480 						break;
1481 					len[short_axis] = Q_RSqrtf (len[short_axis]);
1482 					Vec3Scale (m0[short_axis], len[short_axis], m0[0]);
1483 					Vec3Copy (axis, m0[1]);
1484 					CrossProduct (m0[0], m0[1], m0[2]);
1485 				}
1486 
1487 				rot_centre[0] = (quadIn[0][0] + quadIn[1][0] + quadIn[2][0] + quadIn[3][0]) * 0.25f;
1488 				rot_centre[1] = (quadIn[0][1] + quadIn[1][1] + quadIn[2][1] + quadIn[3][1]) * 0.25f;
1489 				rot_centre[2] = (quadIn[0][2] + quadIn[1][2] + quadIn[2][2] + quadIn[3][2]) * 0.25f;
1490 
1491 				if (rb.curModel && rb.curModel == ri.scn.worldModel) {
1492 					Vec3Copy (rot_centre, tv);
1493 					Vec3Subtract (ri.def.viewOrigin, tv, tv);
1494 				}
1495 				else {
1496 					Vec3Add (rb.curEntity->origin, rot_centre, tv);
1497 					Vec3Subtract (ri.def.viewOrigin, tv, tmp);
1498 					Matrix3_TransformVector (rb.curEntity->axis, tmp, tv);
1499 				}
1500 
1501 				// Filter any longest-axis-parts off the camera-direction
1502 				deflect = -DotProduct (tv, axis);
1503 
1504 				Vec3MA (tv, deflect, axis, m1[2]);
1505 				VectorNormalizeFastf (m1[2]);
1506 				Vec3Copy (axis, m1[1]);
1507 				CrossProduct (m1[1], m1[2], m1[0]);
1508 
1509 				Matrix3_Transpose (m1, m2);
1510 				Matrix3_Multiply (m2, m0, result);
1511 
1512 				for (j=0 ; j<4 ; j++) {
1513 					Vec3Subtract (quadIn[j], rot_centre, tv);
1514 					Matrix3_TransformVector (result, tv, quadOut[j]);
1515 					Vec3Add (rot_centre, quadOut[j], quadOut[j]);
1516 				}
1517 			}
1518 			break;
1519 
1520 		case DEFORMV_PROJECTION_SHADOW:
1521 			break;
1522 
1523 		case DEFORMV_AUTOPARTICLE:
1524 			{
1525 				mat3x3_t	m0, m1, m2, result;
1526 				float		scale;
1527 
1528 				if (rb.numIndexes % 6)
1529 					break;
1530 
1531 				if (rb.curModel && rb.curModel == ri.scn.worldModel)
1532 					Matrix4_Matrix3 (ri.scn.worldViewMatrix, m1);
1533 				else
1534 					Matrix4_Matrix3 (ri.scn.modelViewMatrix, m1);
1535 
1536 				Matrix3_Transpose (m1, m2);
1537 
1538 				for (k=0 ; k<rb.numIndexes ; k+=6) {
1539 					quadIn[0] = (float *)(rb.inVertices + rb.inIndices[k+0]);
1540 					quadIn[1] = (float *)(rb.inVertices + rb.inIndices[k+1]);
1541 					quadIn[2] = (float *)(rb.inVertices + rb.inIndices[k+2]);
1542 
1543 					quadOut[0] = (float *)(rb_outVertexArray + rb.inIndices[k+0]);
1544 					quadOut[1] = (float *)(rb_outVertexArray + rb.inIndices[k+1]);
1545 					quadOut[2] = (float *)(rb_outVertexArray + rb.inIndices[k+2]);
1546 
1547 					for (j=2 ; j>=0 ; j--) {
1548 						quadIn[3] = (float *)(rb.inVertices + rb.inIndices[k+3+j]);
1549 
1550 						if (!Vec3Compare (quadIn[3], quadIn[0])
1551 						&& !Vec3Compare (quadIn[3], quadIn[1])
1552 						&& !Vec3Compare (quadIn[3], quadIn[2])) {
1553 							quadOut[3] = (float *)(rb_outVertexArray + rb.inIndices[k+3+j]);
1554 							break;
1555 						}
1556 					}
1557 
1558 					Matrix3_FromPoints (quadIn[0], quadIn[1], quadIn[2], m0);
1559 					Matrix3_Multiply (m2, m0, result);
1560 
1561 					// Hack a scale up to keep particles from disappearing
1562 					scale = (quadIn[0][0] - ri.def.viewOrigin[0]) * ri.def.viewAxis[0][0] +
1563 							(quadIn[0][1] - ri.def.viewOrigin[1]) * ri.def.viewAxis[0][1] +
1564 							(quadIn[0][2] - ri.def.viewOrigin[2]) * ri.def.viewAxis[0][2];
1565 					if (scale < 20)
1566 						scale = 1.5;
1567 					else
1568 						scale = 1.5 + scale * 0.006f;
1569 
1570 					rot_centre[0] = (quadIn[0][0] + quadIn[1][0] + quadIn[2][0] + quadIn[3][0]) * 0.25f;
1571 					rot_centre[1] = (quadIn[0][1] + quadIn[1][1] + quadIn[2][1] + quadIn[3][1]) * 0.25f;
1572 					rot_centre[2] = (quadIn[0][2] + quadIn[1][2] + quadIn[2][2] + quadIn[3][2]) * 0.25f;
1573 
1574 					for (j=0 ; j<4 ; j++) {
1575 						Vec3Subtract (quadIn[j], rot_centre, tv);
1576 						Matrix3_TransformVector (result, tv, quadOut[j]);
1577 						Vec3MA (rot_centre, scale, quadOut[j], quadOut[j]);
1578 					}
1579 				}
1580 			}
1581 			break;
1582 
1583 		default:
1584 			assert (0);
1585 			break;
1586 		}
1587 	}
1588 }
1589 
1590 /*
1591 ===============================================================================
1592 
1593 	MESH RENDERING
1594 
1595 ===============================================================================
1596 */
1597 
1598 /*
1599 =============
1600 RB_DrawElements
1601 =============
1602 */
RB_DrawElements(void)1603 static void RB_DrawElements (void)
1604 {
1605 	if (!rb.numVerts || !rb.numIndexes)
1606 		return;
1607 
1608 	// Flush
1609 	if (ri.config.extDrawRangeElements)
1610 		qglDrawRangeElementsEXT (GL_TRIANGLES, 0, rb.numVerts, rb.numIndexes, GL_UNSIGNED_INT, rb.inIndices);
1611 	else
1612 		qglDrawElements (GL_TRIANGLES, rb.numIndexes, GL_UNSIGNED_INT, rb.inIndices);
1613 
1614 	// Increment performance counters
1615 	if (rb_triangleOutlines || !r_speeds->intVal)
1616 		return;
1617 
1618 	ri.pc.numVerts += rb.numVerts;
1619 	ri.pc.numTris += rb.numIndexes/3;
1620 	ri.pc.numElements++;
1621 
1622 	switch (rb.curMeshType) {
1623 	case MBT_Q2BSP:
1624 	case MBT_Q3BSP:
1625 		ri.pc.worldElements++;
1626 		break;
1627 
1628 	case MBT_ALIAS:
1629 		ri.pc.aliasElements++;
1630 		ri.pc.aliasPolys += rb.numIndexes/3;
1631 		break;
1632 	}
1633 }
1634 
1635 
1636 /*
1637 =============
1638 RB_CleanUpTextureUnits
1639 
1640 This cleans up the texture units not planned to be used in the next render.
1641 =============
1642 */
RB_CleanUpTextureUnits(void)1643 static void RB_CleanUpTextureUnits (void)
1644 {
1645 	texUnit_t		i;
1646 
1647 	if (rb_matrixCoords)
1648 		qglMatrixMode (GL_TEXTURE);
1649 
1650 	for (i=rb_numOldPasses ; i>rb_numPasses ; i--) {
1651 		RB_SelectTexture (i-1);
1652 		RB_TextureTarget (0);
1653 		qglDisable (GL_TEXTURE_GEN_S);
1654 		qglDisable (GL_TEXTURE_GEN_T);
1655 		qglDisable (GL_TEXTURE_GEN_R);
1656 		qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
1657 		RB_LoadIdentityTexMatrix ();
1658 	}
1659 
1660 	if (rb_matrixCoords)
1661 		qglMatrixMode (GL_MODELVIEW);
1662 
1663 	rb_numOldPasses = rb_numPasses;
1664 }
1665 
1666 
1667 /*
1668 =============
1669 RB_BindShaderPass
1670 =============
1671 */
RB_BindShaderPass(shaderPass_t * pass,image_t * image,texUnit_t texUnit)1672 static void RB_BindShaderPass (shaderPass_t *pass, image_t *image, texUnit_t texUnit)
1673 {
1674 	if (!image) {
1675 		// Find the texture
1676 		if (pass->flags & SHADER_PASS_LIGHTMAP)
1677 			image = r_lmTextures[rb.curLMTexNum];
1678 		else if (pass->flags & SHADER_PASS_ANIMMAP)
1679 			image = pass->animImages[(int)(pass->animFPS * rb_shaderTime) % pass->animNumImages];
1680 		else
1681 			image = pass->animImages[0];
1682 
1683 		if (!image)
1684 			image = ri.noTexture;
1685 	}
1686 
1687 	// Bind the texture
1688 	RB_SelectTexture (texUnit);
1689 	RB_BindTexture (image);
1690 
1691 	// FIXME: This is kind of hacky
1692 	RB_TextureTarget (image->target);
1693 	if (image->flags & (IT_3D|IT_CUBEMAP))
1694 		qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
1695 	else
1696 		qglEnableClientState (GL_TEXTURE_COORD_ARRAY);
1697 
1698 	// Modify the texture coordinates
1699 	RB_ModifyTextureCoords (pass, texUnit);
1700 }
1701 
1702 
1703 /*
1704 =============
1705 RB_SetupPassState
1706 =============
1707 */
RB_SetupPassState(shaderPass_t * pass,qBool mTex)1708 static void RB_SetupPassState (shaderPass_t *pass, qBool mTex)
1709 {
1710 	program_t	*program;
1711 	uint32		sb1;
1712 
1713 	sb1 = rb_stateBits1|pass->stateBits1;
1714 
1715 	// Vertex program
1716 	if (pass->flags & SHADER_PASS_VERTEXPROGRAM) {
1717 		program = pass->vertProgPtr;
1718 
1719 		qglEnable (GL_VERTEX_PROGRAM_ARB);
1720 		RB_BindProgram (program);
1721 
1722 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 0, ri.def.viewOrigin[0], ri.def.viewOrigin[1], ri.def.viewOrigin[2], 0);
1723 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 1, ri.def.viewAxis[0][0], ri.def.viewAxis[0][1], ri.def.viewAxis[0][2], 0);
1724 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 2, ri.def.rightVec[0], ri.def.rightVec[1], ri.def.rightVec[2], 0);
1725 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 3, ri.def.viewAxis[2][0], ri.def.viewAxis[2][1], ri.def.viewAxis[2][2], 0);
1726 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 4, rb.curEntity->origin[0], rb.curEntity->origin[1], rb.curEntity->origin[2], 0);
1727 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 5, rb.curEntity->axis[0][0], rb.curEntity->axis[0][1], rb.curEntity->axis[0][2], 0);
1728 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 6, rb.curEntity->axis[1][0], rb.curEntity->axis[1][1], rb.curEntity->axis[1][2], 0);
1729 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 7, rb.curEntity->axis[2][0], rb.curEntity->axis[2][1], rb.curEntity->axis[2][2], 0);
1730 		qglProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 8, rb_shaderTime, 0, 0, 0);
1731 	}
1732 	else if (ri.config.extVertexProgram)
1733 		qglDisable (GL_VERTEX_PROGRAM_ARB);
1734 
1735 	// Fragment program
1736 	if (pass->flags & SHADER_PASS_FRAGMENTPROGRAM) {
1737 		program = pass->fragProgPtr;
1738 
1739 		qglEnable (GL_FRAGMENT_PROGRAM_ARB);
1740 		RB_BindProgram (program);
1741 
1742 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, ri.def.viewOrigin[0], ri.def.viewOrigin[1], ri.def.viewOrigin[2], 0);
1743 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, ri.def.viewAxis[0][0], ri.def.viewAxis[0][1], ri.def.viewAxis[0][2], 0);
1744 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 2, ri.def.rightVec[0], ri.def.rightVec[1], ri.def.rightVec[2], 0);
1745 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 3, ri.def.viewAxis[2][0], ri.def.viewAxis[2][1], ri.def.viewAxis[2][2], 0);
1746 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 4, rb.curEntity->origin[0], rb.curEntity->origin[1], rb.curEntity->origin[2], 0);
1747 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 5, rb.curEntity->axis[0][0], rb.curEntity->axis[0][1], rb.curEntity->axis[0][2], 0);
1748 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 6, rb.curEntity->axis[1][0], rb.curEntity->axis[1][1], rb.curEntity->axis[1][2], 0);
1749 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 7, rb.curEntity->axis[2][0], rb.curEntity->axis[2][1], rb.curEntity->axis[2][2], 0);
1750 		qglProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 8, rb_shaderTime, 0, 0, 0);
1751 	}
1752 	else if (ri.config.extFragmentProgram)
1753 		qglDisable (GL_FRAGMENT_PROGRAM_ARB);
1754 
1755 	// Blending
1756 	if (pass->flags & SHADER_PASS_BLEND) {
1757 		sb1 |= SB1_BLEND_ON;
1758 	}
1759 	else if (rb.curEntity->flags & RF_TRANSLUCENT) {
1760 		// FIXME: necessary Quake2 hack
1761 		sb1 &= ~(SB1_BLENDSRC_BITS|SB1_BLENDDST_BITS);
1762 		sb1 |= SB1_BLEND_ON|SB1_BLENDSRC_SRC_ALPHA|SB1_BLENDDST_ONE_MINUS_SRC_ALPHA;
1763 	}
1764 
1765 	// Nasty hack!!!
1766 	if (!rb_glState.in2D) {
1767 		qglDepthFunc (pass->depthFunc);
1768 		if (pass->flags & SHADER_PASS_DEPTHWRITE && !(rb.curEntity->flags & RF_TRANSLUCENT)) // FIXME: necessary Quake2 hack
1769 			sb1 |= SB1_DEPTHMASK_ON;
1770 	}
1771 
1772 	// Mask colors
1773 	if (pass->totalMask)
1774 		qglColorMask (!pass->maskRed, !pass->maskGreen, !pass->maskBlue, !pass->maskAlpha);
1775 	else
1776 		qglColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1777 
1778 	// Commit
1779 	RB_StateForBits (sb1);
1780 }
1781 
1782 
1783 /*
1784 =================
1785 RB_RenderDLights
1786 
1787 Special case for rendering Q3BSP dynamic light attenuation.
1788 =================
1789 */
RB_RenderDLights(void)1790 static void RB_RenderDLights (void)
1791 {
1792 	int				j;
1793 	refDLight_t		*light;
1794 	byte			*outColor;
1795 	float			dist;
1796 	vec3_t			tempVec, lightOrigin;
1797 	float			scale;
1798 	GLfloat			s[4], t[4], r[4];
1799 	shaderPass_t	*pass;
1800 	uint32			num;
1801 
1802 	// Set state
1803 	pass = rb_accumPasses[0];
1804 	RB_BindShaderPass (pass, ri.dLightTexture, 0);
1805 	RB_SetupPassState (pass, qFalse);
1806 	RB_TextureEnv (GL_MODULATE);
1807 
1808 	// Texture state
1809 	if (ri.config.extTex3D) {
1810 		qglEnable (GL_TEXTURE_GEN_S);
1811 		qglTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1812 		s[1] = s[2] = 0;
1813 
1814 		qglEnable (GL_TEXTURE_GEN_T);
1815 		qglTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1816 		t[0] = t[2] = 0;
1817 
1818 		qglEnable (GL_TEXTURE_GEN_R);
1819 		qglTexGeni (GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1820 		r[0] = r[1] = 0;
1821 
1822 		qglDisableClientState (GL_COLOR_ARRAY);
1823 	}
1824 	else {
1825 		qglEnable (GL_TEXTURE_GEN_S);
1826 		qglTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1827 		s[1] = s[2] = 0;
1828 
1829 		qglEnable (GL_TEXTURE_GEN_T);
1830 		qglTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
1831 		t[0] = t[2] = 0;
1832 
1833 		qglDisable (GL_TEXTURE_GEN_R);
1834 
1835 		qglEnableClientState (GL_COLOR_ARRAY);
1836 		qglColorPointer (4, GL_UNSIGNED_BYTE, 0, rb.batch.colors);
1837 	}
1838 
1839 	for (num=0, light=ri.scn.dLightList ; num<ri.scn.numDLights ; num++, light++) {
1840 		if (!(rb.curDLightBits & (1<<num)))
1841 			continue;	// Not lit by this light
1842 
1843 		// Transform
1844 		Vec3Subtract (light->origin, rb.curEntity->origin, lightOrigin);
1845 		if (!Matrix3_Compare (rb.curEntity->axis, axisIdentity)) {
1846 			Vec3Copy (lightOrigin, tempVec);
1847 			Matrix3_TransformVector (rb.curEntity->axis, tempVec, lightOrigin);
1848 		}
1849 
1850 		scale = 1.0f / light->intensity;
1851 
1852 		// Calculate coordinates
1853 		s[0] = scale;
1854 		s[3] = (-lightOrigin[0] * scale) + 0.5f;
1855 		qglTexGenfv (GL_S, GL_OBJECT_PLANE, s);
1856 
1857 		t[1] = scale;
1858 		t[3] = (-lightOrigin[1] * scale) + 0.5f;
1859 		qglTexGenfv (GL_T, GL_OBJECT_PLANE, t);
1860 
1861 		if (ri.config.extTex3D) {
1862 			// Color
1863 			qglColor3fv (light->color);
1864 
1865 			// Depth coordinate
1866 			r[2] = scale;
1867 			r[3] = (-lightOrigin[2] * scale) + 0.5f;
1868 			qglTexGenfv (GL_R, GL_OBJECT_PLANE, r);
1869 		}
1870 		else {
1871 			// Color
1872 			outColor = rb.batch.colors[0];
1873 			for (j=0 ; j<rb.numVerts ; j++) {
1874 				dist = (rb.inVertices[j][2] - lightOrigin[2]) * 2;
1875 				if (dist < 0)
1876 					dist = -dist;
1877 
1878 				if (dist < light->intensity) {
1879 					outColor[0] = FloatToByte (light->color[0]);
1880 					outColor[1] = FloatToByte (light->color[1]);
1881 					outColor[2] = FloatToByte (light->color[2]);
1882 				}
1883 				else {
1884 					dist = Q_RSqrtf (dist * dist - light->intensity * light->intensity);
1885 					dist = clamp (dist, 0, 1);
1886 
1887 					outColor[0] = FloatToByte (dist * light->color[0]);
1888 					outColor[1] = FloatToByte (dist * light->color[1]);
1889 					outColor[2] = FloatToByte (dist * light->color[2]);
1890 				}
1891 				outColor[3] = 255;
1892 
1893 				// Next
1894 				outColor += 4;
1895 			}
1896 		}
1897 
1898 		// Render
1899 		RB_DrawElements ();
1900 	}
1901 }
1902 
1903 
1904 /*
1905 =============
1906 RB_RenderGeneric
1907 =============
1908 */
RB_RenderGeneric(void)1909 static void RB_RenderGeneric (void)
1910 {
1911 	shaderPass_t	*pass;
1912 
1913 	pass = rb_accumPasses[0];
1914 
1915 	RB_BindShaderPass (pass, NULL, 0);
1916 	RB_SetupColor (pass);
1917 	RB_SetupPassState (pass, qFalse);
1918 	if (pass->blendMode == GL_REPLACE)
1919 		RB_TextureEnv (GL_REPLACE);
1920 	else
1921 		RB_TextureEnv (GL_MODULATE);
1922 
1923 	RB_DrawElements ();
1924 }
1925 
1926 
1927 /*
1928 =============
1929 RB_RenderCombine
1930 =============
1931 */
RB_RenderCombine(void)1932 static void RB_RenderCombine (void)
1933 {
1934 	shaderPass_t	*pass;
1935 	int				i;
1936 
1937 	pass = rb_accumPasses[0];
1938 
1939 	RB_BindShaderPass (pass, NULL, 0);
1940 	RB_SetupColor (pass);
1941 	RB_SetupPassState (pass, qTrue);
1942 	RB_TextureEnv (GL_MODULATE);
1943 
1944 	for (i=1 ; i<rb_numPasses ; i++) {
1945 		pass = rb_accumPasses[i];
1946 		RB_BindShaderPass (pass, NULL, i);
1947 
1948 		switch (pass->blendMode) {
1949 		case GL_REPLACE:
1950 		case GL_MODULATE:
1951 			RB_TextureEnv (GL_MODULATE);
1952 			break;
1953 
1954 		case GL_ADD:
1955 			// These modes are best set with TexEnv, Combine4 would need much more setup
1956 			RB_TextureEnv (GL_ADD);
1957 			break;
1958 
1959 		case GL_DECAL:
1960 			// Mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, they�re added
1961 			// this way it can be possible to use GL_DECAL in both texture-units, while still looking good
1962 			// normal mutlitexturing would multiply the alpha-channel which looks ugly
1963 			RB_TextureEnv (GL_COMBINE_ARB);
1964 			qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1965 			qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
1966 
1967 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1968 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1969 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
1970 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1971 
1972 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
1973 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1974 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
1975 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
1976 
1977 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1978 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
1979 			break;
1980 
1981 		default:
1982 			RB_TextureEnv (GL_COMBINE4_NV);
1983 
1984 			qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
1985 			qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
1986 
1987 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1988 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1989 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
1990 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1991 
1992 			switch (pass->blendSource) {
1993 			case GL_ONE:
1994 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_ZERO);
1995 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
1996 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_ZERO);
1997 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
1998 				break;
1999 			case GL_ZERO:
2000 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_ZERO);
2001 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
2002 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_ZERO);
2003 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
2004 				break;
2005 			case GL_DST_COLOR:
2006 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
2007 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
2008 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
2009 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
2010 				break;
2011 			case GL_ONE_MINUS_DST_COLOR:
2012 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
2013 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
2014 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
2015 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
2016 				break;
2017 			case GL_SRC_ALPHA:
2018 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
2019 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
2020 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
2021 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
2022 				break;
2023 			case GL_ONE_MINUS_SRC_ALPHA:
2024 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
2025 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
2026 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
2027 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
2028 				break;
2029 			case GL_DST_ALPHA:
2030 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
2031 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
2032 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
2033 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
2034 				break;
2035 			case GL_ONE_MINUS_DST_ALPHA:
2036 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
2037 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
2038 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
2039 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
2040 				break;
2041 			default:
2042 				assert (0);
2043 				break;
2044 			}
2045 
2046 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB);
2047 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
2048 			qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_PREVIOUS_ARB);
2049 			qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
2050 
2051 			switch (pass->blendDest) {
2052 			case GL_ONE:
2053 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
2054 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
2055 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
2056 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
2057 				break;
2058 			case GL_ZERO:
2059 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO);
2060 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
2061 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
2062 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
2063 				break;
2064 			case GL_SRC_COLOR:
2065 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_TEXTURE);
2066 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
2067 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_TEXTURE);
2068 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
2069 				break;
2070 			case GL_ONE_MINUS_SRC_COLOR:
2071 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_TEXTURE);
2072 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR);
2073 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_TEXTURE);
2074 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
2075 				break;
2076 			case GL_SRC_ALPHA:
2077 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_TEXTURE);
2078 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_ALPHA);
2079 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_TEXTURE);
2080 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
2081 				break;
2082 			case GL_ONE_MINUS_SRC_ALPHA:
2083 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_TEXTURE);
2084 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_ALPHA);
2085 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_TEXTURE);
2086 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
2087 				break;
2088 			case GL_DST_ALPHA:
2089 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_ARB);
2090 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_ALPHA);
2091 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_PREVIOUS_ARB);
2092 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA);
2093 				break;
2094 			case GL_ONE_MINUS_DST_ALPHA:
2095 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_ARB);
2096 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_ALPHA);
2097 				qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_PREVIOUS_ARB);
2098 				qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
2099 				break;
2100 			default:
2101 				assert (0);
2102 				break;
2103 			}
2104 		}
2105 	}
2106 
2107 	RB_DrawElements ();
2108 }
2109 
2110 
2111 /*
2112 =============
2113 RB_RenderMTex
2114 =============
2115 */
RB_RenderMTex(void)2116 static void RB_RenderMTex (void)
2117 {
2118 	shaderPass_t	*pass;
2119 	int				i;
2120 
2121 	pass = rb_accumPasses[0];
2122 
2123 	RB_BindShaderPass (pass, NULL, 0);
2124 	RB_SetupColor (pass);
2125 	RB_SetupPassState (pass, qTrue);
2126 	RB_TextureEnv (GL_MODULATE);
2127 
2128 	for (i=1 ; i<rb_numPasses ; i++) {
2129 		pass = rb_accumPasses[i];
2130 		RB_BindShaderPass (pass, NULL, i);
2131 		RB_TextureEnv (pass->blendMode);
2132 	}
2133 
2134 	RB_DrawElements ();
2135 }
2136 
2137 /*
2138 ===============================================================================
2139 
2140 	PASS ACCUMULATION
2141 
2142 ===============================================================================
2143 */
2144 
2145 /*
2146 =============
2147 RB_RenderAccumulatedPasses
2148 =============
2149 */
RB_RenderAccumulatedPasses(void)2150 static void RB_RenderAccumulatedPasses (void)
2151 {
2152 	// Clean up texture units not used in this flush
2153 	RB_CleanUpTextureUnits ();
2154 
2155 	// Flush
2156 	if (rb_numPasses == 1)
2157 		RB_RenderGeneric ();
2158 	else if (ri.config.extTexEnvCombine)
2159 		RB_RenderCombine ();
2160 	else
2161 		RB_RenderMTex ();
2162 	rb_numPasses = 0;
2163 }
2164 
2165 
2166 /*
2167 =============
2168 RB_AccumulatePass
2169 =============
2170 */
RB_AccumulatePass(shaderPass_t * pass)2171 static void RB_AccumulatePass (shaderPass_t *pass)
2172 {
2173 	shaderPass_t	*prevPass;
2174 	qBool			accum;
2175 
2176 	ri.pc.meshPasses++;
2177 
2178 	// First pass always accumulates
2179 	if (!rb_numPasses) {
2180 		rb_accumPasses[rb_numPasses++] = pass;
2181 		return;
2182 	}
2183 
2184 	// Dynamic lights never accumulate
2185 	if (pass->flags & SHADER_PASS_DLIGHT) {
2186 		if (rb.curDLightBits && ri.scn.numDLights) {
2187 			RB_RenderAccumulatedPasses ();
2188 
2189 			// Clean up texture units not used in this flush
2190 			RB_CleanUpTextureUnits ();
2191 
2192 			// Flush
2193 			rb_accumPasses[rb_numPasses++] = pass;
2194 			RB_RenderDLights ();
2195 			rb_numPasses = 0;
2196 		}
2197 		return;
2198 	}
2199 
2200 	// Check bounds
2201 	if (rb_numPasses >= ri.config.maxTexUnits) {
2202 		RB_RenderAccumulatedPasses ();
2203 		rb_accumPasses[rb_numPasses++] = pass;
2204 		return;
2205 	}
2206 
2207 	// Compare against previous pass properties
2208 	prevPass = rb_accumPasses[rb_numPasses-1];
2209 	if (prevPass->depthFunc != pass->depthFunc
2210 	|| prevPass->totalMask != pass->totalMask
2211 	|| !pass->canAccumulate
2212 	|| (prevPass->alphaFunc != ALPHA_FUNC_NONE && pass->depthFunc != GL_EQUAL)) {
2213 		RB_RenderAccumulatedPasses ();
2214 		rb_accumPasses[rb_numPasses++] = pass;
2215 		return;
2216 	}
2217 
2218 	// Check the blend modes
2219 	if (!pass->blendMode) {
2220 		accum = (prevPass->blendMode == GL_REPLACE) && ri.config.extNVTexEnvCombine4;
2221 	}
2222 	else switch (prevPass->blendMode) {
2223 	case GL_REPLACE:
2224 		if (ri.config.extTexEnvCombine)
2225 			accum = (pass->blendMode == GL_ADD) ? ri.config.extTexEnvAdd : qTrue;
2226 		else
2227 			accum = (pass->blendMode == GL_ADD) ? ri.config.extTexEnvAdd : (pass->blendMode != GL_DECAL);
2228 		break;
2229 
2230 	case GL_ADD:
2231 		accum = (pass->blendMode == GL_ADD) && ri.config.extTexEnvAdd;
2232 		break;
2233 
2234 	case GL_MODULATE:
2235 		accum = (pass->blendMode == GL_MODULATE || pass->blendMode == GL_REPLACE);
2236 		break;
2237 
2238 	default:
2239 		accum = qFalse;
2240 		break;
2241 	}
2242 
2243 	if (!accum)
2244 		RB_RenderAccumulatedPasses ();
2245 	rb_accumPasses[rb_numPasses++] = pass;
2246 }
2247 
2248 /*
2249 ===============================================================================
2250 
2251 	MESH RENDERING SUPPORTING FUNCTIONS
2252 
2253 ===============================================================================
2254 */
2255 
2256 /*
2257 =============
2258 RB_SetupShaderState
2259 =============
2260 */
RB_SetupShaderState(shader_t * shader)2261 static void RB_SetupShaderState (shader_t *shader)
2262 {
2263 	rb_stateBits1 = 0;
2264 
2265 	// Culling
2266 	if (gl_cull->intVal && !(rb.curMeshFeatures & MF_NOCULL)) {
2267 		switch (shader->cullType) {
2268 		case SHADER_CULL_FRONT:
2269 			rb_stateBits1 |= SB1_CULL_FRONT;
2270 			break;
2271 		case SHADER_CULL_BACK:
2272 			rb_stateBits1 |= SB1_CULL_BACK;
2273 			break;
2274 		case SHADER_CULL_NONE:
2275 			break;
2276 		default:
2277 			assert (0);
2278 			break;
2279 		}
2280 	}
2281 
2282 	if (rb_triangleOutlines)
2283 		return;
2284 
2285 	// Polygon offset
2286 	if (shader->flags & SHADER_POLYGONOFFSET)
2287 		rb_stateBits1 |= SB1_POLYOFFSET_ON;
2288 
2289 	// Depth range
2290 	if (shader->flags & SHADER_DEPTHRANGE) {
2291 		qglDepthRange (shader->depthNear, shader->depthFar);
2292 	}
2293 	else if (rb.curEntity->flags & RF_DEPTHHACK)
2294 		qglDepthRange (0, 0.3f);
2295 	else
2296 		qglDepthRange (0, 1);
2297 
2298 	// Depth testing
2299 	// FIXME: SHADER_NODEPTH option?
2300 	if (!(shader->flags & SHADER_FLARE) && !rb_glState.in2D)
2301 		rb_stateBits1 |= SB1_DEPTHTEST_ON;
2302 }
2303 
2304 
2305 /*
2306 =============
2307 RB_SetOutlineColor
2308 =============
2309 */
RB_SetOutlineColor(void)2310 static inline void RB_SetOutlineColor (void)
2311 {
2312 	switch (rb.curMeshType) {
2313 	case MBT_2D:
2314 	case MBT_ALIAS:
2315 	case MBT_SP2:
2316 	case MBT_SKY:
2317 		qglColor4fv (Q_colorRed);
2318 		break;
2319 
2320 	case MBT_Q2BSP:
2321 	case MBT_Q3BSP:
2322 	case MBT_Q3BSP_FLARE:
2323 		qglColor4fv (Q_colorWhite);
2324 		break;
2325 
2326 	case MBT_DECAL:
2327 		qglColor4fv (Q_colorYellow);
2328 		break;
2329 
2330 	case MBT_POLY:
2331 		qglColor4fv (Q_colorGreen);
2332 		break;
2333 
2334 	default:
2335 		assert (0);
2336 		break;
2337 	}
2338 }
2339 
2340 
2341 /*
2342 =============
2343 RB_ShowTriangles
2344 =============
2345 */
RB_ShowTriangles(void)2346 static inline void RB_ShowTriangles (void)
2347 {
2348 	int			i;
2349 
2350 	// Set color
2351 	switch (gl_showtris->intVal) {
2352 	case 1:
2353 		qglColor4ub (255, 255, 255, 255);
2354 		break;
2355 
2356 	case 2:
2357 		RB_SetOutlineColor ();
2358 		break;
2359 	}
2360 
2361 	// Draw
2362 	for (i=0 ; i<rb.numIndexes ; i+=3) {
2363 		qglBegin (GL_LINE_STRIP);
2364 		qglArrayElement (rb.inIndices[i]);
2365 		qglArrayElement (rb.inIndices[i+1]);
2366 		qglArrayElement (rb.inIndices[i+2]);
2367 		qglArrayElement (rb.inIndices[i]);
2368 		qglEnd ();
2369 	}
2370 }
2371 
2372 
2373 /*
2374 =============
2375 RB_ShowNormals
2376 =============
2377 */
RB_ShowNormals(void)2378 static inline void RB_ShowNormals (void)
2379 {
2380 	int		i;
2381 
2382 	if (!rb.inNormals)
2383 		return;
2384 
2385 	// Set color
2386 	switch (gl_shownormals->intVal) {
2387 	case 1:
2388 		qglColor4ub (255, 255, 255, 255);
2389 		break;
2390 
2391 	case 2:
2392 		RB_SetOutlineColor ();
2393 		break;
2394 	}
2395 
2396 	// Draw
2397 	qglBegin (GL_LINES);
2398 	for (i=0 ; i<rb.numVerts ; i++) {
2399 		qglVertex3f(rb.inVertices[i][0],
2400 					rb.inVertices[i][1],
2401 					rb.inVertices[i][2]);
2402 		qglVertex3f(rb.inVertices[i][0] + rb.inNormals[i][0]*2,
2403 					rb.inVertices[i][1] + rb.inNormals[i][1]*2,
2404 					rb.inVertices[i][2] + rb.inNormals[i][2]*2);
2405 	}
2406 	qglEnd ();
2407 }
2408 
2409 /*
2410 ===============================================================================
2411 
2412 	MESH BUFFER RENDERING
2413 
2414 ===============================================================================
2415 */
2416 
2417 /*
2418 =============
2419 RB_RenderMeshBuffer
2420 
2421 This is the entry point for rendering just about everything
2422 =============
2423 */
RB_RenderMeshBuffer(meshBuffer_t * mb,qBool shadowPass)2424 void RB_RenderMeshBuffer (meshBuffer_t *mb, qBool shadowPass)
2425 {
2426 	mBspSurface_t	*surf;
2427 	shaderPass_t	*pass;
2428 	qBool			debugLightmap, addDlights;
2429 	int				i;
2430 
2431 	if (r_skipBackend->intVal)
2432 		return;
2433 
2434 	// Collect mesh buffer values
2435 	rb.curMeshType = mb->sortKey & (MBT_MAX-1);
2436 	rb.curShader = mb->shader;
2437 	rb.curEntity = mb->entity;
2438 	rb.curModel = mb->entity->model;
2439 
2440 	switch (rb.curMeshType) {
2441 	case MBT_Q2BSP:
2442 		rb.curLMTexNum = ((mBspSurface_t *)mb->mesh)->q2_lmTexNumActive;
2443 
2444 		surf = (mBspSurface_t *)mb->mesh;
2445 		addDlights = qFalse;
2446 		break;
2447 
2448 	case MBT_Q3BSP:
2449 		rb.curLMTexNum = ((mBspSurface_t *)mb->mesh)->lmTexNum;
2450 		rb.curPatchWidth = ((mBspSurface_t *)mb->mesh)->q3_patchWidth;
2451 		rb.curPatchHeight = ((mBspSurface_t *)mb->mesh)->q3_patchHeight;
2452 
2453 		surf = (mBspSurface_t *)mb->mesh;
2454 		if (!(rb.curShader->flags & SHADER_FLARE) && surf->dLightFrame == ri.frameCount) {
2455 			rb.curDLightBits = surf->dLightBits;
2456 			addDlights = qTrue;
2457 		}
2458 		else {
2459 			addDlights = qFalse;
2460 		}
2461 		break;
2462 
2463 	default:
2464 		addDlights = qFalse;
2465 		break;
2466 	}
2467 
2468 	// Set time
2469 	if (rb_glState.in2D)
2470 		rb_shaderTime = Sys_Milliseconds () * 0.001f;
2471 	else
2472 		rb_shaderTime = ri.def.time;
2473 	rb_shaderTime -= mb->shaderTime;
2474 	if (rb_shaderTime < 0)
2475 		rb_shaderTime = 0;
2476 
2477 	// State
2478 	RB_SetupShaderState (rb.curShader);
2479 
2480 	// Setup vertices
2481 	if (rb.curShader->numDeforms) {
2482 		RB_DeformVertices ();
2483 		qglVertexPointer (3, GL_FLOAT, 0, rb_outVertexArray);
2484 	}
2485 	else {
2486 		qglVertexPointer (3, GL_FLOAT, 0, rb.inVertices);
2487 	}
2488 
2489 	if (!rb.numIndexes || shadowPass)
2490 		return;
2491 
2492 	RB_LockArrays (rb.numVerts);
2493 
2494 	// Render outlines if desired
2495 	if (rb_triangleOutlines) {
2496 		if (gl_showtris->intVal)
2497 			RB_ShowTriangles ();
2498 		if (gl_shownormals->intVal)
2499 			RB_ShowNormals ();
2500 
2501 		RB_UnlockArrays ();
2502 		RB_ResetPointers ();
2503 		return;
2504 	}
2505 
2506 	// Set fog shaders
2507 	if (mb->fog && mb->fog->shader) {
2508 		if ((rb.curShader->sortKey <= SHADER_SORT_PARTICLE+1 && rb.curShader->flags & (SHADER_DEPTHWRITE|SHADER_SKY)) || rb.curShader->fogDist)
2509 			rb.curTexFog = mb->fog;
2510 		else
2511 			rb.curColorFog = mb->fog;
2512 	}
2513 
2514 	// Accumulate passes and render
2515 	debugLightmap = qFalse;
2516 	for (i=0, pass=mb->shader->passes ; i<mb->shader->numPasses ; pass++, i++) {
2517 		if (pass->flags & SHADER_PASS_LIGHTMAP) {
2518 			if (rb.curLMTexNum < 0)
2519 				continue;
2520 			debugLightmap = (gl_lightmap->intVal);
2521 		}
2522 		else if (!pass->animNumImages)
2523 			continue;
2524 		if (r_detailTextures->intVal) {
2525 			if (pass->flags & SHADER_PASS_NOTDETAIL)
2526 				continue;
2527 		}
2528 		else if (pass->flags & SHADER_PASS_DETAIL)
2529 			continue;
2530 
2531 		// Accumulate
2532 		RB_AccumulatePass (pass);
2533 
2534 		if (pass->flags & SHADER_PASS_LIGHTMAP) {
2535 			RB_AccumulatePass (&rb_dLightPass);
2536 			addDlights = qFalse;
2537 		}
2538 	}
2539 
2540 	if (debugLightmap) {
2541 		// Accumulate a lightmap pass for debugging purposes
2542 		RB_AccumulatePass (&rb_lightMapPass);
2543 	}
2544 	else if (rb.curTexFog && rb.curTexFog->shader) {
2545 		// Accumulate fog
2546 		rb_fogPass.animImages[0] = ri.fogTexture;
2547 		if (!mb->shader->numPasses || rb.curShader->fogDist || rb.curShader->flags & SHADER_SKY)
2548 			rb_fogPass.depthFunc = GL_LEQUAL;
2549 		else
2550 			rb_fogPass.depthFunc = GL_EQUAL;
2551 		RB_AccumulatePass (&rb_fogPass);
2552 	}
2553 
2554 	// Render dlights
2555 	if (addDlights || debugLightmap)
2556 		RB_AccumulatePass (&rb_dLightPass);
2557 
2558 	// Make sure we've flushed
2559 	if (rb_numPasses)
2560 		RB_RenderAccumulatedPasses ();
2561 
2562 	// Unlock arrays
2563 	RB_UnlockArrays ();
2564 
2565 	// Reset the texture matrices
2566 	if (rb_matrixCoords)
2567 		qglMatrixMode (GL_MODELVIEW);
2568 
2569 	// Reset backend information
2570 	if (!rb_triangleOutlines)
2571 		RB_ResetPointers ();
2572 
2573 	// Update performance counters
2574 	ri.pc.meshCount++;
2575 }
2576 
2577 
2578 /*
2579 =============
2580 RB_FinishRendering
2581 
2582 This is called after rendering the mesh list and individual items that pass through the
2583 rendering backend. It resets states so that anything rendered through another system
2584 doesn't catch a leaked state.
2585 =============
2586 */
RB_FinishRendering(void)2587 void RB_FinishRendering (void)
2588 {
2589 	texUnit_t		i;
2590 
2591 	if (rb_matrixCoords)
2592 		qglMatrixMode (GL_TEXTURE);
2593 
2594 	for (i=ri.config.maxTexUnits-1 ; i>0 ; i--) {
2595 		RB_SelectTexture (i);
2596 		RB_TextureTarget (0);
2597 		qglDisable (GL_TEXTURE_GEN_S);
2598 		qglDisable (GL_TEXTURE_GEN_T);
2599 		qglDisable (GL_TEXTURE_GEN_R);
2600 		qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
2601 		RB_LoadIdentityTexMatrix ();
2602 	}
2603 
2604 	RB_SelectTexture (0);
2605 	RB_TextureTarget (GL_TEXTURE_2D);
2606 	qglDisable (GL_TEXTURE_GEN_S);
2607 	qglDisable (GL_TEXTURE_GEN_T);
2608 	qglDisable (GL_TEXTURE_GEN_R);
2609 	qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
2610 	RB_LoadIdentityTexMatrix ();
2611 
2612 	if (rb_matrixCoords)
2613 		qglMatrixMode (GL_MODELVIEW);
2614 
2615 	qglDisableClientState (GL_NORMAL_ARRAY);
2616 	qglDisableClientState (GL_COLOR_ARRAY);
2617 
2618 	qglColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2619 
2620 	RB_StateForBits (SB1_DEPTHMASK_ON|SB1_DEFAULT);
2621 
2622 	qglDepthFunc (GL_LEQUAL);
2623 
2624 	rb_numOldPasses = 0;
2625 }
2626 
2627 /*
2628 ===============================================================================
2629 
2630 	FRAME HANDLING
2631 
2632 ===============================================================================
2633 */
2634 
2635 /*
2636 =============
2637 RB_BeginTriangleOutlines
2638 =============
2639 */
RB_BeginTriangleOutlines(void)2640 void RB_BeginTriangleOutlines (void)
2641 {
2642 	rb_triangleOutlines = qTrue;
2643 
2644 	RB_StateForBits (SB1_BLENDSRC_SRC_ALPHA|SB1_BLENDDST_ONE_MINUS_SRC_ALPHA);
2645 	RB_TextureTarget (0);
2646 
2647 	qglColor4ub (255, 255, 255, 255);
2648 }
2649 
2650 
2651 /*
2652 =============
2653 RB_EndTriangleOutlines
2654 =============
2655 */
RB_EndTriangleOutlines(void)2656 void RB_EndTriangleOutlines (void)
2657 {
2658 	rb_triangleOutlines = qFalse;
2659 
2660 	RB_StateForBits (SB1_DEPTHMASK_ON|SB1_DEFAULT);
2661 	RB_TextureTarget (GL_TEXTURE_2D);
2662 }
2663 
2664 
2665 /*
2666 =============
2667 RB_BeginFrame
2668 
2669 Does any pre-frame backend actions
2670 =============
2671 */
RB_BeginFrame(void)2672 void RB_BeginFrame (void)
2673 {
2674 	static uint32	prevUpdate;
2675 	static uint32	interval = 300;
2676 
2677 	rb.numVerts = 0;
2678 	rb.numIndexes = 0;
2679 
2680 	rb_numOldPasses = 0;
2681 
2682 	// Update the noise table
2683 	if (prevUpdate > Sys_UMilliseconds()%interval) {
2684 		int		i, j, k;
2685 		float	t;
2686 
2687 		j = rand()*(FTABLE_SIZE/4);
2688 		k = rand()*(FTABLE_SIZE/2);
2689 
2690 		for (i=0 ; i<FTABLE_SIZE ; i++) {
2691 			if (i >= j && i < j+k) {
2692 				t = (double)((i-j)) / (double)(k);
2693 				rb_noiseTable[i] = RB_FastSin (t + 0.25f);
2694 			}
2695 			else {
2696 				rb_noiseTable[i] = 1;
2697 			}
2698 		}
2699 
2700 		interval = 300 + rand() % 300;
2701 	}
2702 	prevUpdate = Sys_UMilliseconds () % interval;
2703 }
2704 
2705 
2706 /*
2707 =============
2708 RB_EndFrame
2709 =============
2710 */
RB_EndFrame(void)2711 void RB_EndFrame (void)
2712 {
2713 }
2714 
2715 /*
2716 ===============================================================================
2717 
2718 	INIT / SHUTDOWN
2719 
2720 ===============================================================================
2721 */
2722 
2723 /*
2724 =============
2725 RB_Init
2726 =============
2727 */
2728 void R_PassStateBits (shaderPass_t *pass);
RB_Init(void)2729 void RB_Init (void)
2730 {
2731 	int		i;
2732 	double	t;
2733 
2734 	// Set defaults
2735 	rb_triangleOutlines = qFalse;
2736 	RB_ResetPointers ();
2737 
2738 	qglEnableClientState (GL_VERTEX_ARRAY);
2739 
2740 	// Build lookup tables
2741 	for (i=0 ; i<FTABLE_SIZE ; i++) {
2742 		t = (double)i / (double)FTABLE_SIZE;
2743 
2744 		rb_sinTable[i] = sin (t * (M_PI * 2.0f));
2745 		rb_triangleTable[i] = (t < 0.25) ? t * 4.0f : (t < 0.75) ? 2 - 4.0f * t : (t - 0.75f) * 4.0f - 1.0f;
2746 		rb_squareTable[i] = (t < 0.5) ? 1.0f : -1.0f;
2747 		rb_sawtoothTable[i] = t;
2748 		rb_inverseSawtoothTable[i] = 1.0 - t;
2749 	}
2750 
2751 	// Identity lighting
2752 	rb_identityLighting = ri.inverseIntensity * 255;
2753 	if (rb_identityLighting > 255)
2754 		rb_identityLighting = 255;
2755 
2756 	// Quake3 BSP specific dynamic light pass
2757 	memset (&rb_dLightPass, 0, sizeof (shaderPass_t));
2758 	rb_dLightPass.flags = SHADER_PASS_DLIGHT|SHADER_PASS_BLEND;
2759 	rb_dLightPass.tcGen = TC_GEN_DLIGHT,
2760 	rb_dLightPass.depthFunc = GL_EQUAL;
2761 	rb_dLightPass.blendSource = GL_DST_COLOR;
2762 	rb_dLightPass.blendDest = GL_ONE;
2763 	rb_dLightPass.canAccumulate = qFalse;
2764 	R_PassStateBits (&rb_dLightPass);
2765 
2766 	// Create the fog pass
2767 	memset (&rb_fogPass, 0, sizeof (shaderPass_t));
2768 	rb_fogPass.flags = SHADER_PASS_BLEND|SHADER_PASS_NOCOLORARRAY;
2769 	rb_fogPass.tcGen = TC_GEN_FOG;
2770 	rb_fogPass.blendMode = GL_DECAL;
2771 	rb_fogPass.blendSource = GL_SRC_ALPHA;
2772 	rb_fogPass.blendDest = GL_ONE_MINUS_SRC_ALPHA;
2773 	rb_fogPass.rgbGen.type = RGB_GEN_FOG;
2774 	rb_fogPass.alphaGen.type = ALPHA_GEN_FOG;
2775 	rb_fogPass.canAccumulate = qFalse;
2776 	R_PassStateBits (&rb_fogPass);
2777 
2778 	// Togglable solid lightmap overlay
2779 	memset (&rb_lightMapPass, 0, sizeof (shaderPass_t));
2780 	rb_lightMapPass.flags = SHADER_PASS_LIGHTMAP|SHADER_PASS_NOCOLORARRAY;
2781 	rb_lightMapPass.tcGen = TC_GEN_LIGHTMAP;
2782 	rb_lightMapPass.depthFunc = GL_EQUAL;
2783 	rb_lightMapPass.blendMode = GL_REPLACE;
2784 	rb_lightMapPass.rgbGen.type = RGB_GEN_IDENTITY;
2785 	rb_lightMapPass.alphaGen.type = ALPHA_GEN_IDENTITY;
2786 	rb_lightMapPass.canAccumulate = qTrue;
2787 	R_PassStateBits (&rb_lightMapPass);
2788 
2789 	// Find rendering paths
2790 	switch (ri.renderClass) {
2791 	case REND_CLASS_INTEL:
2792 	case REND_CLASS_S3:
2793 	case REND_CLASS_SIS:
2794 		// These models are known for not supporting texture matrices properly/at all
2795 		RB_ModifyTextureCoords = RB_ModifyTextureCoordsGeneric;
2796 		rb_matrixCoords = qFalse;
2797 		break;
2798 
2799 	default:
2800 		RB_ModifyTextureCoords = RB_ModifyTextureCoordsMatrix;
2801 		rb_matrixCoords = qTrue;
2802 		break;
2803 	}
2804 }
2805 
2806 
2807 /*
2808 =============
2809 RB_Shutdown
2810 =============
2811 */
RB_Shutdown(void)2812 void RB_Shutdown (void)
2813 {
2814 }
2815