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