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