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