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