2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
33 #include "simplex.h" // line font definition
35 #define MAX_DEBUG_LINES 16384
37 typedef struct debugLine_s {
45 debugLine_t rb_debugLines[ MAX_DEBUG_LINES ];
46 int rb_numDebugLines = 0;
47 int rb_debugLineTime = 0;
49 #define MAX_DEBUG_TEXT 512
51 typedef struct debugText_s {
62 debugText_t rb_debugText[ MAX_DEBUG_TEXT ];
63 int rb_numDebugText = 0;
64 int rb_debugTextTime = 0;
66 #define MAX_DEBUG_POLYGONS 8192
68 typedef struct debugPolygon_s {
75 debugPolygon_t rb_debugPolygons[ MAX_DEBUG_POLYGONS ];
76 int rb_numDebugPolygons = 0;
77 int rb_debugPolygonTime = 0;
79 static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align );
86 void RB_DrawBounds( const idBounds &bounds ) {
87 if ( bounds.IsCleared() ) {
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] );
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] );
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] );
108 qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
109 qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
111 qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
112 qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
114 qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
115 qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
122 RB_SimpleSurfaceSetup
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;
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 );
147 void RB_SimpleWorldSetup( void ) {
148 backEnd.currentSpace = &backEnd.viewDef->worldSpace;
149 qglLoadMatrixf( backEnd.viewDef->worldSpace.modelViewMatrix );
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 );
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.
168 void RB_PolygonClear( void ) {
170 qglPushAttrib( GL_ALL_ATTRIB_BITS );
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 );
188 RB_ShowDestinationAlpha
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 );
201 Debugging tool to see what values are in the stencil buffer
204 void RB_ScanStencilBuffer( void ) {
207 byte *stencilReadback;
209 memset( counts, 0, sizeof( counts ) );
211 stencilReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight );
212 qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
214 for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
215 counts[ stencilReadback[i] ]++;
218 R_StaticFree( stencilReadback );
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++ ) {
224 common->Printf( "%i: %i\n", i, counts[i] );
232 RB_CountStencilBuffer
234 Print an overdraw count based on stencil index values
237 void RB_CountStencilBuffer( void ) {
240 byte *stencilReadback;
243 stencilReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight );
244 qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
247 for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
248 count += stencilReadback[i];
251 R_StaticFree( stencilReadback );
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) );
259 R_ColorByStencilBuffer
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
266 static void R_ColorByStencilBuffer( void ) {
268 static float colors[8][3] = {
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 );
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 );
292 qglStencilFunc( GL_ALWAYS, 0, 255 );
295 //======================================================================
302 void RB_ShowOverdraw( void ) {
303 const idMaterial * material;
305 drawSurf_t * * drawSurfs;
306 const drawSurf_t * surf;
308 viewLight_t * vLight;
310 if ( r_showOverDraw.GetInteger() == 0 ) {
314 material = declManager->FindMaterial( "textures/common/overdrawtest", false );
315 if ( material == NULL ) {
319 drawSurfs = backEnd.viewDef->drawSurfs;
320 numDrawSurfs = backEnd.viewDef->numDrawSurfs;
322 int interactions = 0;
323 for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
324 for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
327 for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
332 drawSurf_t **newDrawSurfs = (drawSurf_t **)R_FrameAlloc( numDrawSurfs + interactions * sizeof( newDrawSurfs[0] ) );
334 for ( i = 0; i < numDrawSurfs; i++ ) {
336 if ( surf->material ) {
337 const_cast<drawSurf_t *>(surf)->material = material;
339 newDrawSurfs[i] = const_cast<drawSurf_t *>(surf);
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);
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);
351 vLight->localInteractions = NULL;
352 vLight->globalInteractions = NULL;
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;
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;
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;
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
380 void RB_ShowIntensity( void ) {
384 if ( !r_showIntensity.GetBool() ) {
388 colorReadback = (byte *)R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight * 4 );
389 qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorReadback );
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];
397 if ( colorReadback[i+2] > j ) {
398 j = colorReadback[i+2];
401 colorReadback[i+0] = 2*(128-j);
402 colorReadback[i+1] = 2*j;
403 colorReadback[i+2] = 0;
405 colorReadback[i+0] = 0;
406 colorReadback[i+1] = 2*(255-j);
407 colorReadback[i+2] = 2*(j-128);
411 // draw it back to the screen
413 qglMatrixMode( GL_PROJECTION );
414 GL_State( GLS_DEPTHFUNC_ALWAYS );
417 qglOrtho( 0, 1, 0, 1, -1, 1 );
418 qglRasterPos2f( 0, 0 );
420 qglColor3f( 1, 1, 1 );
421 globalImages->BindNull();
422 qglMatrixMode( GL_MODELVIEW );
424 qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA , GL_UNSIGNED_BYTE, colorReadback );
426 R_StaticFree( colorReadback );
434 Draw the depth buffer as colors
437 void RB_ShowDepthBuffer( void ) {
440 if ( !r_showDepth.GetBool() ) {
446 qglMatrixMode( GL_PROJECTION );
449 qglOrtho( 0, 1, 0, 1, -1, 1 );
450 qglRasterPos2f( 0, 0 );
452 qglMatrixMode( GL_MODELVIEW );
455 GL_State( GLS_DEPTHFUNC_ALWAYS );
456 qglColor3f( 1, 1, 1 );
457 globalImages->BindNull();
459 depthReadback = R_StaticAlloc( glConfig.vidWidth * glConfig.vidHeight*4 );
460 memset( depthReadback, 0, glConfig.vidWidth * glConfig.vidHeight*4 );
462 qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_DEPTH_COMPONENT , GL_FLOAT, depthReadback );
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;
473 qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA , GL_UNSIGNED_BYTE, depthReadback );
474 R_StaticFree( depthReadback );
481 This is a debugging tool that will draw each surface with a color
482 based on how many lights are effecting it
485 void RB_ShowLightCount( void ) {
487 const drawSurf_t *surf;
488 const viewLight_t *vLight;
490 if ( !r_showLightCount.GetBool() ) {
494 GL_State( GLS_DEPTHFUNC_EQUAL );
496 RB_SimpleWorldSetup();
497 qglClearStencil( 0 );
498 qglClear( GL_STENCIL_BUFFER_BIT );
500 qglEnable( GL_STENCIL_TEST );
502 // optionally count everything through walls
503 if ( r_showLightCount.GetInteger() >= 2 ) {
504 qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
506 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
509 qglStencilFunc( GL_ALWAYS, 1, 255 );
511 globalImages->defaultImage->Bind();
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 ) {
521 const idDrawVert *ac = (idDrawVert *)vertexCache.Position( surf->geo->ambientCache );
522 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), &ac->xyz );
523 RB_DrawElementsWithCounters( surf->geo );
528 // display the results
529 R_ColorByStencilBuffer();
531 if ( r_showLightCount.GetInteger() > 2 ) {
532 RB_CountStencilBuffer();
541 Blacks out all edges, then adds color for each edge that a shadow
542 plane extends from, allowing you to see doubled edges
545 void RB_ShowSilhouette( void ) {
547 const drawSurf_t *surf;
548 const viewLight_t *vLight;
550 if ( !r_showSilhouette.GetBool() ) {
555 // clear all triangle edges to black
557 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
558 globalImages->BindNull();
559 qglDisable( GL_TEXTURE_2D );
560 qglDisable( GL_STENCIL_TEST );
562 qglColor3f( 0, 0, 0 );
564 GL_State( GLS_POLYMODE_LINE );
566 GL_Cull( CT_TWO_SIDED );
567 qglDisable( GL_DEPTH_TEST );
569 RB_RenderDrawSurfListWithFunction( backEnd.viewDef->drawSurfs, backEnd.viewDef->numDrawSurfs,
570 RB_T_RenderTriangleSurface );
574 // now blend in edges that cast silhouettes
576 RB_SimpleWorldSetup();
577 qglColor3f( 0.5, 0, 0 );
578 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
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 );
586 const srfTriangles_t *tri = surf->geo;
588 qglVertexPointer( 3, GL_FLOAT, sizeof( shadowCache_t ), vertexCache.Position( tri->shadowCache ) );
589 qglBegin( GL_LINES );
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];
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 );
612 qglEnable( GL_DEPTH_TEST );
614 GL_State( GLS_DEFAULT );
616 GL_Cull( CT_FRONT_SIDED );
625 This is a debugging tool that will draw only the shadow volumes
626 and count up the total fill usage
629 static void RB_ShowShadowCount( void ) {
631 const drawSurf_t *surf;
632 const viewLight_t *vLight;
634 if ( !r_showShadowCount.GetBool() ) {
638 GL_State( GLS_DEFAULT );
640 qglClearStencil( 0 );
641 qglClear( GL_STENCIL_BUFFER_BIT );
643 qglEnable( GL_STENCIL_TEST );
645 qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
647 qglStencilFunc( GL_ALWAYS, 1, 255 );
649 globalImages->defaultImage->Bind();
652 GL_Cull( CT_TWO_SIDED );
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 ) {
664 if ( r_showShadowCount.GetInteger() == 3 ) {
665 // only show turboshadows
666 if ( tri->numShadowIndexesNoCaps != tri->numIndexes ) {
670 if ( r_showShadowCount.GetInteger() == 4 ) {
671 // only show static shadows
672 if ( tri->numShadowIndexesNoCaps == tri->numIndexes ) {
677 shadowCache_t *cache = (shadowCache_t *)vertexCache.Position( tri->shadowCache );
678 qglVertexPointer( 4, GL_FLOAT, sizeof( *cache ), &cache->xyz );
679 RB_DrawElementsWithCounters( tri );
684 // display the results
685 R_ColorByStencilBuffer();
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 " );
695 if ( r_showShadowCount.GetInteger() >= 2 ) {
696 RB_CountStencilBuffer();
699 GL_Cull( CT_FRONT_SIDED );
705 RB_T_RenderTriangleSurfaceAsLines
709 void RB_T_RenderTriangleSurfaceAsLines( const drawSurf_t *surf ) {
710 const srfTriangles_t *tri = surf->geo;
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() );
729 =====================
733 =====================
735 static void RB_ShowTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
739 if ( !r_showTris.GetInteger() ) {
743 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
744 globalImages->BindNull();
745 qglDisable( GL_TEXTURE_2D );
746 qglDisable( GL_STENCIL_TEST );
748 qglColor3f( 1, 1, 1 );
751 GL_State( GLS_POLYMODE_LINE );
753 switch ( r_showTris.GetInteger() ) {
754 case 1: // only draw visible ones
755 qglPolygonOffset( -1, -2 );
756 qglEnable( GL_POLYGON_OFFSET_LINE );
759 case 2: // draw all front facing
760 GL_Cull( CT_FRONT_SIDED );
761 qglDisable( GL_DEPTH_TEST );
764 GL_Cull( CT_TWO_SIDED );
765 qglDisable( GL_DEPTH_TEST );
769 RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_RenderTriangleSurface );
771 qglEnable( GL_DEPTH_TEST );
772 qglDisable( GL_POLYGON_OFFSET_LINE );
774 qglDepthRange( 0, 1 );
775 GL_State( GLS_DEFAULT );
776 GL_Cull( CT_FRONT_SIDED );
781 =====================
785 =====================
787 static void RB_ShowSurfaceInfo( drawSurf_t **drawSurfs, int numDrawSurfs ) {
791 if ( !r_showSurfaceInfo.GetBool() ) {
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 ) ) {
802 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
803 globalImages->BindNull();
804 qglDisable( GL_TEXTURE_2D );
805 qglDisable( GL_STENCIL_TEST );
807 qglColor3f( 1, 1, 1 );
809 GL_State( GLS_POLYMODE_LINE );
811 qglPolygonOffset( -1, -2 );
812 qglEnable( GL_POLYGON_OFFSET_LINE );
817 // transform the object verts into global space
818 R_AxisToModelMatrix( mt.entity->axis, mt.entity->origin, matrix );
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 );
825 qglEnable( GL_DEPTH_TEST );
826 qglDisable( GL_POLYGON_OFFSET_LINE );
828 qglDepthRange( 0, 1 );
829 GL_State( GLS_DEFAULT );
830 GL_Cull( CT_FRONT_SIDED );
835 =====================
839 =====================
841 static void RB_ShowViewEntitys( viewEntity_t *vModels ) {
842 if ( !r_showViewEntitys.GetBool() ) {
845 if ( r_showViewEntitys.GetInteger() == 2 ) {
846 common->Printf( "view entities: " );
847 for ( ; vModels ; vModels = vModels->next ) {
848 common->Printf( "%i ", vModels->entityDef->index );
850 common->Printf( "\n" );
854 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
855 globalImages->BindNull();
856 qglDisable( GL_TEXTURE_2D );
857 qglDisable( GL_STENCIL_TEST );
859 qglColor3f( 1, 1, 1 );
862 GL_State( GLS_POLYMODE_LINE );
864 GL_Cull( CT_TWO_SIDED );
865 qglDisable( GL_DEPTH_TEST );
866 qglDisable( GL_SCISSOR_TEST );
868 for ( ; vModels ; vModels = vModels->next ) {
871 qglLoadMatrixf( vModels->modelViewMatrix );
873 if ( !vModels->entityDef ) {
877 // draw the reference bounds in yellow
878 qglColor3f( 1, 1, 0 );
879 RB_DrawBounds( vModels->entityDef->referenceBounds );
882 // draw the model bounds in white
883 qglColor3f( 1, 1, 1 );
885 idRenderModel *model = R_EntityDefDynamicModel( vModels->entityDef );
887 continue; // particles won't instantiate without a current view
889 b = model->Bounds( &vModels->entityDef->parms );
893 qglEnable( GL_DEPTH_TEST );
894 qglDisable( GL_POLYGON_OFFSET_LINE );
896 qglDepthRange( 0, 1 );
897 GL_State( GLS_DEFAULT );
898 GL_Cull( CT_FRONT_SIDED );
902 =====================
903 RB_ShowTexturePolarity
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 =====================
909 static void RB_ShowTexturePolarity( drawSurf_t **drawSurfs, int numDrawSurfs ) {
911 drawSurf_t *drawSurf;
912 const srfTriangles_t *tri;
914 if ( !r_showTexturePolarity.GetBool() ) {
917 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
918 globalImages->BindNull();
919 qglDisable( GL_STENCIL_TEST );
921 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
923 qglColor3f( 1, 1, 1 );
925 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
926 drawSurf = drawSurfs[i];
932 RB_SimpleSurfaceSetup( drawSurf );
934 qglBegin( GL_TRIANGLES );
935 for ( j = 0 ; j < tri->numIndexes ; j+=3 ) {
936 idDrawVert *a, *b, *c;
940 a = tri->verts + tri->indexes[j];
941 b = tri->verts + tri->indexes[j+1];
942 c = tri->verts + tri->indexes[j+2];
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];
951 area = d0[3] * d1[4] - d0[4] * d1[3];
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 );
958 qglColor4f( 0, 1, 0, 0.5 );
960 qglVertex3fv( a->xyz.ToFloatPtr() );
961 qglVertex3fv( b->xyz.ToFloatPtr() );
962 qglVertex3fv( c->xyz.ToFloatPtr() );
967 GL_State( GLS_DEFAULT );
972 =====================
973 RB_ShowUnsmoothedTangents
975 Shade materials that are using unsmoothed tangents
976 =====================
978 static void RB_ShowUnsmoothedTangents( drawSurf_t **drawSurfs, int numDrawSurfs ) {
980 drawSurf_t *drawSurf;
981 const srfTriangles_t *tri;
983 if ( !r_showUnsmoothedTangents.GetBool() ) {
986 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
987 globalImages->BindNull();
988 qglDisable( GL_STENCIL_TEST );
990 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
992 qglColor4f( 0, 1, 0, 0.5 );
994 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
995 drawSurf = drawSurfs[i];
997 if ( !drawSurf->material->UseUnsmoothedTangents() ) {
1001 RB_SimpleSurfaceSetup( drawSurf );
1003 tri = drawSurf->geo;
1004 qglBegin( GL_TRIANGLES );
1005 for ( j = 0 ; j < tri->numIndexes ; j+=3 ) {
1006 idDrawVert *a, *b, *c;
1008 a = tri->verts + tri->indexes[j];
1009 b = tri->verts + tri->indexes[j+1];
1010 c = tri->verts + tri->indexes[j+2];
1012 qglVertex3fv( a->xyz.ToFloatPtr() );
1013 qglVertex3fv( b->xyz.ToFloatPtr() );
1014 qglVertex3fv( c->xyz.ToFloatPtr() );
1019 GL_State( GLS_DEFAULT );
1024 =====================
1027 Shade a triangle by the RGB colors of its tangent space
1031 =====================
1033 static void RB_ShowTangentSpace( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1035 drawSurf_t *drawSurf;
1036 const srfTriangles_t *tri;
1038 if ( !r_showTangentSpace.GetInteger() ) {
1041 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1042 globalImages->BindNull();
1043 qglDisable( GL_STENCIL_TEST );
1045 GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
1047 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1048 drawSurf = drawSurfs[i];
1050 RB_SimpleSurfaceSetup( drawSurf );
1052 tri = drawSurf->geo;
1053 if ( !tri->verts ) {
1056 qglBegin( GL_TRIANGLES );
1057 for ( j = 0 ; j < tri->numIndexes ; j++ ) {
1058 const idDrawVert *v;
1060 v = &tri->verts[tri->indexes[j]];
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 );
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 );
1072 qglVertex3fv( v->xyz.ToFloatPtr() );
1077 GL_State( GLS_DEFAULT );
1081 =====================
1084 Draw each triangle with the solid vertex colors
1085 =====================
1087 static void RB_ShowVertexColor( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1089 drawSurf_t *drawSurf;
1090 const srfTriangles_t *tri;
1092 if ( !r_showVertexColor.GetBool() ) {
1095 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1096 globalImages->BindNull();
1097 qglDisable( GL_STENCIL_TEST );
1099 GL_State( GLS_DEPTHFUNC_LESS );
1101 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1102 drawSurf = drawSurfs[i];
1104 RB_SimpleSurfaceSetup( drawSurf );
1106 tri = drawSurf->geo;
1107 if ( !tri->verts ) {
1110 qglBegin( GL_TRIANGLES );
1111 for ( j = 0 ; j < tri->numIndexes ; j++ ) {
1112 const idDrawVert *v;
1114 v = &tri->verts[tri->indexes[j]];
1115 qglColor4ubv( v->color );
1116 qglVertex3fv( v->xyz.ToFloatPtr() );
1121 GL_State( GLS_DEFAULT );
1126 =====================
1130 =====================
1132 static void RB_ShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1134 drawSurf_t *drawSurf;
1136 const srfTriangles_t *tri;
1141 if ( r_showNormals.GetFloat() == 0.0f ) {
1145 GL_State( GLS_POLYMODE_LINE );
1146 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1148 globalImages->BindNull();
1149 qglDisable( GL_STENCIL_TEST );
1150 if ( !r_debugLineDepthTest.GetBool() ) {
1151 qglDisable( GL_DEPTH_TEST );
1153 qglEnable( GL_DEPTH_TEST );
1156 size = r_showNormals.GetFloat();
1157 if ( size < 0.0f ) {
1161 showNumbers = false;
1164 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1165 drawSurf = drawSurfs[i];
1167 RB_SimpleSurfaceSetup( drawSurf );
1169 tri = drawSurf->geo;
1170 if ( !tri->verts ) {
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() );
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() );
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() );
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 ) {
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 );
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 );
1215 qglEnable( GL_STENCIL_TEST );
1220 =====================
1224 =====================
1226 static void RB_AltShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1228 drawSurf_t *drawSurf;
1230 const srfTriangles_t *tri;
1232 if ( r_showNormals.GetFloat() == 0.0f ) {
1236 GL_State( GLS_DEFAULT );
1237 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1239 globalImages->BindNull();
1240 qglDisable( GL_STENCIL_TEST );
1241 qglDisable( GL_DEPTH_TEST );
1243 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1244 drawSurf = drawSurfs[i];
1246 RB_SimpleSurfaceSetup( drawSurf );
1248 tri = drawSurf->geo;
1249 qglBegin( GL_LINES );
1250 for ( j = 0 ; j < tri->numIndexes ; j += 3 ) {
1251 const idDrawVert *v[3];
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]];
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();
1262 for ( k = 0 ; k < 3 ; k++ ) {
1265 pos = ( mid + v[k]->xyz * 3.0f ) * 0.25f;
1267 qglColor3f( 0, 0, 1 );
1268 qglVertex3fv( pos.ToFloatPtr() );
1269 VectorMA( pos, r_showNormals.GetFloat(), v[k]->normal, end );
1270 qglVertex3fv( end.ToFloatPtr() );
1272 qglColor3f( 1, 0, 0 );
1273 qglVertex3fv( pos.ToFloatPtr() );
1274 VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[0], end );
1275 qglVertex3fv( end.ToFloatPtr() );
1277 qglColor3f( 0, 1, 0 );
1278 qglVertex3fv( pos.ToFloatPtr() );
1279 VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[1], end );
1280 qglVertex3fv( end.ToFloatPtr() );
1282 qglColor3f( 1, 1, 1 );
1283 qglVertex3fv( pos.ToFloatPtr() );
1284 qglVertex3fv( v[k]->xyz.ToFloatPtr() );
1290 qglEnable( GL_DEPTH_TEST );
1291 qglEnable( GL_STENCIL_TEST );
1297 =====================
1298 RB_ShowTextureVectors
1300 Draw texture vectors in the center of each triangle
1301 =====================
1303 static void RB_ShowTextureVectors( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1305 drawSurf_t *drawSurf;
1306 const srfTriangles_t *tri;
1308 if ( r_showTextureVectors.GetFloat() == 0.0f ) {
1312 GL_State( GLS_DEPTHFUNC_LESS );
1313 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1315 globalImages->BindNull();
1317 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1318 drawSurf = drawSurfs[i];
1320 tri = drawSurf->geo;
1322 if ( !tri->verts ) {
1325 if ( !tri->facePlanes ) {
1328 RB_SimpleSurfaceSetup( drawSurf );
1330 // draw non-shared edges in yellow
1331 qglBegin( GL_LINES );
1333 for ( j = 0 ; j < tri->numIndexes ; j+= 3 ) {
1334 const idDrawVert *a, *b, *c;
1341 a = &tri->verts[tri->indexes[j+0]];
1342 b = &tri->verts[tri->indexes[j+1]];
1343 c = &tri->verts[tri->indexes[j+2]];
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();
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];
1357 area = d0[3] * d1[4] - d0[4] * d1[3];
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;
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;
1375 // draw the tangents
1376 tangents[0] = mid + tangents[0] * r_showTextureVectors.GetFloat();
1377 tangents[1] = mid + tangents[1] * r_showTextureVectors.GetFloat();
1379 qglColor3f( 1, 0, 0 );
1380 qglVertex3fv( mid.ToFloatPtr() );
1381 qglVertex3fv( tangents[0].ToFloatPtr() );
1383 qglColor3f( 0, 1, 0 );
1384 qglVertex3fv( mid.ToFloatPtr() );
1385 qglVertex3fv( tangents[1].ToFloatPtr() );
1393 =====================
1396 Draw lines from each vertex to the dominant triangle center
1397 =====================
1399 static void RB_ShowDominantTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
1401 drawSurf_t *drawSurf;
1402 const srfTriangles_t *tri;
1404 if ( !r_showDominantTri.GetBool() ) {
1408 GL_State( GLS_DEPTHFUNC_LESS );
1409 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1411 qglPolygonOffset( -1, -2 );
1412 qglEnable( GL_POLYGON_OFFSET_LINE );
1414 globalImages->BindNull();
1416 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1417 drawSurf = drawSurfs[i];
1419 tri = drawSurf->geo;
1421 if ( !tri->verts ) {
1424 if ( !tri->dominantTris ) {
1427 RB_SimpleSurfaceSetup( drawSurf );
1429 qglColor3f( 1, 1, 0 );
1430 qglBegin( GL_LINES );
1432 for ( j = 0 ; j < tri->numVerts ; j++ ) {
1433 const idDrawVert *a, *b, *c;
1436 // find the midpoint of the dominant tri
1439 b = &tri->verts[tri->dominantTris[j].v2];
1440 c = &tri->verts[tri->dominantTris[j].v3];
1442 mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f );
1444 qglVertex3fv( mid.ToFloatPtr() );
1445 qglVertex3fv( a->xyz.ToFloatPtr() );
1450 qglDisable( GL_POLYGON_OFFSET_LINE );
1454 =====================
1458 =====================
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;
1467 if ( !r_showEdges.GetBool() ) {
1471 GL_State( GLS_DEFAULT );
1472 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1474 globalImages->BindNull();
1475 qglDisable( GL_DEPTH_TEST );
1477 for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1478 drawSurf = drawSurfs[i];
1480 tri = drawSurf->geo;
1482 idDrawVert *ac = (idDrawVert *)tri->verts;
1487 RB_SimpleSurfaceSetup( drawSurf );
1489 // draw non-shared edges in yellow
1490 qglColor3f( 1, 1, 0 );
1491 qglBegin( GL_LINES );
1493 for ( j = 0 ; j < tri->numIndexes ; j+= 3 ) {
1494 for ( k = 0 ; k < 3 ; k++ ) {
1496 l = ( k == 2 ) ? 0 : k + 1;
1497 i1 = tri->indexes[j+k];
1498 i2 = tri->indexes[j+l];
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 ) {
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() );
1524 // draw dangling sil edges in red
1525 if ( !tri->silEdges ) {
1529 // the plane number after all real planes
1530 // is the dangling edge
1531 danglePlane = tri->numIndexes / 3;
1533 qglColor3f( 1, 0, 0 );
1535 qglBegin( GL_LINES );
1536 for ( j = 0 ; j < tri->numSilEdges ; j++ ) {
1537 edge = tri->silEdges + j;
1539 if ( edge->p1 != danglePlane && edge->p2 != danglePlane ) {
1543 qglVertex3fv( ac[ edge->v1 ].xyz.ToFloatPtr() );
1544 qglVertex3fv( ac[ edge->v2 ].xyz.ToFloatPtr() );
1549 qglEnable( GL_DEPTH_TEST );
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
1562 void RB_ShowLights( void ) {
1563 const idRenderLightLocal *light;
1565 srfTriangles_t *tri;
1566 viewLight_t *vLight;
1568 if ( !r_showLights.GetInteger() ) {
1572 // all volumes are expressed in world coordinates
1573 RB_SimpleWorldSetup();
1575 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1576 globalImages->BindNull();
1577 qglDisable( GL_STENCIL_TEST );
1580 GL_Cull( CT_TWO_SIDED );
1581 qglDisable( GL_DEPTH_TEST );
1584 common->Printf( "volumes: " ); // FIXME: not in back end!
1587 for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
1588 light = vLight->lightDef;
1591 tri = light->frustumTris;
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 );
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 );
1611 index = backEnd.viewDef->renderWorld->lightDefs.FindIndex( vLight->lightDef );
1612 if ( vLight->viewInsideLight ) {
1613 // view is in this volume
1614 common->Printf( "[%i] ", index );
1616 common->Printf( "%i ", index );
1620 qglEnable( GL_DEPTH_TEST );
1621 qglDisable( GL_POLYGON_OFFSET_LINE );
1623 qglDepthRange( 0, 1 );
1624 GL_State( GLS_DEFAULT );
1625 GL_Cull( CT_FRONT_SIDED );
1627 common->Printf( " = %i total\n", count );
1631 =====================
1634 Debugging tool, won't work correctly with SMP or when mirrors are present
1635 =====================
1637 void RB_ShowPortals( void ) {
1638 if ( !r_showPortals.GetBool() ) {
1642 // all portals are expressed in world coordinates
1643 RB_SimpleWorldSetup();
1645 globalImages->BindNull();
1646 qglDisable( GL_DEPTH_TEST );
1648 GL_State( GLS_DEFAULT );
1650 ((idRenderWorldLocal *)backEnd.viewDef->renderWorld)->ShowPortals();
1652 qglEnable( GL_DEPTH_TEST );
1660 void RB_ClearDebugText( int time ) {
1665 rb_debugTextTime = time;
1668 // free up our strings
1669 text = rb_debugText;
1670 for ( i = 0 ; i < MAX_DEBUG_TEXT; i++, text++ ) {
1673 rb_numDebugText = 0;
1677 // copy any text that still needs to be drawn
1679 text = rb_debugText;
1680 for ( i = 0 ; i < rb_numDebugText; i++, text++ ) {
1681 if ( text->lifeTime > time ) {
1683 rb_debugText[ num ] = *text;
1688 rb_numDebugText = num;
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;
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;
1716 returns the length of the given text
1719 float RB_DrawTextLength( const char *text, float scale, int len ) {
1720 int i, num, index, charIndex;
1721 float spacing, textLen = 0.0f;
1723 if ( text && *text ) {
1727 for ( i = 0; i < len; i++ ) {
1728 charIndex = text[i] - 32;
1729 if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
1732 num = simplex[charIndex][0] * 2;
1733 spacing = simplex[charIndex][1];
1736 while( index - 2 < num ) {
1737 if ( simplex[charIndex][index] < 0) {
1742 if ( simplex[charIndex][index] < 0) {
1747 textLen += spacing * scale;
1757 oriented on the viewaxis
1758 align can be 0-left, 1-center (default), 2-right
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;
1766 if ( text && *text ) {
1767 qglBegin( GL_LINES );
1768 qglColor3fv( color.ToFloatPtr() );
1770 if ( text[0] == '\n' ) {
1776 len = strlen( text );
1777 for ( i = 0; i < len; i++ ) {
1779 if ( i == 0 || text[i] == '\n' ) {
1780 org = origin - viewAxis[2] * ( line * 36.0f * scale );
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 );
1790 org += viewAxis[1] * textLen;
1793 org += viewAxis[1] * ( textLen * 0.5f );
1799 charIndex = text[i] - 32;
1800 if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
1803 num = simplex[charIndex][0] * 2;
1804 spacing = simplex[charIndex][1];
1807 while( index - 2 < num ) {
1808 if ( simplex[charIndex][index] < 0) {
1812 p1 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
1814 if ( simplex[charIndex][index] < 0) {
1818 p2 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
1820 qglVertex3fv( p1.ToFloatPtr() );
1821 qglVertex3fv( p2.ToFloatPtr() );
1823 org -= viewAxis[1] * ( spacing * scale );
1835 void RB_ShowDebugText( void ) {
1840 if ( !rb_numDebugText ) {
1844 // all lines are expressed in world coordinates
1845 RB_SimpleWorldSetup();
1847 globalImages->BindNull();
1849 width = r_debugLineWidth.GetInteger();
1852 } else if ( width > 10 ) {
1857 GL_State( GLS_POLYMODE_LINE );
1858 qglLineWidth( width );
1860 if ( !r_debugLineDepthTest.GetBool() ) {
1861 qglDisable( GL_DEPTH_TEST );
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 );
1871 if ( !r_debugLineDepthTest.GetBool() ) {
1872 qglEnable( GL_DEPTH_TEST );
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 );
1883 GL_State( GLS_DEFAULT );
1891 void RB_ClearDebugLines( int time ) {
1896 rb_debugLineTime = time;
1899 rb_numDebugLines = 0;
1903 // copy any lines that still need to be drawn
1905 line = rb_debugLines;
1906 for ( i = 0 ; i < rb_numDebugLines; i++, line++ ) {
1907 if ( line->lifeTime > time ) {
1909 rb_debugLines[ num ] = *line;
1914 rb_numDebugLines = num;
1922 void RB_AddDebugLine( const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifeTime, const bool depthTest ) {
1925 if ( rb_numDebugLines < MAX_DEBUG_LINES ) {
1926 line = &rb_debugLines[ rb_numDebugLines++ ];
1928 line->start = start;
1930 line->depthTest = depthTest;
1931 line->lifeTime = rb_debugLineTime + lifeTime;
1940 void RB_ShowDebugLines( void ) {
1945 if ( !rb_numDebugLines ) {
1949 // all lines are expressed in world coordinates
1950 RB_SimpleWorldSetup();
1952 globalImages->BindNull();
1954 width = r_debugLineWidth.GetInteger();
1957 } else if ( width > 10 ) {
1962 GL_State( GLS_POLYMODE_LINE );//| GLS_DEPTHMASK ); //| GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
1963 qglLineWidth( width );
1965 if ( !r_debugLineDepthTest.GetBool() ) {
1966 qglDisable( GL_DEPTH_TEST );
1969 qglBegin( GL_LINES );
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() );
1981 if ( !r_debugLineDepthTest.GetBool() ) {
1982 qglEnable( GL_DEPTH_TEST );
1985 qglBegin( GL_LINES );
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() );
1999 GL_State( GLS_DEFAULT );
2004 RB_ClearDebugPolygons
2007 void RB_ClearDebugPolygons( int time ) {
2010 debugPolygon_t *poly;
2012 rb_debugPolygonTime = time;
2015 rb_numDebugPolygons = 0;
2019 // copy any polygons that still need to be drawn
2022 poly = rb_debugPolygons;
2023 for ( i = 0 ; i < rb_numDebugPolygons; i++, poly++ ) {
2024 if ( poly->lifeTime > time ) {
2026 rb_debugPolygons[ num ] = *poly;
2031 rb_numDebugPolygons = num;
2039 void RB_AddDebugPolygon( const idVec4 &color, const idWinding &winding, const int lifeTime, const bool depthTest ) {
2040 debugPolygon_t *poly;
2042 if ( rb_numDebugPolygons < MAX_DEBUG_POLYGONS ) {
2043 poly = &rb_debugPolygons[ rb_numDebugPolygons++ ];
2045 poly->winding = winding;
2046 poly->depthTest = depthTest;
2047 poly->lifeTime = rb_debugPolygonTime + lifeTime;
2053 RB_ShowDebugPolygons
2056 void RB_ShowDebugPolygons( void ) {
2058 debugPolygon_t *poly;
2060 if ( !rb_numDebugPolygons ) {
2064 // all lines are expressed in world coordinates
2065 RB_SimpleWorldSetup();
2067 globalImages->BindNull();
2069 qglDisable( GL_TEXTURE_2D );
2070 qglDisable( GL_STENCIL_TEST );
2072 qglEnable( GL_DEPTH_TEST );
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 );
2079 GL_State( GLS_POLYMODE_LINE );
2080 qglPolygonOffset( -1, -2 );
2081 qglEnable( GL_POLYGON_OFFSET_LINE );
2084 poly = rb_debugPolygons;
2085 for ( i = 0 ; i < rb_numDebugPolygons; i++, poly++ ) {
2086 // if ( !poly->depthTest ) {
2088 qglColor4fv( poly->rgb.ToFloatPtr() );
2090 qglBegin( GL_POLYGON );
2092 for ( j = 0; j < poly->winding.GetNumPoints(); j++) {
2093 qglVertex3fv( poly->winding[j].ToFloatPtr() );
2100 GL_State( GLS_DEFAULT );
2102 if ( r_debugPolygonFilled.GetBool() ) {
2103 qglDisable( GL_POLYGON_OFFSET_FILL );
2105 qglDisable( GL_POLYGON_OFFSET_LINE );
2108 qglDepthRange( 0, 1 );
2109 GL_State( GLS_DEFAULT );
2118 #define G_HEIGHT 512
2119 #define BAR_HEIGHT 64
2121 void RB_TestGamma( void ) {
2122 byte image[G_HEIGHT][G_WIDTH][4];
2128 if ( r_testGamma.GetInteger() <= 0 ) {
2132 v = r_testGamma.GetInteger();
2133 if ( v <= 1 || v >= 196 ) {
2137 memset( image, 0, sizeof( image ) );
2139 for ( mask = 0 ; mask < 8 ; mask++ ) {
2140 y = mask * BAR_HEIGHT;
2141 for ( c = 0 ; c < 4 ; c++ ) {
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;
2153 for ( j = 0 ; j < G_WIDTH/4 ; j++ ) {
2154 if ( ( i ^ j ) & 1 ) {
2157 dither = c * 64 + 63;
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;
2169 // draw geometrically increasing steps in the bottom row
2172 for ( c = 0 ; c < 4 ; c++ ) {
2173 v = (int)(64 * scale);
2176 } else if ( v > 255 ) {
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;
2192 qglMatrixMode( GL_PROJECTION );
2193 GL_State( GLS_DEPTHFUNC_ALWAYS );
2194 qglColor3f( 1, 1, 1 );
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 );
2202 qglEnable( GL_TEXTURE_2D );
2203 qglMatrixMode( GL_MODELVIEW );
2212 static void RB_TestGammaBias( void ) {
2213 byte image[G_HEIGHT][G_WIDTH][4];
2215 if ( r_testGammaBias.GetInteger() <= 0 ) {
2220 for ( int bias = -40 ; bias < 40 ; bias+=10, y += BAR_HEIGHT ) {
2222 for ( int c = 0 ; c < 4 ; c++ ) {
2223 int v = (int)(64 * scale + bias);
2224 scale = scale * 1.5;
2227 } else if ( v > 255 ) {
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;
2242 qglMatrixMode( GL_PROJECTION );
2243 GL_State( GLS_DEPTHFUNC_ALWAYS );
2244 qglColor3f( 1, 1, 1 );
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 );
2252 qglEnable( GL_TEXTURE_2D );
2253 qglMatrixMode( GL_MODELVIEW );
2260 Display a single image over most of the screen
2263 void RB_TestImage( void ) {
2268 image = tr.testImage;
2273 if ( tr.testVideo ) {
2276 cin = tr.testVideo->ImageForTime( (int)(1000 * ( backEnd.viewDef->floatTime - tr.testVideoStartTime ) ) );
2278 image->UploadScratch( cin.image, cin.imageWidth, cin.imageHeight );
2280 tr.testImage = NULL;
2286 max = image->uploadWidth > image->uploadHeight ? image->uploadWidth : image->uploadHeight;
2288 w = 0.25 * image->uploadWidth / max;
2289 h = 0.25 * image->uploadHeight / max;
2291 w *= (float)glConfig.vidHeight / glConfig.vidWidth;
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 );
2301 qglOrtho( 0, 1, 0, 1, -1, 1 );
2303 tr.testImage->Bind();
2304 qglBegin( GL_QUADS );
2306 qglTexCoord2f( 0, 1 );
2307 qglVertex2f( 0.5 - w, 0 );
2309 qglTexCoord2f( 0, 0 );
2310 qglVertex2f( 0.5 - w, h*2 );
2312 qglTexCoord2f( 1, 0 );
2313 qglVertex2f( 0.5 + w, h*2 );
2315 qglTexCoord2f( 1, 1 );
2316 qglVertex2f( 0.5 + w, 0 );
2321 qglMatrixMode( GL_MODELVIEW );
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 ) {
2335 RB_LogComment( "---------- RB_RenderDebugTools ----------\n" );
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 );
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 );
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
2362 if ( r_testGammaBias.GetInteger() > 0 ) {
2367 RB_ShowSilhouette();
2368 RB_ShowDepthBuffer();
2370 RB_ShowDebugLines();
2372 RB_ShowDebugPolygons();
2373 RB_ShowTrace( drawSurfs, numDrawSurfs );
2378 RB_ShutdownDebugTools
2381 void RB_ShutdownDebugTools( void ) {
2382 for ( int i = 0; i < MAX_DEBUG_POLYGONS; i++ ) {
2383 rb_debugPolygons[i].winding.Clear();