]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/renderer/tr_rendertools.cpp
hello world
[icculus/iodoom3.git] / neo / renderer / tr_rendertools.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 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 Doom 3 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 Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 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 Doom 3 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 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "tr_local.h"
33 #include "simplex.h"    // line font definition
34
35 #define MAX_DEBUG_LINES                 16384
36
37 typedef struct debugLine_s {
38         idVec4          rgb;
39         idVec3          start;
40         idVec3          end;
41         bool            depthTest;
42         int                     lifeTime;
43 } debugLine_t;
44
45 debugLine_t             rb_debugLines[ MAX_DEBUG_LINES ];
46 int                             rb_numDebugLines = 0;
47 int                             rb_debugLineTime = 0;
48
49 #define MAX_DEBUG_TEXT                  512
50
51 typedef struct debugText_s {
52         idStr           text;
53         idVec3          origin;
54         float           scale;
55         idVec4          color;
56         idMat3          viewAxis;
57         int                     align;
58         int                     lifeTime;
59         bool            depthTest;
60 } debugText_t;
61
62 debugText_t             rb_debugText[ MAX_DEBUG_TEXT ];
63 int                             rb_numDebugText = 0;
64 int                             rb_debugTextTime = 0;
65
66 #define MAX_DEBUG_POLYGONS              8192
67
68 typedef struct debugPolygon_s {
69         idVec4          rgb;
70         idWinding       winding;
71         bool            depthTest;
72         int                     lifeTime;
73 } debugPolygon_t;
74
75 debugPolygon_t  rb_debugPolygons[ MAX_DEBUG_POLYGONS ];
76 int                             rb_numDebugPolygons = 0;
77 int                             rb_debugPolygonTime = 0;
78
79 static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align );
80
81 /*
82 ================
83 RB_DrawBounds
84 ================
85 */
86 void RB_DrawBounds( const idBounds &bounds ) {
87         if ( bounds.IsCleared() ) {
88                 return;
89         }
90
91         qglBegin( GL_LINE_LOOP );
92         qglVertex3f( bounds[0][0], bounds[0][1], bounds[0][2] );
93         qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
94         qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
95         qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
96         qglEnd();
97         qglBegin( GL_LINE_LOOP );
98         qglVertex3f( bounds[0][0], bounds[0][1], bounds[1][2] );
99         qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
100         qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
101         qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
102         qglEnd();
103
104         qglBegin( GL_LINES );
105         qglVertex3f( bounds[0][0], bounds[0][1], bounds[0][2] );
106         qglVertex3f( bounds[0][0], bounds[0][1], bounds[1][2] );
107
108         qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
109         qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
110
111         qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
112         qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
113
114         qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
115         qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
116         qglEnd();
117 }
118
119
120 /*
121 ================
122 RB_SimpleSurfaceSetup
123 ================
124 */
125 void RB_SimpleSurfaceSetup( const drawSurf_t *drawSurf ) {
126         // change the matrix if needed
127         if ( drawSurf->space != backEnd.currentSpace ) {
128                 qglLoadMatrixf( drawSurf->space->modelViewMatrix );
129                 backEnd.currentSpace = drawSurf->space;
130         }
131
132         // change the scissor if needed
133         if ( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( drawSurf->scissorRect ) ) {
134                 backEnd.currentScissor = drawSurf->scissorRect;
135                 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1, 
136                         backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
137                         backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
138                         backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
139         }
140 }
141
142 /*
143 ================
144 RB_SimpleWorldSetup
145 ================
146 */
147 void RB_SimpleWorldSetup( void ) {
148         backEnd.currentSpace = &backEnd.viewDef->worldSpace;
149         qglLoadMatrixf( backEnd.viewDef->worldSpace.modelViewMatrix );
150
151         backEnd.currentScissor = backEnd.viewDef->scissor;
152         qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1, 
153                 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
154                 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
155                 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
156 }
157
158 /*
159 =================
160 RB_PolygonClear
161
162 This will cover the entire screen with normal rasterization.
163 Texturing is disabled, but the existing glColor, glDepthMask,
164 glColorMask, and the enabled state of depth buffering and
165 stenciling will matter.
166 =================
167 */
168 void RB_PolygonClear( void ) {
169         qglPushMatrix();
170         qglPushAttrib( GL_ALL_ATTRIB_BITS  );
171         qglLoadIdentity();
172         qglDisable( GL_TEXTURE_2D );
173         qglDisable( GL_DEPTH_TEST );
174         qglDisable( GL_CULL_FACE );
175         qglDisable( GL_SCISSOR_TEST );
176         qglBegin( GL_POLYGON );
177         qglVertex3f( -20, -20, -10 );
178         qglVertex3f( 20, -20, -10 );
179         qglVertex3f( 20, 20, -10 );
180         qglVertex3f( -20, 20, -10 );
181         qglEnd();
182         qglPopAttrib();
183         qglPopMatrix();
184 }
185
186 /*
187 ====================
188 RB_ShowDestinationAlpha
189 ====================
190 */
191 void RB_ShowDestinationAlpha( void ) {
192         GL_State( GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
193         qglColor3f( 1, 1, 1 );
194         RB_PolygonClear();
195 }
196
197 /*
198 ===================
199 RB_ScanStencilBuffer
200
201 Debugging tool to see what values are in the stencil buffer
202 ===================
203 */
204 void RB_ScanStencilBuffer( void ) {
205         int             counts[256];
206         int             i;
207         byte    *stencilReadback;
208
209         memset( counts, 0, sizeof( counts ) );
210
211         stencilReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight );
212         qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
213
214         for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
215                 counts[ stencilReadback[i] ]++;
216         }
217
218         R_StaticFree( stencilReadback );
219
220         // print some stats (not supposed to do from back end in SMP...)
221         common->Printf( "stencil values:\n" );
222         for ( i = 0 ; i < 255 ; i++ ) {
223                 if ( counts[i] ) {
224                         common->Printf( "%i: %i\n", i, counts[i] );
225                 }
226         }
227 }
228
229
230 /*
231 ===================
232 RB_CountStencilBuffer
233
234 Print an overdraw count based on stencil index values
235 ===================
236 */
237 void RB_CountStencilBuffer( void ) {
238         int             count;
239         int             i;
240         byte    *stencilReadback;
241
242
243         stencilReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight );
244         qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
245
246         count = 0;
247         for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
248                 count += stencilReadback[i];
249         }
250
251         R_StaticFree( stencilReadback );
252
253         // print some stats (not supposed to do from back end in SMP...)
254         common->Printf( "overdraw: %5.1f\n", (float)count/(glConfig.vidWidth * glConfig.vidHeight)  );
255 }
256
257 /*
258 ===================
259 R_ColorByStencilBuffer
260
261 Sets the screen colors based on the contents of the
262 stencil buffer.  Stencil of 0 = black, 1 = red, 2 = green,
263 3 = blue, ..., 7+ = white
264 ===================
265 */
266 static void R_ColorByStencilBuffer( void ) {
267         int             i;
268         static float    colors[8][3] = {
269                 {0,0,0},
270                 {1,0,0},
271                 {0,1,0},
272                 {0,0,1},
273                 {0,1,1},
274                 {1,0,1},
275                 {1,1,0},
276                 {1,1,1},
277         };
278
279         // clear color buffer to white (>6 passes)
280         qglClearColor( 1, 1, 1, 1 );
281         qglDisable( GL_SCISSOR_TEST );
282         qglClear( GL_COLOR_BUFFER_BIT );
283
284         // now draw color for each stencil value
285         qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
286         for ( i = 0 ; i < 6 ; i++ ) {
287                 qglColor3fv( colors[i] );
288                 qglStencilFunc( GL_EQUAL, i, 255 );
289                 RB_PolygonClear();
290         }
291
292         qglStencilFunc( GL_ALWAYS, 0, 255 );
293 }
294
295 //======================================================================
296
297 /*
298 ==================
299 RB_ShowOverdraw
300 ==================
301 */
302 void RB_ShowOverdraw( void ) {
303         const idMaterial *      material;
304         int                                     i;
305         drawSurf_t * *          drawSurfs;
306         const drawSurf_t *      surf;
307         int                                     numDrawSurfs;
308         viewLight_t *           vLight;
309
310         if ( r_showOverDraw.GetInteger() == 0 ) {
311                 return;
312         }
313
314         material = declManager->FindMaterial( "textures/common/overdrawtest", false );
315         if ( material == NULL ) {
316                 return;
317         }
318
319         drawSurfs = backEnd.viewDef->drawSurfs;
320         numDrawSurfs = backEnd.viewDef->numDrawSurfs;
321
322         int interactions = 0;
323         for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
324                 for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
325                         interactions++;
326                 }
327                 for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
328                         interactions++;
329                 }
330         }
331
332         drawSurf_t **newDrawSurfs = (drawSurf_t **)R_FrameAlloc( numDrawSurfs + interactions * sizeof( newDrawSurfs[0] ) );
333
334         for ( i = 0; i < numDrawSurfs; i++ ) {
335                 surf = drawSurfs[i];
336                 if ( surf->material ) {
337                         const_cast<drawSurf_t *>(surf)->material = material;
338                 }
339                 newDrawSurfs[i] = const_cast<drawSurf_t *>(surf);
340         }
341
342         for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
343                 for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
344                         const_cast<drawSurf_t *>(surf)->material = material;
345                         newDrawSurfs[i++] = const_cast<drawSurf_t *>(surf);
346                 }
347                 for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
348                         const_cast<drawSurf_t *>(surf)->material = material;
349                         newDrawSurfs[i++] = const_cast<drawSurf_t *>(surf);
350                 }
351                 vLight->localInteractions = NULL;
352                 vLight->globalInteractions = NULL;
353         }
354
355         switch( r_showOverDraw.GetInteger() ) {
356                 case 1: // geometry overdraw
357                         const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = newDrawSurfs;
358                         const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs = numDrawSurfs;
359                         break;
360                 case 2: // light interaction overdraw
361                         const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = &newDrawSurfs[numDrawSurfs];
362                         const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs = interactions;
363                         break;
364                 case 3: // geometry + light interaction overdraw
365                         const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = newDrawSurfs;
366                         const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs += interactions;
367                         break;
368         }
369 }
370
371 /*
372 ===================
373 RB_ShowIntensity
374
375 Debugging tool to see how much dynamic range a scene is using.
376 The greatest of the rgb values at each pixel will be used, with
377 the resulting color shading from red at 0 to green at 128 to blue at 255
378 ===================
379 */
380 void RB_ShowIntensity( void ) {
381         byte    *colorReadback;
382         int             i, j, c;
383
384         if ( !r_showIntensity.GetBool() ) {
385                 return;
386         }
387
388         colorReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight * 4 );
389         qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorReadback );
390
391         c = glConfig.vidWidth * glConfig.vidHeight * 4;
392         for ( i = 0; i < c ; i+=4 ) {
393                 j = colorReadback[i];
394                 if ( colorReadback[i+1] > j ) {
395                         j = colorReadback[i+1];
396                 }
397                 if ( colorReadback[i+2] > j ) {
398                         j = colorReadback[i+2];
399                 }
400                 if ( j < 128 ) {
401                         colorReadback[i+0] = 2*(128-j);
402                         colorReadback[i+1] = 2*j;
403                         colorReadback[i+2] = 0;
404                 } else {
405                         colorReadback[i+0] = 0;
406                         colorReadback[i+1] = 2*(255-j);
407                         colorReadback[i+2] = 2*(j-128);
408                 }
409         }
410
411         // draw it back to the screen
412         qglLoadIdentity();
413         qglMatrixMode( GL_PROJECTION );
414         GL_State( GLS_DEPTHFUNC_ALWAYS );
415         qglPushMatrix();
416         qglLoadIdentity(); 
417     qglOrtho( 0, 1, 0, 1, -1, 1 );
418         qglRasterPos2f( 0, 0 );
419         qglPopMatrix();
420         qglColor3f( 1, 1, 1 );
421         globalImages->BindNull();
422         qglMatrixMode( GL_MODELVIEW );
423
424         qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA , GL_UNSIGNED_BYTE, colorReadback );
425
426         R_StaticFree( colorReadback );
427 }
428
429
430 /*
431 ===================
432 RB_ShowDepthBuffer
433
434 Draw the depth buffer as colors
435 ===================
436 */
437 void RB_ShowDepthBuffer( void ) {
438         void    *depthReadback;
439
440         if ( !r_showDepth.GetBool() ) {
441                 return;
442         }
443
444         qglPushMatrix();
445         qglLoadIdentity();
446         qglMatrixMode( GL_PROJECTION );
447         qglPushMatrix();
448         qglLoadIdentity(); 
449     qglOrtho( 0, 1, 0, 1, -1, 1 );
450         qglRasterPos2f( 0, 0 );
451         qglPopMatrix();
452         qglMatrixMode( GL_MODELVIEW );
453         qglPopMatrix();
454
455         GL_State( GLS_DEPTHFUNC_ALWAYS );
456         qglColor3f( 1, 1, 1 );
457         globalImages->BindNull();
458
459         depthReadback = R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight*4 );
460         memset( depthReadback, 0, glConfig.vidWidth * glConfig.vidHeight*4 );
461
462         qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_DEPTH_COMPONENT , GL_FLOAT, depthReadback );
463
464 #if 0
465         for ( i = 0 ; i < glConfig.vidWidth * glConfig.vidHeight ; i++ ) {
466                 ((byte *)depthReadback)[i*4] = 
467                 ((byte *)depthReadback)[i*4+1] = 
468                 ((byte *)depthReadback)[i*4+2] = 255 * ((float *)depthReadback)[i];
469                 ((byte *)depthReadback)[i*4+3] = 1;
470         }
471 #endif
472
473         qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA , GL_UNSIGNED_BYTE, depthReadback );
474         R_StaticFree( depthReadback );
475 }
476
477 /*
478 =================
479 RB_ShowLightCount
480
481 This is a debugging tool that will draw each surface with a color
482 based on how many lights are effecting it
483 =================
484 */
485 void RB_ShowLightCount( void ) {
486         int             i;
487         const drawSurf_t        *surf;
488         const viewLight_t       *vLight;
489
490         if ( !r_showLightCount.GetBool() ) {
491                 return;
492         }
493
494         GL_State( GLS_DEPTHFUNC_EQUAL );
495
496         RB_SimpleWorldSetup();
497         qglClearStencil( 0 );
498         qglClear( GL_STENCIL_BUFFER_BIT );
499
500         qglEnable( GL_STENCIL_TEST );
501
502         // optionally count everything through walls
503         if ( r_showLightCount.GetInteger() >= 2 ) {
504                 qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
505         } else {
506                 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
507         }
508
509         qglStencilFunc( GL_ALWAYS, 1, 255 );
510
511         globalImages->defaultImage->Bind();
512
513         for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
514                 for ( i = 0 ; i < 2 ; i++ ) {
515                         for ( surf = i ? vLight->localInteractions: vLight->globalInteractions; surf; surf = (drawSurf_t *)surf->nextOnLight ) {
516                                 RB_SimpleSurfaceSetup( surf );
517                                 if ( !surf->geo->ambientCache ) {
518                                         continue;
519                                 }
520
521                                 const idDrawVert        *ac = (idDrawVert *)vertexCache.Position( surf->geo->ambientCache );
522                                 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), &ac->xyz );
523                                 RB_DrawElementsWithCounters( surf->geo );
524                         }
525                 }
526         }
527
528         // display the results
529         R_ColorByStencilBuffer();
530
531         if ( r_showLightCount.GetInteger() > 2 ) {
532                 RB_CountStencilBuffer();
533         }
534 }
535
536
537 /*
538 =================
539 RB_ShowSilhouette
540
541 Blacks out all edges, then adds color for each edge that a shadow
542 plane extends from, allowing you to see doubled edges
543 =================
544 */
545 void RB_ShowSilhouette( void ) {
546         int             i;
547         const drawSurf_t        *surf;
548         const viewLight_t       *vLight;
549
550         if ( !r_showSilhouette.GetBool() ) {
551                 return;
552         }
553
554         //
555         // clear all triangle edges to black
556         //
557         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
558         globalImages->BindNull();
559         qglDisable( GL_TEXTURE_2D );
560         qglDisable( GL_STENCIL_TEST );
561
562         qglColor3f( 0, 0, 0 );
563
564         GL_State( GLS_POLYMODE_LINE );
565
566         GL_Cull( CT_TWO_SIDED );
567         qglDisable( GL_DEPTH_TEST );
568
569         RB_RenderDrawSurfListWithFunction( backEnd.viewDef->drawSurfs, backEnd.viewDef->numDrawSurfs, 
570                 RB_T_RenderTriangleSurface );
571
572
573         //
574         // now blend in edges that cast silhouettes
575         //
576         RB_SimpleWorldSetup();
577         qglColor3f( 0.5, 0, 0 );
578         GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
579
580         for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
581                 for ( i = 0 ; i < 2 ; i++ ) {
582                         for ( surf = i ? vLight->localShadows : vLight->globalShadows
583                                 ; surf ; surf = (drawSurf_t *)surf->nextOnLight ) {
584                                 RB_SimpleSurfaceSetup( surf );
585
586                                 const srfTriangles_t    *tri = surf->geo;
587
588                                 qglVertexPointer( 3, GL_FLOAT, sizeof( shadowCache_t ), vertexCache.Position( tri->shadowCache ) );
589                                 qglBegin( GL_LINES );
590
591                                 for ( int j = 0 ; j < tri->numIndexes ; j+=3 ) {
592                                         int             i1 = tri->indexes[j+0];
593                                         int             i2 = tri->indexes[j+1];
594                                         int             i3 = tri->indexes[j+2];
595
596                                         if ( (i1 & 1) + (i2 & 1) + (i3 & 1) == 1 ) {
597                                                 if ( (i1 & 1) + (i2 & 1) == 0 ) {
598                                                         qglArrayElement( i1 );
599                                                         qglArrayElement( i2 );
600                                                 } else if ( (i1 & 1 ) + (i3 & 1) == 0 ) {
601                                                         qglArrayElement( i1 );
602                                                         qglArrayElement( i3 );
603                                                 }
604                                         }
605                                 }
606                                 qglEnd();
607
608                         }
609                 }
610         }
611
612         qglEnable( GL_DEPTH_TEST );
613
614         GL_State( GLS_DEFAULT );
615         qglColor3f( 1,1,1 );
616         GL_Cull( CT_FRONT_SIDED );
617 }
618
619
620
621 /*
622 =================
623 RB_ShowShadowCount
624
625 This is a debugging tool that will draw only the shadow volumes
626 and count up the total fill usage
627 =================
628 */
629 static void RB_ShowShadowCount( void ) {
630         int             i;
631         const drawSurf_t        *surf;
632         const viewLight_t       *vLight;
633
634         if ( !r_showShadowCount.GetBool() ) {
635                 return;
636         }
637
638         GL_State( GLS_DEFAULT );
639
640         qglClearStencil( 0 );
641         qglClear( GL_STENCIL_BUFFER_BIT );
642
643         qglEnable( GL_STENCIL_TEST );
644
645         qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
646
647         qglStencilFunc( GL_ALWAYS, 1, 255 );
648
649         globalImages->defaultImage->Bind();
650
651         // draw both sides
652         GL_Cull( CT_TWO_SIDED );
653
654         for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
655                 for ( i = 0 ; i < 2 ; i++ ) {
656                         for ( surf = i ? vLight->localShadows : vLight->globalShadows 
657                                 ; surf ; surf = (drawSurf_t *)surf->nextOnLight ) {
658                                 RB_SimpleSurfaceSetup( surf );
659                                 const srfTriangles_t    *tri = surf->geo;
660                                 if ( !tri->shadowCache ) {
661                                         continue;
662                                 }
663
664                                 if ( r_showShadowCount.GetInteger() == 3 ) {
665                                         // only show turboshadows
666                                         if ( tri->numShadowIndexesNoCaps != tri->numIndexes ) {
667                                                 continue;
668                                         }
669                                 }
670                                 if ( r_showShadowCount.GetInteger() == 4 ) {
671                                         // only show static shadows
672                                         if ( tri->numShadowIndexesNoCaps == tri->numIndexes ) {
673                                                 continue;
674                                         }
675                                 }
676
677                                 shadowCache_t *cache = (shadowCache_t *)vertexCache.Position( tri->shadowCache );
678                                 qglVertexPointer( 4, GL_FLOAT, sizeof( *cache ), &cache->xyz );
679                                 RB_DrawElementsWithCounters( tri );
680                         }
681                 }
682         }
683
684         // display the results
685         R_ColorByStencilBuffer();
686
687         if ( r_showShadowCount.GetInteger() == 2 ) {
688                 common->Printf( "all shadows " );
689         } else if ( r_showShadowCount.GetInteger() == 3 ) {
690                 common->Printf( "turboShadows " );
691         } else if ( r_showShadowCount.GetInteger() == 4 ) {
692                 common->Printf( "static shadows " );
693         }
694
695         if ( r_showShadowCount.GetInteger() >= 2 ) {
696                 RB_CountStencilBuffer();
697         }
698
699         GL_Cull( CT_FRONT_SIDED );
700 }
701
702
703 /*
704 ===============
705 RB_T_RenderTriangleSurfaceAsLines
706
707 ===============
708 */
709 void RB_T_RenderTriangleSurfaceAsLines( const drawSurf_t *surf ) {
710         const srfTriangles_t *tri = surf->geo;
711
712         if ( !tri->verts ) {
713                 return;
714         }
715
716         qglBegin( GL_LINES );
717         for ( int i = 0 ; i < tri->numIndexes ; i+= 3 ) {
718                 for ( int j = 0 ; j < 3 ; j++ ) {
719                         int k = ( j + 1 ) % 3;
720                         qglVertex3fv( tri->verts[ tri->silIndexes[i+j] ].xyz.ToFloatPtr() );
721                         qglVertex3fv( tri->verts[ tri->silIndexes[i+k] ].xyz.ToFloatPtr() );
722                 }
723         }
724         qglEnd();
725 }
726
727
728 /*
729 =====================
730 RB_ShowTris
731
732 Debugging tool
733 =====================
734 */
735 static void RB_ShowTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
736         modelTrace_t mt;
737         idVec3 end;
738
739         if ( !r_showTris.GetInteger() ) {
740                 return;
741         }
742
743         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
744         globalImages->BindNull();
745         qglDisable( GL_TEXTURE_2D );
746         qglDisable( GL_STENCIL_TEST );
747
748         qglColor3f( 1, 1, 1 );
749
750
751         GL_State( GLS_POLYMODE_LINE );
752
753         switch ( r_showTris.GetInteger() ) {
754         case 1: // only draw visible ones
755                 qglPolygonOffset( -1, -2 );
756                 qglEnable( GL_POLYGON_OFFSET_LINE );
757                 break;
758         default:
759         case 2: // draw all front facing
760                 GL_Cull( CT_FRONT_SIDED );
761                 qglDisable( GL_DEPTH_TEST );
762                 break;
763         case 3: // draw all
764                 GL_Cull( CT_TWO_SIDED );
765                 qglDisable( GL_DEPTH_TEST );
766                 break;
767         }
768
769         RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_RenderTriangleSurface );
770
771         qglEnable( GL_DEPTH_TEST );
772         qglDisable( GL_POLYGON_OFFSET_LINE );
773
774         qglDepthRange( 0, 1 );
775         GL_State( GLS_DEFAULT );
776         GL_Cull( CT_FRONT_SIDED );
777 }
778
779
780 /*
781 =====================
782 RB_ShowSurfaceInfo
783
784 Debugging tool
785 =====================
786 */
787 static void RB_ShowSurfaceInfo( drawSurf_t **drawSurfs, int numDrawSurfs ) {
788         modelTrace_t mt;
789         idVec3 start, end;
790         
791         if ( !r_showSurfaceInfo.GetBool() ) {
792                 return;
793         }
794
795         // start far enough away that we don't hit the player model
796         start = tr.primaryView->renderView.vieworg + tr.primaryView->renderView.viewaxis[0] * 16;
797         end = start + tr.primaryView->renderView.viewaxis[0] * 1000.0f;
798         if ( !tr.primaryWorld->Trace( mt, start, end, 0.0f, false ) ) {
799                 return;
800         }
801
802         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
803         globalImages->BindNull();
804         qglDisable( GL_TEXTURE_2D );
805         qglDisable( GL_STENCIL_TEST );
806
807         qglColor3f( 1, 1, 1 );
808
809         GL_State( GLS_POLYMODE_LINE );
810
811         qglPolygonOffset( -1, -2 );
812         qglEnable( GL_POLYGON_OFFSET_LINE );
813
814         idVec3  trans[3];
815         float   matrix[16];
816
817         // transform the object verts into global space
818         R_AxisToModelMatrix( mt.entity->axis, mt.entity->origin, matrix );
819
820         tr.primaryWorld->DrawText( mt.entity->hModel->Name(), mt.point + tr.primaryView->renderView.viewaxis[2] * 12,
821                 0.35f, colorRed, tr.primaryView->renderView.viewaxis );
822         tr.primaryWorld->DrawText( mt.material->GetName(), mt.point, 
823                 0.35f, colorBlue, tr.primaryView->renderView.viewaxis );
824
825         qglEnable( GL_DEPTH_TEST );
826         qglDisable( GL_POLYGON_OFFSET_LINE );
827
828         qglDepthRange( 0, 1 );
829         GL_State( GLS_DEFAULT );
830         GL_Cull( CT_FRONT_SIDED );
831 }
832
833
834 /*
835 =====================
836 RB_ShowViewEntitys
837
838 Debugging tool
839 =====================
840 */
841 static void RB_ShowViewEntitys( viewEntity_t *vModels ) {
842         if ( !r_showViewEntitys.GetBool() ) {
843                 return;
844         }
845         if ( r_showViewEntitys.GetInteger() == 2 ) {
846                 common->Printf( "view entities: " );
847                 for ( ; vModels ; vModels = vModels->next ) {
848                         common->Printf( "%i ", vModels->entityDef->index );
849                 }
850                 common->Printf( "\n" );
851                 return;
852         }
853
854         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
855         globalImages->BindNull();
856         qglDisable( GL_TEXTURE_2D );
857         qglDisable( GL_STENCIL_TEST );
858
859         qglColor3f( 1, 1, 1 );
860
861
862         GL_State( GLS_POLYMODE_LINE );
863
864         GL_Cull( CT_TWO_SIDED );
865         qglDisable( GL_DEPTH_TEST );
866         qglDisable( GL_SCISSOR_TEST );
867
868         for ( ; vModels ; vModels = vModels->next ) {
869                 idBounds        b;
870
871                 qglLoadMatrixf( vModels->modelViewMatrix );
872
873                 if ( !vModels->entityDef ) {
874                         continue;
875                 }
876
877                 // draw the reference bounds in yellow
878                 qglColor3f( 1, 1, 0 );
879                 RB_DrawBounds( vModels->entityDef->referenceBounds );
880
881
882                 // draw the model bounds in white
883                 qglColor3f( 1, 1, 1 );
884
885                 idRenderModel *model = R_EntityDefDynamicModel( vModels->entityDef );
886                 if ( !model ) {
887                         continue;       // particles won't instantiate without a current view
888                 }
889                 b = model->Bounds( &vModels->entityDef->parms );
890                 RB_DrawBounds( b );
891         }
892
893         qglEnable( GL_DEPTH_TEST );
894         qglDisable( GL_POLYGON_OFFSET_LINE );
895
896         qglDepthRange( 0, 1 );
897         GL_State( GLS_DEFAULT );
898         GL_Cull( CT_FRONT_SIDED );
899 }
900
901 /*
902 =====================
903 RB_ShowTexturePolarity
904
905 Shade triangle red if they have a positive texture area
906 green if they have a negative texture area, or blue if degenerate area
907 =====================
908 */
909 static void RB_ShowTexturePolarity( drawSurf_t **drawSurfs, int numDrawSurfs ) {
910         int             i, j;
911         drawSurf_t      *drawSurf;
912         const srfTriangles_t    *tri;
913
914         if ( !r_showTexturePolarity.GetBool() ) {
915                 return;
916         }
917         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
918         globalImages->BindNull();
919         qglDisable( GL_STENCIL_TEST );
920
921         GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
922
923         qglColor3f( 1, 1, 1 );
924
925         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
926                 drawSurf = drawSurfs[i];
927                 tri = drawSurf->geo;
928                 if ( !tri->verts ) {
929                         continue;
930                 }
931
932                 RB_SimpleSurfaceSetup( drawSurf );
933
934                 qglBegin( GL_TRIANGLES );
935                 for ( j = 0 ; j < tri->numIndexes ; j+=3 ) {
936                         idDrawVert      *a, *b, *c;
937                         float           d0[5], d1[5];
938                         float           area;
939
940                         a = tri->verts + tri->indexes[j];
941                         b = tri->verts + tri->indexes[j+1];
942                         c = tri->verts + tri->indexes[j+2];
943
944                         // VectorSubtract( b->xyz, a->xyz, d0 );
945                         d0[3] = b->st[0] - a->st[0];
946                         d0[4] = b->st[1] - a->st[1];
947                         // VectorSubtract( c->xyz, a->xyz, d1 );
948                         d1[3] = c->st[0] - a->st[0];
949                         d1[4] = c->st[1] - a->st[1];
950
951                         area = d0[3] * d1[4] - d0[4] * d1[3];
952
953                         if ( idMath::Fabs( area ) < 0.0001 ) {
954                                 qglColor4f( 0, 0, 1, 0.5 );
955                         } else  if ( area < 0 ) {
956                                 qglColor4f( 1, 0, 0, 0.5 );
957                         } else {
958                                 qglColor4f( 0, 1, 0, 0.5 );
959                         }
960                         qglVertex3fv( a->xyz.ToFloatPtr() );
961                         qglVertex3fv( b->xyz.ToFloatPtr() );
962                         qglVertex3fv( c->xyz.ToFloatPtr() );
963                 }
964                 qglEnd();
965         }
966
967         GL_State( GLS_DEFAULT );
968 }
969
970
971 /*
972 =====================
973 RB_ShowUnsmoothedTangents
974
975 Shade materials that are using unsmoothed tangents
976 =====================
977 */
978 static void RB_ShowUnsmoothedTangents( drawSurf_t **drawSurfs, int numDrawSurfs ) {
979         int             i, j;
980         drawSurf_t      *drawSurf;
981         const srfTriangles_t    *tri;
982
983         if ( !r_showUnsmoothedTangents.GetBool() ) {
984                 return;
985         }
986         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
987         globalImages->BindNull();
988         qglDisable( GL_STENCIL_TEST );
989
990         GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
991
992         qglColor4f( 0, 1, 0, 0.5 );
993
994         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
995                 drawSurf = drawSurfs[i];
996
997                 if ( !drawSurf->material->UseUnsmoothedTangents() ) {
998                         continue;
999                 }
1000
1001                 RB_SimpleSurfaceSetup( drawSurf );
1002
1003                 tri = drawSurf->geo;
1004                 qglBegin( GL_TRIANGLES );
1005                 for ( j = 0 ; j < tri->numIndexes ; j+=3 ) {
1006                         idDrawVert      *a, *b, *c;
1007
1008                         a = tri->verts + tri->indexes[j];
1009                         b = tri->verts + tri->indexes[j+1];
1010                         c = tri->verts + tri->indexes[j+2];
1011
1012                         qglVertex3fv( a->xyz.ToFloatPtr() );
1013                         qglVertex3fv( b->xyz.ToFloatPtr() );
1014                         qglVertex3fv( c->xyz.ToFloatPtr() );
1015                 }
1016                 qglEnd();
1017         }
1018
1019         GL_State( GLS_DEFAULT );
1020 }
1021
1022
1023 /*
1024 =====================
1025 RB_ShowTangentSpace
1026
1027 Shade a triangle by the RGB colors of its tangent space
1028 1 = tangents[0]
1029 2 = tangents[1]
1030 3 = normal
1031 =====================
1032 */
1033 static void RB_ShowTangentSpace( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1034         int             i, j;
1035         drawSurf_t      *drawSurf;
1036         const srfTriangles_t    *tri;
1037
1038         if ( !r_showTangentSpace.GetInteger() ) {
1039                 return;
1040         }
1041         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1042         globalImages->BindNull();
1043         qglDisable( GL_STENCIL_TEST );
1044
1045         GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
1046
1047         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1048                 drawSurf = drawSurfs[i];
1049
1050                 RB_SimpleSurfaceSetup( drawSurf );
1051
1052                 tri = drawSurf->geo;
1053                 if ( !tri->verts ) {
1054                         continue;
1055                 }
1056                 qglBegin( GL_TRIANGLES );
1057                 for ( j = 0 ; j < tri->numIndexes ; j++ ) {
1058                         const idDrawVert *v;
1059
1060                         v = &tri->verts[tri->indexes[j]];
1061
1062                         if ( r_showTangentSpace.GetInteger() == 1 ) {
1063                                 qglColor4f( 0.5 + 0.5 * v->tangents[0][0],  0.5 + 0.5 * v->tangents[0][1],  
1064                                         0.5 + 0.5 * v->tangents[0][2], 0.5 );
1065                         } else if ( r_showTangentSpace.GetInteger() == 2 ) {
1066                                 qglColor4f( 0.5 + 0.5 * v->tangents[1][0],  0.5 + 0.5 * v->tangents[1][1],  
1067                                         0.5 + 0.5 * v->tangents[1][2], 0.5 );
1068                         } else {
1069                                 qglColor4f( 0.5 + 0.5 * v->normal[0],  0.5 + 0.5 * v->normal[1],  
1070                                         0.5 + 0.5 * v->normal[2], 0.5 );
1071                         }
1072                         qglVertex3fv( v->xyz.ToFloatPtr() );
1073                 }
1074                 qglEnd();
1075         }
1076
1077         GL_State( GLS_DEFAULT );
1078 }
1079
1080 /*
1081 =====================
1082 RB_ShowVertexColor
1083
1084 Draw each triangle with the solid vertex colors
1085 =====================
1086 */
1087 static void RB_ShowVertexColor( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1088         int             i, j;
1089         drawSurf_t      *drawSurf;
1090         const srfTriangles_t    *tri;
1091
1092         if ( !r_showVertexColor.GetBool() ) {
1093                 return;
1094         }
1095         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1096         globalImages->BindNull();
1097         qglDisable( GL_STENCIL_TEST );
1098
1099         GL_State( GLS_DEPTHFUNC_LESS );
1100
1101         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1102                 drawSurf = drawSurfs[i];
1103
1104                 RB_SimpleSurfaceSetup( drawSurf );
1105
1106                 tri = drawSurf->geo;
1107                 if ( !tri->verts ) {
1108                         continue;
1109                 }
1110                 qglBegin( GL_TRIANGLES );
1111                 for ( j = 0 ; j < tri->numIndexes ; j++ ) {
1112                         const idDrawVert *v;
1113
1114                         v = &tri->verts[tri->indexes[j]];
1115                         qglColor4ubv( v->color );
1116                         qglVertex3fv( v->xyz.ToFloatPtr() );
1117                 }
1118                 qglEnd();
1119         }
1120
1121         GL_State( GLS_DEFAULT );
1122 }
1123
1124
1125 /*
1126 =====================
1127 RB_ShowNormals
1128
1129 Debugging tool
1130 =====================
1131 */
1132 static void RB_ShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1133         int                     i, j;
1134         drawSurf_t      *drawSurf;
1135         idVec3          end;
1136         const srfTriangles_t    *tri;
1137         float           size;
1138         bool            showNumbers;
1139         idVec3          pos;
1140
1141         if ( r_showNormals.GetFloat() == 0.0f ) {
1142                 return;
1143         }
1144
1145         GL_State( GLS_POLYMODE_LINE );
1146         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1147
1148         globalImages->BindNull();
1149         qglDisable( GL_STENCIL_TEST );
1150         if ( !r_debugLineDepthTest.GetBool() ) {
1151                 qglDisable( GL_DEPTH_TEST );
1152         } else {
1153                 qglEnable( GL_DEPTH_TEST );
1154         }
1155
1156         size = r_showNormals.GetFloat();
1157         if ( size < 0.0f ) {
1158                 size = -size;
1159                 showNumbers = true;
1160         } else {
1161                 showNumbers = false;
1162         }
1163
1164         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1165                 drawSurf = drawSurfs[i];
1166
1167                 RB_SimpleSurfaceSetup( drawSurf );
1168
1169                 tri = drawSurf->geo;
1170                 if ( !tri->verts ) {
1171                         continue;
1172                 }
1173
1174                 qglBegin( GL_LINES );
1175                 for ( j = 0 ; j < tri->numVerts ; j++ ) {
1176                         qglColor3f( 0, 0, 1 );
1177                         qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
1178                         VectorMA( tri->verts[j].xyz, size, tri->verts[j].normal, end );
1179                         qglVertex3fv( end.ToFloatPtr() );
1180
1181                         qglColor3f( 1, 0, 0 );
1182                         qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
1183                         VectorMA( tri->verts[j].xyz, size, tri->verts[j].tangents[0], end );
1184                         qglVertex3fv( end.ToFloatPtr() );
1185
1186                         qglColor3f( 0, 1, 0 );
1187                         qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
1188                         VectorMA( tri->verts[j].xyz, size, tri->verts[j].tangents[1], end );
1189                         qglVertex3fv( end.ToFloatPtr() );
1190                 }
1191                 qglEnd();
1192         }
1193
1194         if ( showNumbers ) {
1195                 RB_SimpleWorldSetup();
1196                 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1197                         drawSurf = drawSurfs[i];
1198                         tri = drawSurf->geo;
1199                         if ( !tri->verts ) {
1200                                 continue;
1201                         }
1202                         
1203                         for ( j = 0 ; j < tri->numVerts ; j++ ) {
1204                                 R_LocalPointToGlobal( drawSurf->space->modelMatrix, tri->verts[j].xyz + tri->verts[j].tangents[0] + tri->verts[j].normal * 0.2f, pos );
1205                                 RB_DrawText( va( "%d", j ), pos, 0.01f, colorWhite, backEnd.viewDef->renderView.viewaxis, 1 );
1206                         }
1207
1208                         for ( j = 0 ; j < tri->numIndexes; j += 3 ) {
1209                                 R_LocalPointToGlobal( drawSurf->space->modelMatrix, ( tri->verts[ tri->indexes[ j + 0 ] ].xyz + tri->verts[ tri->indexes[ j + 1 ] ].xyz + tri->verts[ tri->indexes[ j + 2 ] ].xyz ) * ( 1.0f / 3.0f ) + tri->verts[ tri->indexes[ j + 0 ] ].normal * 0.2f, pos );
1210                                 RB_DrawText( va( "%d", j / 3 ), pos, 0.01f, colorCyan, backEnd.viewDef->renderView.viewaxis, 1 );
1211                         }
1212                 }
1213         }
1214
1215         qglEnable( GL_STENCIL_TEST );
1216 }
1217
1218
1219 /*
1220 =====================
1221 RB_ShowNormals
1222
1223 Debugging tool
1224 =====================
1225 */
1226 static void RB_AltShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1227         int                     i, j, k;
1228         drawSurf_t      *drawSurf;
1229         idVec3          end;
1230         const srfTriangles_t    *tri;
1231
1232         if ( r_showNormals.GetFloat() == 0.0f ) {
1233                 return;
1234         }
1235
1236         GL_State( GLS_DEFAULT );
1237         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1238
1239         globalImages->BindNull();
1240         qglDisable( GL_STENCIL_TEST );
1241         qglDisable( GL_DEPTH_TEST );
1242
1243         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1244                 drawSurf = drawSurfs[i];
1245
1246                 RB_SimpleSurfaceSetup( drawSurf );
1247
1248                 tri = drawSurf->geo;
1249                 qglBegin( GL_LINES );
1250                 for ( j = 0 ; j < tri->numIndexes ; j += 3 ) {
1251                         const idDrawVert *v[3];
1252                         idVec3          mid;
1253
1254                         v[0] = &tri->verts[tri->indexes[j+0]];
1255                         v[1] = &tri->verts[tri->indexes[j+1]];
1256                         v[2] = &tri->verts[tri->indexes[j+2]];
1257
1258                         // make the midpoint slightly above the triangle
1259                         mid = ( v[0]->xyz + v[1]->xyz + v[2]->xyz ) * ( 1.0f / 3.0f );
1260                         mid += 0.1f * tri->facePlanes[ j / 3 ].Normal();
1261
1262                         for ( k = 0 ; k < 3 ; k++ ) {
1263                                 idVec3  pos;
1264
1265                                 pos = ( mid + v[k]->xyz * 3.0f ) * 0.25f;
1266
1267                                 qglColor3f( 0, 0, 1 );
1268                                 qglVertex3fv( pos.ToFloatPtr() );
1269                                 VectorMA( pos, r_showNormals.GetFloat(), v[k]->normal, end );
1270                                 qglVertex3fv( end.ToFloatPtr() );
1271
1272                                 qglColor3f( 1, 0, 0 );
1273                                 qglVertex3fv( pos.ToFloatPtr() );
1274                                 VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[0], end );
1275                                 qglVertex3fv( end.ToFloatPtr() );
1276
1277                                 qglColor3f( 0, 1, 0 );
1278                                 qglVertex3fv( pos.ToFloatPtr() );
1279                                 VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[1], end );
1280                                 qglVertex3fv( end.ToFloatPtr() );
1281
1282                                 qglColor3f( 1, 1, 1 );
1283                                 qglVertex3fv( pos.ToFloatPtr() );
1284                                 qglVertex3fv( v[k]->xyz.ToFloatPtr() );
1285                         }
1286                 }
1287                 qglEnd();
1288         }
1289
1290         qglEnable( GL_DEPTH_TEST );
1291         qglEnable( GL_STENCIL_TEST );
1292 }
1293
1294
1295
1296 /*
1297 =====================
1298 RB_ShowTextureVectors
1299
1300 Draw texture vectors in the center of each triangle
1301 =====================
1302 */
1303 static void RB_ShowTextureVectors( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1304         int                     i, j;
1305         drawSurf_t      *drawSurf;
1306         const srfTriangles_t    *tri;
1307
1308         if ( r_showTextureVectors.GetFloat() == 0.0f ) {
1309                 return;
1310         }
1311
1312         GL_State( GLS_DEPTHFUNC_LESS );
1313         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1314
1315         globalImages->BindNull();
1316
1317         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1318                 drawSurf = drawSurfs[i];
1319
1320                 tri = drawSurf->geo;
1321
1322                 if ( !tri->verts ) {
1323                         continue;
1324                 }
1325                 if ( !tri->facePlanes ) {
1326                         continue;
1327                 }
1328                 RB_SimpleSurfaceSetup( drawSurf );
1329
1330                 // draw non-shared edges in yellow
1331                 qglBegin( GL_LINES );
1332
1333                 for ( j = 0 ; j < tri->numIndexes ; j+= 3 ) {
1334                         const idDrawVert *a, *b, *c;
1335                         float   area, inva;
1336                         idVec3  temp;
1337                         float           d0[5], d1[5];
1338                         idVec3          mid;
1339                         idVec3          tangents[2];
1340
1341                         a = &tri->verts[tri->indexes[j+0]];
1342                         b = &tri->verts[tri->indexes[j+1]];
1343                         c = &tri->verts[tri->indexes[j+2]];
1344
1345                         // make the midpoint slightly above the triangle
1346                         mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f );
1347                         mid += 0.1f * tri->facePlanes[ j / 3 ].Normal();
1348
1349                         // calculate the texture vectors
1350                         VectorSubtract( b->xyz, a->xyz, d0 );
1351                         d0[3] = b->st[0] - a->st[0];
1352                         d0[4] = b->st[1] - a->st[1];
1353                         VectorSubtract( c->xyz, a->xyz, d1 );
1354                         d1[3] = c->st[0] - a->st[0];
1355                         d1[4] = c->st[1] - a->st[1];
1356
1357                         area = d0[3] * d1[4] - d0[4] * d1[3];
1358                         if ( area == 0 ) {
1359                                 continue;
1360                         }
1361                         inva = 1.0 / area;
1362
1363                         temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]) * inva;
1364                         temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]) * inva;
1365                         temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]) * inva;
1366                         temp.Normalize();
1367                         tangents[0] = temp;
1368         
1369                         temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]) * inva;
1370                         temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]) * inva;
1371                         temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]) * inva;
1372                         temp.Normalize();
1373                         tangents[1] = temp;
1374
1375                         // draw the tangents
1376                         tangents[0] = mid + tangents[0] * r_showTextureVectors.GetFloat();
1377                         tangents[1] = mid + tangents[1] * r_showTextureVectors.GetFloat();
1378
1379                         qglColor3f( 1, 0, 0 );
1380                         qglVertex3fv( mid.ToFloatPtr() );
1381                         qglVertex3fv( tangents[0].ToFloatPtr() );
1382
1383                         qglColor3f( 0, 1, 0 );
1384                         qglVertex3fv( mid.ToFloatPtr() );
1385                         qglVertex3fv( tangents[1].ToFloatPtr() );
1386                 }
1387
1388                 qglEnd();
1389         }
1390 }
1391
1392 /*
1393 =====================
1394 RB_ShowDominantTris
1395
1396 Draw lines from each vertex to the dominant triangle center
1397 =====================
1398 */
1399 static void RB_ShowDominantTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1400         int                     i, j;
1401         drawSurf_t      *drawSurf;
1402         const srfTriangles_t    *tri;
1403
1404         if ( !r_showDominantTri.GetBool() ) {
1405                 return;
1406         }
1407
1408         GL_State( GLS_DEPTHFUNC_LESS );
1409         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1410
1411         qglPolygonOffset( -1, -2 );
1412         qglEnable( GL_POLYGON_OFFSET_LINE );
1413
1414         globalImages->BindNull();
1415
1416         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1417                 drawSurf = drawSurfs[i];
1418
1419                 tri = drawSurf->geo;
1420
1421                 if ( !tri->verts ) {
1422                         continue;
1423                 }
1424                 if ( !tri->dominantTris ) {
1425                         continue;
1426                 }
1427                 RB_SimpleSurfaceSetup( drawSurf );
1428
1429                 qglColor3f( 1, 1, 0 );
1430                 qglBegin( GL_LINES );
1431
1432                 for ( j = 0 ; j < tri->numVerts ; j++ ) {
1433                         const idDrawVert *a, *b, *c;
1434                         idVec3          mid;
1435
1436                         // find the midpoint of the dominant tri
1437
1438                         a = &tri->verts[j];
1439                         b = &tri->verts[tri->dominantTris[j].v2];
1440                         c = &tri->verts[tri->dominantTris[j].v3];
1441
1442                         mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f );
1443
1444                         qglVertex3fv( mid.ToFloatPtr() );
1445                         qglVertex3fv( a->xyz.ToFloatPtr() );
1446                 }
1447
1448                 qglEnd();
1449         }
1450         qglDisable( GL_POLYGON_OFFSET_LINE );
1451 }
1452
1453 /*
1454 =====================
1455 RB_ShowEdges
1456
1457 Debugging tool
1458 =====================
1459 */
1460 static void RB_ShowEdges( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1461         int                     i, j, k, m, n, o;
1462         drawSurf_t      *drawSurf;
1463         const srfTriangles_t    *tri;
1464         const silEdge_t                 *edge;
1465         int                     danglePlane;
1466
1467         if ( !r_showEdges.GetBool() ) {
1468                 return;
1469         }
1470
1471         GL_State( GLS_DEFAULT );
1472         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1473
1474         globalImages->BindNull();
1475         qglDisable( GL_DEPTH_TEST );
1476
1477         for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1478                 drawSurf = drawSurfs[i];
1479
1480                 tri = drawSurf->geo;
1481
1482                 idDrawVert *ac = (idDrawVert *)tri->verts;
1483                 if ( !ac ) {
1484                         continue;
1485                 }
1486
1487                 RB_SimpleSurfaceSetup( drawSurf );
1488
1489                 // draw non-shared edges in yellow
1490                 qglColor3f( 1, 1, 0 );
1491                 qglBegin( GL_LINES );
1492
1493                 for ( j = 0 ; j < tri->numIndexes ; j+= 3 ) {
1494                         for ( k = 0 ; k < 3 ; k++ ) {
1495                                 int             l, i1, i2;
1496                                 l = ( k == 2 ) ? 0 : k + 1;
1497                                 i1 = tri->indexes[j+k];
1498                                 i2 = tri->indexes[j+l];
1499
1500                                 // if these are used backwards, the edge is shared
1501                                 for ( m = 0 ; m < tri->numIndexes ; m += 3 ) {
1502                                         for ( n = 0 ; n < 3 ; n++ ) {
1503                                                 o = ( n == 2 ) ? 0 : n + 1;
1504                                                 if ( tri->indexes[m+n] == i2 && tri->indexes[m+o] == i1 ) {
1505                                                         break;
1506                                                 }
1507                                         }
1508                                         if ( n != 3 ) {
1509                                                 break;
1510                                         }
1511                                 }
1512
1513                                 // if we didn't find a backwards listing, draw it in yellow
1514                                 if ( m == tri->numIndexes ) {
1515                                         qglVertex3fv( ac[ i1 ].xyz.ToFloatPtr() );
1516                                         qglVertex3fv( ac[ i2 ].xyz.ToFloatPtr() );
1517                                 }
1518
1519                         }
1520                 }
1521
1522                 qglEnd();
1523
1524                 // draw dangling sil edges in red
1525                 if ( !tri->silEdges ) {
1526                         continue;
1527                 }
1528
1529                 // the plane number after all real planes
1530                 // is the dangling edge
1531                 danglePlane = tri->numIndexes / 3;
1532
1533                 qglColor3f( 1, 0, 0 );
1534
1535                 qglBegin( GL_LINES );
1536                 for ( j = 0 ; j < tri->numSilEdges ; j++ ) {
1537                         edge = tri->silEdges + j;
1538
1539                         if ( edge->p1 != danglePlane && edge->p2 != danglePlane ) {
1540                                 continue;
1541                         }
1542
1543                         qglVertex3fv( ac[ edge->v1 ].xyz.ToFloatPtr() );
1544                         qglVertex3fv( ac[ edge->v2 ].xyz.ToFloatPtr() );
1545                 }
1546                 qglEnd();
1547         }
1548
1549         qglEnable( GL_DEPTH_TEST );
1550 }
1551
1552 /*
1553 ==============
1554 RB_ShowLights
1555
1556 Visualize all light volumes used in the current scene
1557 r_showLights 1  : just print volumes numbers, highlighting ones covering the view
1558 r_showLights 2  : also draw planes of each volume
1559 r_showLights 3  : also draw edges of each volume
1560 ==============
1561 */
1562 void RB_ShowLights( void ) {
1563         const idRenderLightLocal        *light;
1564         int                                     count;
1565         srfTriangles_t          *tri;
1566         viewLight_t                     *vLight;
1567
1568         if ( !r_showLights.GetInteger() ) {
1569                 return;
1570         }
1571
1572         // all volumes are expressed in world coordinates
1573         RB_SimpleWorldSetup();
1574
1575         qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1576         globalImages->BindNull();
1577         qglDisable( GL_STENCIL_TEST );
1578
1579
1580         GL_Cull( CT_TWO_SIDED );
1581         qglDisable( GL_DEPTH_TEST );
1582
1583
1584         common->Printf( "volumes: " );  // FIXME: not in back end!
1585
1586         count = 0;
1587         for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
1588                 light = vLight->lightDef;
1589                 count++;
1590
1591                 tri = light->frustumTris;
1592
1593                 // depth buffered planes
1594                 if ( r_showLights.GetInteger() >= 2 ) {
1595                         GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
1596                         qglColor4f( 0, 0, 1, 0.25 );
1597                         qglEnable( GL_DEPTH_TEST );
1598                         RB_RenderTriangleSurface( tri );
1599                 }
1600
1601                 // non-hidden lines
1602                 if ( r_showLights.GetInteger() >= 3 ) {
1603                         GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK  );
1604                         qglDisable( GL_DEPTH_TEST );
1605                         qglColor3f( 1, 1, 1 );
1606                         RB_RenderTriangleSurface( tri );
1607                 }
1608
1609                 int index;
1610
1611                 index = backEnd.viewDef->renderWorld->lightDefs.FindIndex( vLight->lightDef );
1612                 if ( vLight->viewInsideLight ) {
1613                         // view is in this volume
1614                         common->Printf( "[%i] ", index );
1615                 } else {
1616                         common->Printf( "%i ", index );
1617                 }
1618         }
1619
1620         qglEnable( GL_DEPTH_TEST );
1621         qglDisable( GL_POLYGON_OFFSET_LINE );
1622
1623         qglDepthRange( 0, 1 );
1624         GL_State( GLS_DEFAULT );
1625         GL_Cull( CT_FRONT_SIDED );
1626
1627         common->Printf( " = %i total\n", count );
1628 }
1629
1630 /*
1631 =====================
1632 RB_ShowPortals
1633
1634 Debugging tool, won't work correctly with SMP or when mirrors are present
1635 =====================
1636 */
1637 void RB_ShowPortals( void ) {
1638         if ( !r_showPortals.GetBool() ) {
1639                 return;
1640         }
1641
1642         // all portals are expressed in world coordinates
1643         RB_SimpleWorldSetup();
1644
1645         globalImages->BindNull();
1646         qglDisable( GL_DEPTH_TEST );
1647
1648         GL_State( GLS_DEFAULT );
1649
1650         ((idRenderWorldLocal *)backEnd.viewDef->renderWorld)->ShowPortals();
1651
1652         qglEnable( GL_DEPTH_TEST );
1653 }
1654
1655 /*
1656 ================
1657 RB_ClearDebugText
1658 ================
1659 */
1660 void RB_ClearDebugText( int time ) {
1661         int                     i;
1662         int                     num;
1663         debugText_t     *text;
1664
1665         rb_debugTextTime = time;
1666
1667         if ( !time ) {
1668                 // free up our strings
1669                 text = rb_debugText;
1670                 for ( i = 0 ; i < MAX_DEBUG_TEXT; i++, text++ ) {
1671                         text->text.Clear();
1672                 }
1673                 rb_numDebugText = 0;
1674                 return;
1675         }
1676
1677         // copy any text that still needs to be drawn
1678         num     = 0;
1679         text = rb_debugText;
1680         for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1681                 if ( text->lifeTime > time ) {
1682                         if ( num != i ) {
1683                                 rb_debugText[ num ] = *text;
1684                         }
1685                         num++;
1686                 }
1687         }
1688         rb_numDebugText = num;
1689 }
1690
1691 /*
1692 ================
1693 RB_AddDebugText
1694 ================
1695 */
1696 void RB_AddDebugText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align, const int lifetime, const bool depthTest ) {
1697         debugText_t *debugText;
1698
1699         if ( rb_numDebugText < MAX_DEBUG_TEXT ) {
1700                 debugText = &rb_debugText[ rb_numDebugText++ ];
1701                 debugText->text                 = text;
1702                 debugText->origin               = origin;
1703                 debugText->scale                = scale;
1704                 debugText->color                = color;
1705                 debugText->viewAxis             = viewAxis;
1706                 debugText->align                = align;
1707                 debugText->lifeTime             = rb_debugTextTime + lifetime;
1708                 debugText->depthTest    = depthTest;
1709         }
1710 }
1711
1712 /*
1713 ================
1714 RB_DrawTextLength
1715
1716   returns the length of the given text
1717 ================
1718 */
1719 float RB_DrawTextLength( const char *text, float scale, int len ) {
1720         int i, num, index, charIndex;
1721         float spacing, textLen = 0.0f;
1722
1723         if ( text && *text ) {
1724                 if ( !len ) {
1725                         len = strlen(text);
1726                 }
1727                 for ( i = 0; i < len; i++ ) {
1728                         charIndex = text[i] - 32;
1729                         if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
1730                                 continue;
1731                         }
1732                         num = simplex[charIndex][0] * 2;
1733                         spacing = simplex[charIndex][1];
1734                         index = 2;
1735
1736                         while( index - 2 < num ) {   
1737                                 if ( simplex[charIndex][index] < 0) {  
1738                                         index++;
1739                                         continue; 
1740                                 } 
1741                                 index += 2;
1742                                 if ( simplex[charIndex][index] < 0) {  
1743                                         index++;
1744                                         continue; 
1745                                 } 
1746                         }   
1747                         textLen += spacing * scale;  
1748                 }
1749         }
1750         return textLen;
1751 }
1752
1753 /*
1754 ================
1755 RB_DrawText
1756
1757   oriented on the viewaxis
1758   align can be 0-left, 1-center (default), 2-right
1759 ================
1760 */
1761 static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align ) {
1762         int i, j, len, num, index, charIndex, line;
1763         float textLen, spacing;
1764         idVec3 org, p1, p2;
1765
1766         if ( text && *text ) {
1767                 qglBegin( GL_LINES );
1768                 qglColor3fv( color.ToFloatPtr() );
1769
1770                 if ( text[0] == '\n' ) {
1771                         line = 1;
1772                 } else {
1773                         line = 0;
1774                 }
1775
1776                 len = strlen( text );
1777                 for ( i = 0; i < len; i++ ) {
1778
1779                         if ( i == 0 || text[i] == '\n' ) {
1780                                 org = origin - viewAxis[2] * ( line * 36.0f * scale );
1781                                 if ( align != 0 ) {
1782                                         for ( j = 1; i+j <= len; j++ ) {
1783                                                 if ( i+j == len || text[i+j] == '\n' ) {
1784                                                         textLen = RB_DrawTextLength( text+i, scale, j );
1785                                                         break;
1786                                                 }
1787                                         }
1788                                         if ( align == 2 ) {
1789                                                 // right
1790                                                 org += viewAxis[1] * textLen;
1791                                         } else {
1792                                                 // center
1793                                                 org += viewAxis[1] * ( textLen * 0.5f );
1794                                         }
1795                                 }
1796                                 line++;
1797                         }
1798
1799                         charIndex = text[i] - 32;
1800                         if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
1801                                 continue;
1802                         }
1803                         num = simplex[charIndex][0] * 2;
1804                         spacing = simplex[charIndex][1];
1805                         index = 2;
1806
1807                         while( index - 2 < num ) {
1808                                 if ( simplex[charIndex][index] < 0) {  
1809                                         index++;
1810                                         continue; 
1811                                 }
1812                                 p1 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
1813                                 index += 2;
1814                                 if ( simplex[charIndex][index] < 0) {
1815                                         index++;
1816                                         continue;
1817                                 }
1818                                 p2 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
1819
1820                                 qglVertex3fv( p1.ToFloatPtr() );
1821                                 qglVertex3fv( p2.ToFloatPtr() );
1822                         }
1823                         org -= viewAxis[1] * ( spacing * scale );
1824                 }
1825
1826                 qglEnd();
1827         }
1828 }
1829
1830 /*
1831 ================
1832 RB_ShowDebugText
1833 ================
1834 */
1835 void RB_ShowDebugText( void ) {
1836         int                     i;
1837         int                     width;
1838         debugText_t     *text;
1839
1840         if ( !rb_numDebugText ) {
1841                 return;
1842         }
1843
1844         // all lines are expressed in world coordinates
1845         RB_SimpleWorldSetup();
1846
1847         globalImages->BindNull();
1848
1849         width = r_debugLineWidth.GetInteger();
1850         if ( width < 1 ) {
1851                 width = 1;
1852         } else if ( width > 10 ) {
1853                 width = 10;
1854         }
1855
1856         // draw lines
1857         GL_State( GLS_POLYMODE_LINE );
1858         qglLineWidth( width );
1859
1860         if ( !r_debugLineDepthTest.GetBool() ) {
1861                 qglDisable( GL_DEPTH_TEST );
1862         }
1863
1864         text = rb_debugText;
1865         for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1866                 if ( !text->depthTest ) {
1867                         RB_DrawText( text->text, text->origin, text->scale, text->color, text->viewAxis, text->align );
1868                 }
1869         }
1870
1871         if ( !r_debugLineDepthTest.GetBool() ) {
1872                 qglEnable( GL_DEPTH_TEST );
1873         }
1874
1875         text = rb_debugText;
1876         for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1877                 if ( text->depthTest ) {
1878                         RB_DrawText( text->text, text->origin, text->scale, text->color, text->viewAxis, text->align );
1879                 }
1880         }
1881
1882         qglLineWidth( 1 );
1883         GL_State( GLS_DEFAULT );
1884 }
1885
1886 /*
1887 ================
1888 RB_ClearDebugLines
1889 ================
1890 */
1891 void RB_ClearDebugLines( int time ) {
1892         int                     i;
1893         int                     num;
1894         debugLine_t     *line;
1895
1896         rb_debugLineTime = time;
1897
1898         if ( !time ) {
1899                 rb_numDebugLines = 0;
1900                 return;
1901         }
1902
1903         // copy any lines that still need to be drawn
1904         num     = 0;
1905         line = rb_debugLines;
1906         for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1907                 if ( line->lifeTime > time ) {
1908                         if ( num != i ) {
1909                                 rb_debugLines[ num ] = *line;
1910                         }
1911                         num++;
1912                 }
1913         }
1914         rb_numDebugLines = num;
1915 }
1916
1917 /*
1918 ================
1919 RB_AddDebugLine
1920 ================
1921 */
1922 void RB_AddDebugLine( const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifeTime, const bool depthTest ) {
1923         debugLine_t *line;
1924
1925         if ( rb_numDebugLines < MAX_DEBUG_LINES ) {
1926                 line = &rb_debugLines[ rb_numDebugLines++ ];
1927                 line->rgb               = color;
1928                 line->start             = start;
1929                 line->end               = end;
1930                 line->depthTest = depthTest;
1931                 line->lifeTime  = rb_debugLineTime + lifeTime;
1932         }
1933 }
1934
1935 /*
1936 ================
1937 RB_ShowDebugLines
1938 ================
1939 */
1940 void RB_ShowDebugLines( void ) {
1941         int                     i;
1942         int                     width;
1943         debugLine_t     *line;
1944
1945         if ( !rb_numDebugLines ) {
1946                 return;
1947         }
1948
1949         // all lines are expressed in world coordinates
1950         RB_SimpleWorldSetup();
1951
1952         globalImages->BindNull();
1953
1954         width = r_debugLineWidth.GetInteger();
1955         if ( width < 1 ) {
1956                 width = 1;
1957         } else if ( width > 10 ) {
1958                 width = 10;
1959         }
1960
1961         // draw lines
1962         GL_State( GLS_POLYMODE_LINE );//| GLS_DEPTHMASK ); //| GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
1963         qglLineWidth( width );
1964
1965         if ( !r_debugLineDepthTest.GetBool() ) {
1966                 qglDisable( GL_DEPTH_TEST );
1967         }
1968
1969         qglBegin( GL_LINES );
1970
1971         line = rb_debugLines;
1972         for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1973                 if ( !line->depthTest ) {
1974                         qglColor3fv( line->rgb.ToFloatPtr() );
1975                         qglVertex3fv( line->start.ToFloatPtr() );
1976                         qglVertex3fv( line->end.ToFloatPtr() );
1977                 }
1978         }
1979         qglEnd();
1980
1981         if ( !r_debugLineDepthTest.GetBool() ) {
1982                 qglEnable( GL_DEPTH_TEST );
1983         }
1984
1985         qglBegin( GL_LINES );
1986
1987         line = rb_debugLines;
1988         for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1989                 if ( line->depthTest ) {
1990                         qglColor4fv( line->rgb.ToFloatPtr() );
1991                         qglVertex3fv( line->start.ToFloatPtr() );
1992                         qglVertex3fv( line->end.ToFloatPtr() );
1993                 }
1994         }
1995
1996         qglEnd();
1997
1998         qglLineWidth( 1 );
1999         GL_State( GLS_DEFAULT );
2000 }
2001
2002 /*
2003 ================
2004 RB_ClearDebugPolygons
2005 ================
2006 */
2007 void RB_ClearDebugPolygons( int time ) {
2008         int                             i;
2009         int                             num;
2010         debugPolygon_t  *poly;
2011
2012         rb_debugPolygonTime = time;
2013
2014         if ( !time ) {
2015                 rb_numDebugPolygons = 0;
2016                 return;
2017         }
2018
2019         // copy any polygons that still need to be drawn
2020         num     = 0;
2021
2022         poly = rb_debugPolygons;
2023         for ( i = 0 ; i < rb_numDebugPolygons; i++, poly++ ) {
2024                 if ( poly->lifeTime > time ) {
2025                         if ( num != i ) {
2026                                 rb_debugPolygons[ num ] = *poly;
2027                         }
2028                         num++;
2029                 }
2030         }
2031         rb_numDebugPolygons = num;
2032 }
2033
2034 /*
2035 ================
2036 RB_AddDebugPolygon
2037 ================
2038 */
2039 void RB_AddDebugPolygon( const idVec4 &color, const idWinding &winding, const int lifeTime, const bool depthTest ) {
2040         debugPolygon_t *poly;
2041
2042         if ( rb_numDebugPolygons < MAX_DEBUG_POLYGONS ) {
2043                 poly = &rb_debugPolygons[ rb_numDebugPolygons++ ];
2044                 poly->rgb               = color;
2045                 poly->winding   = winding;
2046                 poly->depthTest = depthTest;
2047                 poly->lifeTime  = rb_debugPolygonTime + lifeTime;
2048         }
2049 }
2050
2051 /*
2052 ================
2053 RB_ShowDebugPolygons
2054 ================
2055 */
2056 void RB_ShowDebugPolygons( void ) {
2057         int                             i, j;
2058         debugPolygon_t  *poly;
2059
2060         if ( !rb_numDebugPolygons ) {
2061                 return;
2062         }
2063
2064         // all lines are expressed in world coordinates
2065         RB_SimpleWorldSetup();
2066
2067         globalImages->BindNull();
2068
2069         qglDisable( GL_TEXTURE_2D );
2070         qglDisable( GL_STENCIL_TEST );
2071
2072         qglEnable( GL_DEPTH_TEST );
2073
2074         if ( r_debugPolygonFilled.GetBool() ) {
2075                 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
2076                 qglPolygonOffset( -1, -2 );
2077                 qglEnable( GL_POLYGON_OFFSET_FILL );
2078         } else {
2079                 GL_State( GLS_POLYMODE_LINE );
2080                 qglPolygonOffset( -1, -2 );
2081                 qglEnable( GL_POLYGON_OFFSET_LINE );
2082         }
2083
2084         poly = rb_debugPolygons;
2085         for ( i = 0 ; i < rb_numDebugPolygons; i++, poly++ ) {
2086 //              if ( !poly->depthTest ) {
2087
2088                         qglColor4fv( poly->rgb.ToFloatPtr() );
2089
2090                         qglBegin( GL_POLYGON );
2091
2092                         for ( j = 0; j < poly->winding.GetNumPoints(); j++) {
2093                                 qglVertex3fv( poly->winding[j].ToFloatPtr() );
2094                         }
2095
2096                         qglEnd();
2097 //              }
2098         }
2099
2100         GL_State( GLS_DEFAULT );
2101
2102         if ( r_debugPolygonFilled.GetBool() ) {
2103                 qglDisable( GL_POLYGON_OFFSET_FILL );
2104         } else {
2105                 qglDisable( GL_POLYGON_OFFSET_LINE );
2106         }
2107
2108         qglDepthRange( 0, 1 );
2109         GL_State( GLS_DEFAULT );
2110 }
2111
2112 /*
2113 ================
2114 RB_TestGamma
2115 ================
2116 */
2117 #define G_WIDTH         512
2118 #define G_HEIGHT        512
2119 #define BAR_HEIGHT      64
2120
2121 void RB_TestGamma( void ) {
2122         byte    image[G_HEIGHT][G_WIDTH][4];
2123         int             i, j;
2124         int             c, comp;
2125         int             v, dither;
2126         int             mask, y;
2127
2128         if ( r_testGamma.GetInteger() <= 0 ) {
2129                 return;
2130         }
2131
2132         v = r_testGamma.GetInteger();
2133         if ( v <= 1 || v >= 196 ) {
2134                 v = 128;
2135         }
2136
2137         memset( image, 0, sizeof( image ) );
2138
2139         for ( mask = 0 ; mask < 8 ; mask++ ) {
2140                 y = mask * BAR_HEIGHT;
2141                 for ( c = 0 ; c < 4 ; c++ ) {
2142                         v = c * 64 + 32;
2143                         // solid color
2144                         for ( i = 0 ; i < BAR_HEIGHT/2 ; i++ ) {
2145                                 for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2146                                         for ( comp = 0 ; comp < 3 ; comp++ ) {
2147                                                 if ( mask & ( 1 << comp ) ) {
2148                                                         image[y+i][c*G_WIDTH/4+j][comp] = v;
2149                                                 }
2150                                         }
2151                                 }
2152                                 // dithered color
2153                                 for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2154                                         if ( ( i ^ j ) & 1 ) {
2155                                                 dither = c * 64;
2156                                         } else {
2157                                                 dither = c * 64 + 63;
2158                                         }
2159                                         for ( comp = 0 ; comp < 3 ; comp++ ) {
2160                                                 if ( mask & ( 1 << comp ) ) {
2161                                                         image[y+BAR_HEIGHT/2+i][c*G_WIDTH/4+j][comp] = dither;
2162                                                 }
2163                                         }
2164                                 }
2165                         }
2166                 }
2167         }
2168
2169         // draw geometrically increasing steps in the bottom row
2170         y = 0 * BAR_HEIGHT;
2171         float   scale = 1;
2172         for ( c = 0 ; c < 4 ; c++ ) {
2173                 v = (int)(64 * scale);
2174                 if ( v < 0 ) {
2175                         v = 0;
2176                 } else if ( v > 255 ) {
2177                         v = 255;
2178                 }
2179                 scale = scale * 1.5;
2180                 for ( i = 0 ; i < BAR_HEIGHT ; i++ ) {
2181                         for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2182                                 image[y+i][c*G_WIDTH/4+j][0] = v;
2183                                 image[y+i][c*G_WIDTH/4+j][1] = v;
2184                                 image[y+i][c*G_WIDTH/4+j][2] = v;
2185                         }
2186                 }
2187         }
2188
2189
2190         qglLoadIdentity();
2191
2192         qglMatrixMode( GL_PROJECTION );
2193         GL_State( GLS_DEPTHFUNC_ALWAYS );
2194         qglColor3f( 1, 1, 1 );
2195         qglPushMatrix();
2196         qglLoadIdentity(); 
2197         qglDisable( GL_TEXTURE_2D );
2198     qglOrtho( 0, 1, 0, 1, -1, 1 );
2199         qglRasterPos2f( 0.01f, 0.01f );
2200         qglDrawPixels( G_WIDTH, G_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, image );
2201         qglPopMatrix();
2202         qglEnable( GL_TEXTURE_2D );
2203         qglMatrixMode( GL_MODELVIEW );
2204 }
2205
2206
2207 /*
2208 ==================
2209 RB_TestGammaBias
2210 ==================
2211 */
2212 static void RB_TestGammaBias( void ) {
2213         byte    image[G_HEIGHT][G_WIDTH][4];
2214
2215         if ( r_testGammaBias.GetInteger() <= 0 ) {
2216                 return;
2217         }
2218
2219         int y = 0;
2220         for ( int bias = -40 ; bias < 40 ; bias+=10, y += BAR_HEIGHT ) {
2221                 float   scale = 1;
2222                 for ( int c = 0 ; c < 4 ; c++ ) {
2223                         int v = (int)(64 * scale + bias);
2224                         scale = scale * 1.5;
2225                         if ( v < 0 ) {
2226                                 v = 0;
2227                         } else if ( v > 255 ) {
2228                                 v = 255;
2229                         }
2230                         for ( int i = 0 ; i < BAR_HEIGHT ; i++ ) {
2231                                 for ( int j = 0 ; j < G_WIDTH/4 ; j++ ) {
2232                                         image[y+i][c*G_WIDTH/4+j][0] = v;
2233                                         image[y+i][c*G_WIDTH/4+j][1] = v;
2234                                         image[y+i][c*G_WIDTH/4+j][2] = v;
2235                                 }
2236                         }
2237                 }
2238         }
2239
2240
2241         qglLoadIdentity();
2242         qglMatrixMode( GL_PROJECTION );
2243         GL_State( GLS_DEPTHFUNC_ALWAYS );
2244         qglColor3f( 1, 1, 1 );
2245         qglPushMatrix();
2246         qglLoadIdentity(); 
2247         qglDisable( GL_TEXTURE_2D );
2248     qglOrtho( 0, 1, 0, 1, -1, 1 );
2249         qglRasterPos2f( 0.01f, 0.01f );
2250         qglDrawPixels( G_WIDTH, G_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, image );
2251         qglPopMatrix();
2252         qglEnable( GL_TEXTURE_2D );
2253         qglMatrixMode( GL_MODELVIEW );
2254 }
2255
2256 /*
2257 ================
2258 RB_TestImage
2259
2260 Display a single image over most of the screen
2261 ================
2262 */
2263 void RB_TestImage( void ) {
2264         idImage *image;
2265         int             max;
2266         float   w, h;
2267
2268         image = tr.testImage;
2269         if ( !image ) {
2270                 return;
2271         }
2272
2273         if ( tr.testVideo ) {
2274                 cinData_t       cin;
2275
2276                 cin = tr.testVideo->ImageForTime( (int)(1000 * ( backEnd.viewDef->floatTime - tr.testVideoStartTime ) ) );
2277                 if ( cin.image ) {
2278                         image->UploadScratch( cin.image, cin.imageWidth, cin.imageHeight );
2279                 } else {
2280                         tr.testImage = NULL;
2281                         return;
2282                 }
2283                 w = 0.25;
2284                 h = 0.25;
2285         } else {
2286                 max = image->uploadWidth > image->uploadHeight ? image->uploadWidth : image->uploadHeight;
2287
2288                 w = 0.25 * image->uploadWidth / max;
2289                 h = 0.25 * image->uploadHeight / max;
2290
2291                 w *= (float)glConfig.vidHeight / glConfig.vidWidth;
2292         }
2293
2294         qglLoadIdentity();
2295
2296         qglMatrixMode( GL_PROJECTION );
2297         GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
2298         qglColor3f( 1, 1, 1 );
2299         qglPushMatrix();
2300         qglLoadIdentity(); 
2301     qglOrtho( 0, 1, 0, 1, -1, 1 );
2302
2303         tr.testImage->Bind();
2304         qglBegin( GL_QUADS );
2305         
2306         qglTexCoord2f( 0, 1 );
2307         qglVertex2f( 0.5 - w, 0 );
2308
2309         qglTexCoord2f( 0, 0 );
2310         qglVertex2f( 0.5 - w, h*2 );
2311
2312         qglTexCoord2f( 1, 0 );
2313         qglVertex2f( 0.5 + w, h*2 );
2314
2315         qglTexCoord2f( 1, 1 );
2316         qglVertex2f( 0.5 + w, 0 );
2317
2318         qglEnd();
2319
2320         qglPopMatrix();
2321         qglMatrixMode( GL_MODELVIEW );
2322 }
2323
2324 /*
2325 =================
2326 RB_RenderDebugTools
2327 =================
2328 */
2329 void RB_RenderDebugTools( drawSurf_t **drawSurfs, int numDrawSurfs ) {
2330         // don't do anything if this was a 2D rendering
2331         if ( !backEnd.viewDef->viewEntitys ) {
2332                 return;
2333         }
2334
2335         RB_LogComment( "---------- RB_RenderDebugTools ----------\n" );
2336
2337         GL_State( GLS_DEFAULT );
2338         backEnd.currentScissor = backEnd.viewDef->scissor;
2339         qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1, 
2340                 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
2341                 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
2342                 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
2343
2344
2345         RB_ShowLightCount();
2346         RB_ShowShadowCount();
2347         RB_ShowTexturePolarity( drawSurfs, numDrawSurfs );
2348         RB_ShowTangentSpace( drawSurfs, numDrawSurfs );
2349         RB_ShowVertexColor( drawSurfs, numDrawSurfs );
2350         RB_ShowTris( drawSurfs, numDrawSurfs );
2351         RB_ShowUnsmoothedTangents( drawSurfs, numDrawSurfs );
2352         RB_ShowSurfaceInfo( drawSurfs, numDrawSurfs );
2353         RB_ShowEdges( drawSurfs, numDrawSurfs );
2354         RB_ShowNormals( drawSurfs, numDrawSurfs );
2355         RB_ShowViewEntitys( backEnd.viewDef->viewEntitys );
2356         RB_ShowLights();
2357         RB_ShowTextureVectors( drawSurfs, numDrawSurfs );
2358         RB_ShowDominantTris( drawSurfs, numDrawSurfs );
2359         if ( r_testGamma.GetInteger() > 0 ) {   // test here so stack check isn't so damn slow on debug builds
2360                 RB_TestGamma();
2361         }
2362         if ( r_testGammaBias.GetInteger() > 0 ) {
2363                 RB_TestGammaBias();
2364         }
2365         RB_TestImage();
2366         RB_ShowPortals();
2367         RB_ShowSilhouette();
2368         RB_ShowDepthBuffer();
2369         RB_ShowIntensity();
2370         RB_ShowDebugLines();
2371         RB_ShowDebugText();
2372         RB_ShowDebugPolygons();
2373         RB_ShowTrace( drawSurfs, numDrawSurfs );
2374 }
2375
2376 /*
2377 =================
2378 RB_ShutdownDebugTools
2379 =================
2380 */
2381 void RB_ShutdownDebugTools( void ) {
2382         for ( int i = 0; i < MAX_DEBUG_POLYGONS; i++ ) {
2383                 rb_debugPolygons[i].winding.Clear();
2384         }
2385 }