gl_rmain.c (39236B)
1 /* 2 Copyright (C) 1997-2001 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 // r_main.c 21 #include "gl_local.h" 22 23 void R_Clear (void); 24 25 viddef_t vid; 26 27 refimport_t ri; 28 29 model_t *r_worldmodel; 30 31 float gldepthmin, gldepthmax; 32 33 glconfig_t gl_config; 34 glstate_t gl_state; 35 36 image_t *r_notexture; // use for bad textures 37 image_t *r_particletexture; // little dot for particles 38 39 entity_t *currententity; 40 model_t *currentmodel; 41 42 cplane_t frustum[4]; 43 44 int r_visframecount; // bumped when going to a new PVS 45 int r_framecount; // used for dlight push checking 46 47 int c_brush_polys, c_alias_polys; 48 49 float v_blend[4]; // final blending color 50 51 void GL_Strings_f( void ); 52 53 // 54 // view origin 55 // 56 vec3_t vup; 57 vec3_t vpn; 58 vec3_t vright; 59 vec3_t r_origin; 60 61 float r_world_matrix[16]; 62 float r_base_world_matrix[16]; 63 64 // 65 // screen size info 66 // 67 refdef_t r_newrefdef; 68 69 int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; 70 71 cvar_t *r_norefresh; 72 cvar_t *r_drawentities; 73 cvar_t *r_drawworld; 74 cvar_t *r_speeds; 75 cvar_t *r_fullbright; 76 cvar_t *r_novis; 77 cvar_t *r_nocull; 78 cvar_t *r_lerpmodels; 79 cvar_t *r_lefthand; 80 81 cvar_t *r_lightlevel; // FIXME: This is a HACK to get the client's light level 82 83 cvar_t *gl_nosubimage; 84 cvar_t *gl_allow_software; 85 86 cvar_t *gl_vertex_arrays; 87 88 cvar_t *gl_particle_min_size; 89 cvar_t *gl_particle_max_size; 90 cvar_t *gl_particle_size; 91 cvar_t *gl_particle_att_a; 92 cvar_t *gl_particle_att_b; 93 cvar_t *gl_particle_att_c; 94 95 cvar_t *gl_ext_swapinterval; 96 cvar_t *gl_ext_palettedtexture; 97 cvar_t *gl_ext_multitexture; 98 cvar_t *gl_ext_pointparameters; 99 cvar_t *gl_ext_compiled_vertex_array; 100 101 cvar_t *gl_log; 102 cvar_t *gl_bitdepth; 103 cvar_t *gl_drawbuffer; 104 cvar_t *gl_driver; 105 cvar_t *gl_lightmap; 106 cvar_t *gl_shadows; 107 cvar_t *gl_mode; 108 cvar_t *gl_dynamic; 109 cvar_t *gl_monolightmap; 110 cvar_t *gl_modulate; 111 cvar_t *gl_nobind; 112 cvar_t *gl_round_down; 113 cvar_t *gl_picmip; 114 cvar_t *gl_skymip; 115 cvar_t *gl_showtris; 116 cvar_t *gl_ztrick; 117 cvar_t *gl_finish; 118 cvar_t *gl_clear; 119 cvar_t *gl_cull; 120 cvar_t *gl_polyblend; 121 cvar_t *gl_flashblend; 122 cvar_t *gl_playermip; 123 cvar_t *gl_saturatelighting; 124 cvar_t *gl_swapinterval; 125 cvar_t *gl_texturemode; 126 cvar_t *gl_texturealphamode; 127 cvar_t *gl_texturesolidmode; 128 cvar_t *gl_lockpvs; 129 130 cvar_t *gl_3dlabs_broken; 131 132 cvar_t *vid_fullscreen; 133 cvar_t *vid_gamma; 134 cvar_t *vid_ref; 135 136 /* 137 ================= 138 R_CullBox 139 140 Returns true if the box is completely outside the frustom 141 ================= 142 */ 143 qboolean R_CullBox (vec3_t mins, vec3_t maxs) 144 { 145 int i; 146 147 if (r_nocull->value) 148 return false; 149 150 for (i=0 ; i<4 ; i++) 151 if ( BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2) 152 return true; 153 return false; 154 } 155 156 157 void R_RotateForEntity (entity_t *e) 158 { 159 qglTranslatef (e->origin[0], e->origin[1], e->origin[2]); 160 161 qglRotatef (e->angles[1], 0, 0, 1); 162 qglRotatef (-e->angles[0], 0, 1, 0); 163 qglRotatef (-e->angles[2], 1, 0, 0); 164 } 165 166 /* 167 ============================================================= 168 169 SPRITE MODELS 170 171 ============================================================= 172 */ 173 174 175 /* 176 ================= 177 R_DrawSpriteModel 178 179 ================= 180 */ 181 void R_DrawSpriteModel (entity_t *e) 182 { 183 float alpha = 1.0F; 184 vec3_t point; 185 dsprframe_t *frame; 186 float *up, *right; 187 dsprite_t *psprite; 188 189 // don't even bother culling, because it's just a single 190 // polygon without a surface cache 191 192 psprite = (dsprite_t *)currentmodel->extradata; 193 194 #if 0 195 if (e->frame < 0 || e->frame >= psprite->numframes) 196 { 197 ri.Con_Printf (PRINT_ALL, "no such sprite frame %i\n", e->frame); 198 e->frame = 0; 199 } 200 #endif 201 e->frame %= psprite->numframes; 202 203 frame = &psprite->frames[e->frame]; 204 205 #if 0 206 if (psprite->type == SPR_ORIENTED) 207 { // bullet marks on walls 208 vec3_t v_forward, v_right, v_up; 209 210 AngleVectors (currententity->angles, v_forward, v_right, v_up); 211 up = v_up; 212 right = v_right; 213 } 214 else 215 #endif 216 { // normal sprite 217 up = vup; 218 right = vright; 219 } 220 221 if ( e->flags & RF_TRANSLUCENT ) 222 alpha = e->alpha; 223 224 if ( alpha != 1.0F ) 225 qglEnable( GL_BLEND ); 226 227 qglColor4f( 1, 1, 1, alpha ); 228 229 GL_Bind(currentmodel->skins[e->frame]->texnum); 230 231 GL_TexEnv( GL_MODULATE ); 232 233 if ( alpha == 1.0 ) 234 qglEnable (GL_ALPHA_TEST); 235 else 236 qglDisable( GL_ALPHA_TEST ); 237 238 qglBegin (GL_QUADS); 239 240 qglTexCoord2f (0, 1); 241 VectorMA (e->origin, -frame->origin_y, up, point); 242 VectorMA (point, -frame->origin_x, right, point); 243 qglVertex3fv (point); 244 245 qglTexCoord2f (0, 0); 246 VectorMA (e->origin, frame->height - frame->origin_y, up, point); 247 VectorMA (point, -frame->origin_x, right, point); 248 qglVertex3fv (point); 249 250 qglTexCoord2f (1, 0); 251 VectorMA (e->origin, frame->height - frame->origin_y, up, point); 252 VectorMA (point, frame->width - frame->origin_x, right, point); 253 qglVertex3fv (point); 254 255 qglTexCoord2f (1, 1); 256 VectorMA (e->origin, -frame->origin_y, up, point); 257 VectorMA (point, frame->width - frame->origin_x, right, point); 258 qglVertex3fv (point); 259 260 qglEnd (); 261 262 qglDisable (GL_ALPHA_TEST); 263 GL_TexEnv( GL_REPLACE ); 264 265 if ( alpha != 1.0F ) 266 qglDisable( GL_BLEND ); 267 268 qglColor4f( 1, 1, 1, 1 ); 269 } 270 271 //================================================================================== 272 273 /* 274 ============= 275 R_DrawNullModel 276 ============= 277 */ 278 void R_DrawNullModel (void) 279 { 280 vec3_t shadelight; 281 int i; 282 283 if ( currententity->flags & RF_FULLBRIGHT ) 284 shadelight[0] = shadelight[1] = shadelight[2] = 1.0F; 285 else 286 R_LightPoint (currententity->origin, shadelight); 287 288 qglPushMatrix (); 289 R_RotateForEntity (currententity); 290 291 qglDisable (GL_TEXTURE_2D); 292 qglColor3fv (shadelight); 293 294 qglBegin (GL_TRIANGLE_FAN); 295 qglVertex3f (0, 0, -16); 296 for (i=0 ; i<=4 ; i++) 297 qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0); 298 qglEnd (); 299 300 qglBegin (GL_TRIANGLE_FAN); 301 qglVertex3f (0, 0, 16); 302 for (i=4 ; i>=0 ; i--) 303 qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0); 304 qglEnd (); 305 306 qglColor3f (1,1,1); 307 qglPopMatrix (); 308 qglEnable (GL_TEXTURE_2D); 309 } 310 311 /* 312 ============= 313 R_DrawEntitiesOnList 314 ============= 315 */ 316 void R_DrawEntitiesOnList (void) 317 { 318 int i; 319 320 if (!r_drawentities->value) 321 return; 322 323 // draw non-transparent first 324 for (i=0 ; i<r_newrefdef.num_entities ; i++) 325 { 326 currententity = &r_newrefdef.entities[i]; 327 if (currententity->flags & RF_TRANSLUCENT) 328 continue; // solid 329 330 if ( currententity->flags & RF_BEAM ) 331 { 332 R_DrawBeam( currententity ); 333 } 334 else 335 { 336 currentmodel = currententity->model; 337 if (!currentmodel) 338 { 339 R_DrawNullModel (); 340 continue; 341 } 342 switch (currentmodel->type) 343 { 344 case mod_alias: 345 R_DrawAliasModel (currententity); 346 break; 347 case mod_brush: 348 R_DrawBrushModel (currententity); 349 break; 350 case mod_sprite: 351 R_DrawSpriteModel (currententity); 352 break; 353 default: 354 ri.Sys_Error (ERR_DROP, "Bad modeltype"); 355 break; 356 } 357 } 358 } 359 360 // draw transparent entities 361 // we could sort these if it ever becomes a problem... 362 qglDepthMask (0); // no z writes 363 for (i=0 ; i<r_newrefdef.num_entities ; i++) 364 { 365 currententity = &r_newrefdef.entities[i]; 366 if (!(currententity->flags & RF_TRANSLUCENT)) 367 continue; // solid 368 369 if ( currententity->flags & RF_BEAM ) 370 { 371 R_DrawBeam( currententity ); 372 } 373 else 374 { 375 currentmodel = currententity->model; 376 377 if (!currentmodel) 378 { 379 R_DrawNullModel (); 380 continue; 381 } 382 switch (currentmodel->type) 383 { 384 case mod_alias: 385 R_DrawAliasModel (currententity); 386 break; 387 case mod_brush: 388 R_DrawBrushModel (currententity); 389 break; 390 case mod_sprite: 391 R_DrawSpriteModel (currententity); 392 break; 393 default: 394 ri.Sys_Error (ERR_DROP, "Bad modeltype"); 395 break; 396 } 397 } 398 } 399 qglDepthMask (1); // back to writing 400 401 } 402 403 /* 404 ** GL_DrawParticles 405 ** 406 */ 407 void GL_DrawParticles( int num_particles, const particle_t particles[], const unsigned colortable[768] ) 408 { 409 const particle_t *p; 410 int i; 411 vec3_t up, right; 412 float scale; 413 byte color[4]; 414 415 GL_Bind(r_particletexture->texnum); 416 qglDepthMask( GL_FALSE ); // no z buffering 417 qglEnable( GL_BLEND ); 418 GL_TexEnv( GL_MODULATE ); 419 qglBegin( GL_TRIANGLES ); 420 421 VectorScale (vup, 1.5, up); 422 VectorScale (vright, 1.5, right); 423 424 for ( p = particles, i=0 ; i < num_particles ; i++,p++) 425 { 426 // hack a scale up to keep particles from disapearing 427 scale = ( p->origin[0] - r_origin[0] ) * vpn[0] + 428 ( p->origin[1] - r_origin[1] ) * vpn[1] + 429 ( p->origin[2] - r_origin[2] ) * vpn[2]; 430 431 if (scale < 20) 432 scale = 1; 433 else 434 scale = 1 + scale * 0.004; 435 436 *(int *)color = colortable[p->color]; 437 color[3] = p->alpha*255; 438 439 qglColor4ubv( color ); 440 441 qglTexCoord2f( 0.0625, 0.0625 ); 442 qglVertex3fv( p->origin ); 443 444 qglTexCoord2f( 1.0625, 0.0625 ); 445 qglVertex3f( p->origin[0] + up[0]*scale, 446 p->origin[1] + up[1]*scale, 447 p->origin[2] + up[2]*scale); 448 449 qglTexCoord2f( 0.0625, 1.0625 ); 450 qglVertex3f( p->origin[0] + right[0]*scale, 451 p->origin[1] + right[1]*scale, 452 p->origin[2] + right[2]*scale); 453 } 454 455 qglEnd (); 456 qglDisable( GL_BLEND ); 457 qglColor4f( 1,1,1,1 ); 458 qglDepthMask( 1 ); // back to normal Z buffering 459 GL_TexEnv( GL_REPLACE ); 460 } 461 462 /* 463 =============== 464 R_DrawParticles 465 =============== 466 */ 467 void R_DrawParticles (void) 468 { 469 if ( gl_ext_pointparameters->value && qglPointParameterfEXT ) 470 { 471 int i; 472 unsigned char color[4]; 473 const particle_t *p; 474 475 qglDepthMask( GL_FALSE ); 476 qglEnable( GL_BLEND ); 477 qglDisable( GL_TEXTURE_2D ); 478 479 qglPointSize( gl_particle_size->value ); 480 481 qglBegin( GL_POINTS ); 482 for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ ) 483 { 484 *(int *)color = d_8to24table[p->color]; 485 color[3] = p->alpha*255; 486 487 qglColor4ubv( color ); 488 489 qglVertex3fv( p->origin ); 490 } 491 qglEnd(); 492 493 qglDisable( GL_BLEND ); 494 qglColor4f( 1.0F, 1.0F, 1.0F, 1.0F ); 495 qglDepthMask( GL_TRUE ); 496 qglEnable( GL_TEXTURE_2D ); 497 498 } 499 else 500 { 501 GL_DrawParticles( r_newrefdef.num_particles, r_newrefdef.particles, d_8to24table ); 502 } 503 } 504 505 /* 506 ============ 507 R_PolyBlend 508 ============ 509 */ 510 void R_PolyBlend (void) 511 { 512 if (!gl_polyblend->value) 513 return; 514 if (!v_blend[3]) 515 return; 516 517 qglDisable (GL_ALPHA_TEST); 518 qglEnable (GL_BLEND); 519 qglDisable (GL_DEPTH_TEST); 520 qglDisable (GL_TEXTURE_2D); 521 522 qglLoadIdentity (); 523 524 // FIXME: get rid of these 525 qglRotatef (-90, 1, 0, 0); // put Z going up 526 qglRotatef (90, 0, 0, 1); // put Z going up 527 528 qglColor4fv (v_blend); 529 530 qglBegin (GL_QUADS); 531 532 qglVertex3f (10, 100, 100); 533 qglVertex3f (10, -100, 100); 534 qglVertex3f (10, -100, -100); 535 qglVertex3f (10, 100, -100); 536 qglEnd (); 537 538 qglDisable (GL_BLEND); 539 qglEnable (GL_TEXTURE_2D); 540 qglEnable (GL_ALPHA_TEST); 541 542 qglColor4f(1,1,1,1); 543 } 544 545 //======================================================================= 546 547 int SignbitsForPlane (cplane_t *out) 548 { 549 int bits, j; 550 551 // for fast box on planeside test 552 553 bits = 0; 554 for (j=0 ; j<3 ; j++) 555 { 556 if (out->normal[j] < 0) 557 bits |= 1<<j; 558 } 559 return bits; 560 } 561 562 563 void R_SetFrustum (void) 564 { 565 int i; 566 567 #if 0 568 /* 569 ** this code is wrong, since it presume a 90 degree FOV both in the 570 ** horizontal and vertical plane 571 */ 572 // front side is visible 573 VectorAdd (vpn, vright, frustum[0].normal); 574 VectorSubtract (vpn, vright, frustum[1].normal); 575 VectorAdd (vpn, vup, frustum[2].normal); 576 VectorSubtract (vpn, vup, frustum[3].normal); 577 578 // we theoretically don't need to normalize these vectors, but I do it 579 // anyway so that debugging is a little easier 580 VectorNormalize( frustum[0].normal ); 581 VectorNormalize( frustum[1].normal ); 582 VectorNormalize( frustum[2].normal ); 583 VectorNormalize( frustum[3].normal ); 584 #else 585 // rotate VPN right by FOV_X/2 degrees 586 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) ); 587 // rotate VPN left by FOV_X/2 degrees 588 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 ); 589 // rotate VPN up by FOV_X/2 degrees 590 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 ); 591 // rotate VPN down by FOV_X/2 degrees 592 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) ); 593 #endif 594 595 for (i=0 ; i<4 ; i++) 596 { 597 frustum[i].type = PLANE_ANYZ; 598 frustum[i].dist = DotProduct (r_origin, frustum[i].normal); 599 frustum[i].signbits = SignbitsForPlane (&frustum[i]); 600 } 601 } 602 603 //======================================================================= 604 605 /* 606 =============== 607 R_SetupFrame 608 =============== 609 */ 610 void R_SetupFrame (void) 611 { 612 int i; 613 mleaf_t *leaf; 614 615 r_framecount++; 616 617 // build the transformation matrix for the given view angles 618 VectorCopy (r_newrefdef.vieworg, r_origin); 619 620 AngleVectors (r_newrefdef.viewangles, vpn, vright, vup); 621 622 // current viewcluster 623 if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) ) 624 { 625 r_oldviewcluster = r_viewcluster; 626 r_oldviewcluster2 = r_viewcluster2; 627 leaf = Mod_PointInLeaf (r_origin, r_worldmodel); 628 r_viewcluster = r_viewcluster2 = leaf->cluster; 629 630 // check above and below so crossing solid water doesn't draw wrong 631 if (!leaf->contents) 632 { // look down a bit 633 vec3_t temp; 634 635 VectorCopy (r_origin, temp); 636 temp[2] -= 16; 637 leaf = Mod_PointInLeaf (temp, r_worldmodel); 638 if ( !(leaf->contents & CONTENTS_SOLID) && 639 (leaf->cluster != r_viewcluster2) ) 640 r_viewcluster2 = leaf->cluster; 641 } 642 else 643 { // look up a bit 644 vec3_t temp; 645 646 VectorCopy (r_origin, temp); 647 temp[2] += 16; 648 leaf = Mod_PointInLeaf (temp, r_worldmodel); 649 if ( !(leaf->contents & CONTENTS_SOLID) && 650 (leaf->cluster != r_viewcluster2) ) 651 r_viewcluster2 = leaf->cluster; 652 } 653 } 654 655 for (i=0 ; i<4 ; i++) 656 v_blend[i] = r_newrefdef.blend[i]; 657 658 c_brush_polys = 0; 659 c_alias_polys = 0; 660 661 // clear out the portion of the screen that the NOWORLDMODEL defines 662 if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) 663 { 664 qglEnable( GL_SCISSOR_TEST ); 665 qglClearColor( 0.3, 0.3, 0.3, 1 ); 666 qglScissor( r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height ); 667 qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 668 qglClearColor( 1, 0, 0.5, 0.5 ); 669 qglDisable( GL_SCISSOR_TEST ); 670 } 671 } 672 673 674 void MYgluPerspective( GLdouble fovy, GLdouble aspect, 675 GLdouble zNear, GLdouble zFar ) 676 { 677 GLdouble xmin, xmax, ymin, ymax; 678 679 ymax = zNear * tan( fovy * M_PI / 360.0 ); 680 ymin = -ymax; 681 682 xmin = ymin * aspect; 683 xmax = ymax * aspect; 684 685 xmin += -( 2 * gl_state.camera_separation ) / zNear; 686 xmax += -( 2 * gl_state.camera_separation ) / zNear; 687 688 qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); 689 } 690 691 692 /* 693 ============= 694 R_SetupGL 695 ============= 696 */ 697 void R_SetupGL (void) 698 { 699 float screenaspect; 700 // float yfov; 701 int x, x2, y2, y, w, h; 702 703 // 704 // set up viewport 705 // 706 x = floor(r_newrefdef.x * vid.width / vid.width); 707 x2 = ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width); 708 y = floor(vid.height - r_newrefdef.y * vid.height / vid.height); 709 y2 = ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height); 710 711 w = x2 - x; 712 h = y - y2; 713 714 qglViewport (x, y2, w, h); 715 716 // 717 // set up projection matrix 718 // 719 screenaspect = (float)r_newrefdef.width/r_newrefdef.height; 720 // yfov = 2*atan((float)r_newrefdef.height/r_newrefdef.width)*180/M_PI; 721 qglMatrixMode(GL_PROJECTION); 722 qglLoadIdentity (); 723 MYgluPerspective (r_newrefdef.fov_y, screenaspect, 4, 4096); 724 725 qglCullFace(GL_FRONT); 726 727 qglMatrixMode(GL_MODELVIEW); 728 qglLoadIdentity (); 729 730 qglRotatef (-90, 1, 0, 0); // put Z going up 731 qglRotatef (90, 0, 0, 1); // put Z going up 732 qglRotatef (-r_newrefdef.viewangles[2], 1, 0, 0); 733 qglRotatef (-r_newrefdef.viewangles[0], 0, 1, 0); 734 qglRotatef (-r_newrefdef.viewangles[1], 0, 0, 1); 735 qglTranslatef (-r_newrefdef.vieworg[0], -r_newrefdef.vieworg[1], -r_newrefdef.vieworg[2]); 736 737 // if ( gl_state.camera_separation != 0 && gl_state.stereo_enabled ) 738 // qglTranslatef ( gl_state.camera_separation, 0, 0 ); 739 740 qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); 741 742 // 743 // set drawing parms 744 // 745 if (gl_cull->value) 746 qglEnable(GL_CULL_FACE); 747 else 748 qglDisable(GL_CULL_FACE); 749 750 qglDisable(GL_BLEND); 751 qglDisable(GL_ALPHA_TEST); 752 qglEnable(GL_DEPTH_TEST); 753 } 754 755 /* 756 ============= 757 R_Clear 758 ============= 759 */ 760 void R_Clear (void) 761 { 762 if (gl_ztrick->value) 763 { 764 static int trickframe; 765 766 if (gl_clear->value) 767 qglClear (GL_COLOR_BUFFER_BIT); 768 769 trickframe++; 770 if (trickframe & 1) 771 { 772 gldepthmin = 0; 773 gldepthmax = 0.49999; 774 qglDepthFunc (GL_LEQUAL); 775 } 776 else 777 { 778 gldepthmin = 1; 779 gldepthmax = 0.5; 780 qglDepthFunc (GL_GEQUAL); 781 } 782 } 783 else 784 { 785 if (gl_clear->value) 786 qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 787 else 788 qglClear (GL_DEPTH_BUFFER_BIT); 789 gldepthmin = 0; 790 gldepthmax = 1; 791 qglDepthFunc (GL_LEQUAL); 792 } 793 794 qglDepthRange (gldepthmin, gldepthmax); 795 796 } 797 798 void R_Flash( void ) 799 { 800 R_PolyBlend (); 801 } 802 803 /* 804 ================ 805 R_RenderView 806 807 r_newrefdef must be set before the first call 808 ================ 809 */ 810 void R_RenderView (refdef_t *fd) 811 { 812 if (r_norefresh->value) 813 return; 814 815 r_newrefdef = *fd; 816 817 if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) ) 818 ri.Sys_Error (ERR_DROP, "R_RenderView: NULL worldmodel"); 819 820 if (r_speeds->value) 821 { 822 c_brush_polys = 0; 823 c_alias_polys = 0; 824 } 825 826 R_PushDlights (); 827 828 if (gl_finish->value) 829 qglFinish (); 830 831 R_SetupFrame (); 832 833 R_SetFrustum (); 834 835 R_SetupGL (); 836 837 R_MarkLeaves (); // done here so we know if we're in water 838 839 R_DrawWorld (); 840 841 R_DrawEntitiesOnList (); 842 843 R_RenderDlights (); 844 845 R_DrawParticles (); 846 847 R_DrawAlphaSurfaces (); 848 849 R_Flash(); 850 851 if (r_speeds->value) 852 { 853 ri.Con_Printf (PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n", 854 c_brush_polys, 855 c_alias_polys, 856 c_visible_textures, 857 c_visible_lightmaps); 858 } 859 } 860 861 862 void R_SetGL2D (void) 863 { 864 // set 2D virtual screen size 865 qglViewport (0,0, vid.width, vid.height); 866 qglMatrixMode(GL_PROJECTION); 867 qglLoadIdentity (); 868 qglOrtho (0, vid.width, vid.height, 0, -99999, 99999); 869 qglMatrixMode(GL_MODELVIEW); 870 qglLoadIdentity (); 871 qglDisable (GL_DEPTH_TEST); 872 qglDisable (GL_CULL_FACE); 873 qglDisable (GL_BLEND); 874 qglEnable (GL_ALPHA_TEST); 875 qglColor4f (1,1,1,1); 876 } 877 878 static void GL_DrawColoredStereoLinePair( float r, float g, float b, float y ) 879 { 880 qglColor3f( r, g, b ); 881 qglVertex2f( 0, y ); 882 qglVertex2f( vid.width, y ); 883 qglColor3f( 0, 0, 0 ); 884 qglVertex2f( 0, y + 1 ); 885 qglVertex2f( vid.width, y + 1 ); 886 } 887 888 static void GL_DrawStereoPattern( void ) 889 { 890 int i; 891 892 if ( !( gl_config.renderer & GL_RENDERER_INTERGRAPH ) ) 893 return; 894 895 if ( !gl_state.stereo_enabled ) 896 return; 897 898 R_SetGL2D(); 899 900 qglDrawBuffer( GL_BACK_LEFT ); 901 902 for ( i = 0; i < 20; i++ ) 903 { 904 qglBegin( GL_LINES ); 905 GL_DrawColoredStereoLinePair( 1, 0, 0, 0 ); 906 GL_DrawColoredStereoLinePair( 1, 0, 0, 2 ); 907 GL_DrawColoredStereoLinePair( 1, 0, 0, 4 ); 908 GL_DrawColoredStereoLinePair( 1, 0, 0, 6 ); 909 GL_DrawColoredStereoLinePair( 0, 1, 0, 8 ); 910 GL_DrawColoredStereoLinePair( 1, 1, 0, 10); 911 GL_DrawColoredStereoLinePair( 1, 1, 0, 12); 912 GL_DrawColoredStereoLinePair( 0, 1, 0, 14); 913 qglEnd(); 914 915 GLimp_EndFrame(); 916 } 917 } 918 919 920 /* 921 ==================== 922 R_SetLightLevel 923 924 ==================== 925 */ 926 void R_SetLightLevel (void) 927 { 928 vec3_t shadelight; 929 930 if (r_newrefdef.rdflags & RDF_NOWORLDMODEL) 931 return; 932 933 // save off light value for server to look at (BIG HACK!) 934 935 R_LightPoint (r_newrefdef.vieworg, shadelight); 936 937 // pick the greatest component, which should be the same 938 // as the mono value returned by software 939 if (shadelight[0] > shadelight[1]) 940 { 941 if (shadelight[0] > shadelight[2]) 942 r_lightlevel->value = 150*shadelight[0]; 943 else 944 r_lightlevel->value = 150*shadelight[2]; 945 } 946 else 947 { 948 if (shadelight[1] > shadelight[2]) 949 r_lightlevel->value = 150*shadelight[1]; 950 else 951 r_lightlevel->value = 150*shadelight[2]; 952 } 953 954 } 955 956 /* 957 @@@@@@@@@@@@@@@@@@@@@ 958 R_RenderFrame 959 960 @@@@@@@@@@@@@@@@@@@@@ 961 */ 962 void R_RenderFrame (refdef_t *fd) 963 { 964 R_RenderView( fd ); 965 R_SetLightLevel (); 966 R_SetGL2D (); 967 } 968 969 970 void R_Register( void ) 971 { 972 r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE ); 973 r_norefresh = ri.Cvar_Get ("r_norefresh", "0", 0); 974 r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0); 975 r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0); 976 r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0); 977 r_novis = ri.Cvar_Get ("r_novis", "0", 0); 978 r_nocull = ri.Cvar_Get ("r_nocull", "0", 0); 979 r_lerpmodels = ri.Cvar_Get ("r_lerpmodels", "1", 0); 980 r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); 981 982 r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0); 983 984 gl_nosubimage = ri.Cvar_Get( "gl_nosubimage", "0", 0 ); 985 gl_allow_software = ri.Cvar_Get( "gl_allow_software", "0", 0 ); 986 987 gl_particle_min_size = ri.Cvar_Get( "gl_particle_min_size", "2", CVAR_ARCHIVE ); 988 gl_particle_max_size = ri.Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE ); 989 gl_particle_size = ri.Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE ); 990 gl_particle_att_a = ri.Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE ); 991 gl_particle_att_b = ri.Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE ); 992 gl_particle_att_c = ri.Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE ); 993 994 gl_modulate = ri.Cvar_Get ("gl_modulate", "1", CVAR_ARCHIVE ); 995 gl_log = ri.Cvar_Get( "gl_log", "0", 0 ); 996 gl_bitdepth = ri.Cvar_Get( "gl_bitdepth", "0", 0 ); 997 gl_mode = ri.Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE ); 998 gl_lightmap = ri.Cvar_Get ("gl_lightmap", "0", 0); 999 gl_shadows = ri.Cvar_Get ("gl_shadows", "0", CVAR_ARCHIVE ); 1000 gl_dynamic = ri.Cvar_Get ("gl_dynamic", "1", 0); 1001 gl_nobind = ri.Cvar_Get ("gl_nobind", "0", 0); 1002 gl_round_down = ri.Cvar_Get ("gl_round_down", "1", 0); 1003 gl_picmip = ri.Cvar_Get ("gl_picmip", "0", 0); 1004 gl_skymip = ri.Cvar_Get ("gl_skymip", "0", 0); 1005 gl_showtris = ri.Cvar_Get ("gl_showtris", "0", 0); 1006 gl_ztrick = ri.Cvar_Get ("gl_ztrick", "0", 0); 1007 gl_finish = ri.Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE); 1008 gl_clear = ri.Cvar_Get ("gl_clear", "0", 0); 1009 gl_cull = ri.Cvar_Get ("gl_cull", "1", 0); 1010 gl_polyblend = ri.Cvar_Get ("gl_polyblend", "1", 0); 1011 gl_flashblend = ri.Cvar_Get ("gl_flashblend", "0", 0); 1012 gl_playermip = ri.Cvar_Get ("gl_playermip", "0", 0); 1013 gl_monolightmap = ri.Cvar_Get( "gl_monolightmap", "0", 0 ); 1014 gl_driver = ri.Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE ); 1015 gl_texturemode = ri.Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE ); 1016 gl_texturealphamode = ri.Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE ); 1017 gl_texturesolidmode = ri.Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE ); 1018 gl_lockpvs = ri.Cvar_Get( "gl_lockpvs", "0", 0 ); 1019 1020 gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "0", CVAR_ARCHIVE ); 1021 1022 gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE ); 1023 gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE ); 1024 gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE ); 1025 gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE ); 1026 gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE ); 1027 1028 gl_drawbuffer = ri.Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 ); 1029 gl_swapinterval = ri.Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE ); 1030 1031 gl_saturatelighting = ri.Cvar_Get( "gl_saturatelighting", "0", 0 ); 1032 1033 gl_3dlabs_broken = ri.Cvar_Get( "gl_3dlabs_broken", "1", CVAR_ARCHIVE ); 1034 1035 vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE ); 1036 vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE ); 1037 vid_ref = ri.Cvar_Get( "vid_ref", "soft", CVAR_ARCHIVE ); 1038 1039 ri.Cmd_AddCommand( "imagelist", GL_ImageList_f ); 1040 ri.Cmd_AddCommand( "screenshot", GL_ScreenShot_f ); 1041 ri.Cmd_AddCommand( "modellist", Mod_Modellist_f ); 1042 ri.Cmd_AddCommand( "gl_strings", GL_Strings_f ); 1043 } 1044 1045 /* 1046 ================== 1047 R_SetMode 1048 ================== 1049 */ 1050 qboolean R_SetMode (void) 1051 { 1052 rserr_t err; 1053 qboolean fullscreen; 1054 1055 if ( vid_fullscreen->modified && !gl_config.allow_cds ) 1056 { 1057 ri.Con_Printf( PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n" ); 1058 ri.Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value ); 1059 vid_fullscreen->modified = false; 1060 } 1061 1062 fullscreen = vid_fullscreen->value; 1063 1064 vid_fullscreen->modified = false; 1065 gl_mode->modified = false; 1066 1067 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, fullscreen ) ) == rserr_ok ) 1068 { 1069 gl_state.prev_mode = gl_mode->value; 1070 } 1071 else 1072 { 1073 if ( err == rserr_invalid_fullscreen ) 1074 { 1075 ri.Cvar_SetValue( "vid_fullscreen", 0); 1076 vid_fullscreen->modified = false; 1077 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" ); 1078 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, false ) ) == rserr_ok ) 1079 return true; 1080 } 1081 else if ( err == rserr_invalid_mode ) 1082 { 1083 ri.Cvar_SetValue( "gl_mode", gl_state.prev_mode ); 1084 gl_mode->modified = false; 1085 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n" ); 1086 } 1087 1088 // try setting it back to something safe 1089 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok ) 1090 { 1091 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n" ); 1092 return false; 1093 } 1094 } 1095 return true; 1096 } 1097 1098 /* 1099 =============== 1100 R_Init 1101 =============== 1102 */ 1103 int R_Init( void *hinstance, void *hWnd ) 1104 { 1105 char renderer_buffer[1000]; 1106 char vendor_buffer[1000]; 1107 int err; 1108 int j; 1109 extern float r_turbsin[256]; 1110 1111 for ( j = 0; j < 256; j++ ) 1112 { 1113 r_turbsin[j] *= 0.5; 1114 } 1115 1116 ri.Con_Printf (PRINT_ALL, "ref_gl version: "REF_VERSION"\n"); 1117 1118 Draw_GetPalette (); 1119 1120 R_Register(); 1121 1122 // initialize our QGL dynamic bindings 1123 if ( !QGL_Init( gl_driver->string ) ) 1124 { 1125 QGL_Shutdown(); 1126 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string ); 1127 return -1; 1128 } 1129 1130 // initialize OS-specific parts of OpenGL 1131 if ( !GLimp_Init( hinstance, hWnd ) ) 1132 { 1133 QGL_Shutdown(); 1134 return -1; 1135 } 1136 1137 // set our "safe" modes 1138 gl_state.prev_mode = 3; 1139 1140 // create the window and set up the context 1141 if ( !R_SetMode () ) 1142 { 1143 QGL_Shutdown(); 1144 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n" ); 1145 return -1; 1146 } 1147 1148 ri.Vid_MenuInit(); 1149 1150 /* 1151 ** get our various GL strings 1152 */ 1153 gl_config.vendor_string = qglGetString (GL_VENDOR); 1154 ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string ); 1155 gl_config.renderer_string = qglGetString (GL_RENDERER); 1156 ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string ); 1157 gl_config.version_string = qglGetString (GL_VERSION); 1158 ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string ); 1159 gl_config.extensions_string = qglGetString (GL_EXTENSIONS); 1160 ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string ); 1161 1162 strcpy( renderer_buffer, gl_config.renderer_string ); 1163 strlwr( renderer_buffer ); 1164 1165 strcpy( vendor_buffer, gl_config.vendor_string ); 1166 strlwr( vendor_buffer ); 1167 1168 if ( strstr( renderer_buffer, "voodoo" ) ) 1169 { 1170 if ( !strstr( renderer_buffer, "rush" ) ) 1171 gl_config.renderer = GL_RENDERER_VOODOO; 1172 else 1173 gl_config.renderer = GL_RENDERER_VOODOO_RUSH; 1174 } 1175 else if ( strstr( vendor_buffer, "sgi" ) ) 1176 gl_config.renderer = GL_RENDERER_SGI; 1177 else if ( strstr( renderer_buffer, "permedia" ) ) 1178 gl_config.renderer = GL_RENDERER_PERMEDIA2; 1179 else if ( strstr( renderer_buffer, "glint" ) ) 1180 gl_config.renderer = GL_RENDERER_GLINT_MX; 1181 else if ( strstr( renderer_buffer, "glzicd" ) ) 1182 gl_config.renderer = GL_RENDERER_REALIZM; 1183 else if ( strstr( renderer_buffer, "gdi" ) ) 1184 gl_config.renderer = GL_RENDERER_MCD; 1185 else if ( strstr( renderer_buffer, "pcx2" ) ) 1186 gl_config.renderer = GL_RENDERER_PCX2; 1187 else if ( strstr( renderer_buffer, "verite" ) ) 1188 gl_config.renderer = GL_RENDERER_RENDITION; 1189 else 1190 gl_config.renderer = GL_RENDERER_OTHER; 1191 1192 if ( toupper( gl_monolightmap->string[1] ) != 'F' ) 1193 { 1194 if ( gl_config.renderer == GL_RENDERER_PERMEDIA2 ) 1195 { 1196 ri.Cvar_Set( "gl_monolightmap", "A" ); 1197 ri.Con_Printf( PRINT_ALL, "...using gl_monolightmap 'a'\n" ); 1198 } 1199 else if ( gl_config.renderer & GL_RENDERER_POWERVR ) 1200 { 1201 ri.Cvar_Set( "gl_monolightmap", "0" ); 1202 } 1203 else 1204 { 1205 ri.Cvar_Set( "gl_monolightmap", "0" ); 1206 } 1207 } 1208 1209 // power vr can't have anything stay in the framebuffer, so 1210 // the screen needs to redraw the tiled background every frame 1211 if ( gl_config.renderer & GL_RENDERER_POWERVR ) 1212 { 1213 ri.Cvar_Set( "scr_drawall", "1" ); 1214 } 1215 else 1216 { 1217 ri.Cvar_Set( "scr_drawall", "0" ); 1218 } 1219 1220 // MCD has buffering issues 1221 if ( gl_config.renderer == GL_RENDERER_MCD ) 1222 { 1223 ri.Cvar_SetValue( "gl_finish", 1 ); 1224 } 1225 1226 if ( gl_config.renderer & GL_RENDERER_3DLABS ) 1227 { 1228 if ( gl_3dlabs_broken->value ) 1229 gl_config.allow_cds = false; 1230 else 1231 gl_config.allow_cds = true; 1232 } 1233 else 1234 { 1235 gl_config.allow_cds = true; 1236 } 1237 1238 if ( gl_config.allow_cds ) 1239 ri.Con_Printf( PRINT_ALL, "...allowing CDS\n" ); 1240 else 1241 ri.Con_Printf( PRINT_ALL, "...disabling CDS\n" ); 1242 1243 /* 1244 ** grab extensions 1245 */ 1246 #ifdef WIN32 1247 if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) || 1248 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) ) 1249 { 1250 ri.Con_Printf( PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n" ); 1251 qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" ); 1252 qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" ); 1253 } 1254 else 1255 { 1256 ri.Con_Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" ); 1257 } 1258 1259 if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) ) 1260 { 1261 qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" ); 1262 ri.Con_Printf( PRINT_ALL, "...enabling WGL_EXT_swap_control\n" ); 1263 } 1264 else 1265 { 1266 ri.Con_Printf( PRINT_ALL, "...WGL_EXT_swap_control not found\n" ); 1267 } 1268 1269 if ( strstr( gl_config.extensions_string, "GL_EXT_point_parameters" ) ) 1270 { 1271 if ( gl_ext_pointparameters->value ) 1272 { 1273 qglPointParameterfEXT = ( void (APIENTRY *)( GLenum, GLfloat ) ) qwglGetProcAddress( "glPointParameterfEXT" ); 1274 qglPointParameterfvEXT = ( void (APIENTRY *)( GLenum, const GLfloat * ) ) qwglGetProcAddress( "glPointParameterfvEXT" ); 1275 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_point_parameters\n" ); 1276 } 1277 else 1278 { 1279 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_point_parameters\n" ); 1280 } 1281 } 1282 else 1283 { 1284 ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" ); 1285 } 1286 1287 if ( strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) && 1288 strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) ) 1289 { 1290 if ( gl_ext_palettedtexture->value ) 1291 { 1292 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" ); 1293 qglColorTableEXT = ( void ( APIENTRY * ) ( int, int, int, int, int, const void * ) ) qwglGetProcAddress( "glColorTableEXT" ); 1294 } 1295 else 1296 { 1297 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" ); 1298 } 1299 } 1300 else 1301 { 1302 ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" ); 1303 } 1304 1305 if ( strstr( gl_config.extensions_string, "GL_SGIS_multitexture" ) ) 1306 { 1307 if ( gl_ext_multitexture->value ) 1308 { 1309 ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_multitexture\n" ); 1310 qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMTexCoord2fSGIS" ); 1311 qglSelectTextureSGIS = ( void * ) qwglGetProcAddress( "glSelectTextureSGIS" ); 1312 } 1313 else 1314 { 1315 ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_multitexture\n" ); 1316 } 1317 } 1318 else 1319 { 1320 ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture not found\n" ); 1321 } 1322 #endif 1323 1324 GL_SetDefaultState(); 1325 1326 /* 1327 ** draw our stereo patterns 1328 */ 1329 #if 0 // commented out until H3D pays us the money they owe us 1330 GL_DrawStereoPattern(); 1331 #endif 1332 1333 GL_InitImages (); 1334 Mod_Init (); 1335 R_InitParticleTexture (); 1336 Draw_InitLocal (); 1337 1338 err = qglGetError(); 1339 if ( err != GL_NO_ERROR ) 1340 ri.Con_Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); 1341 } 1342 1343 /* 1344 =============== 1345 R_Shutdown 1346 =============== 1347 */ 1348 void R_Shutdown (void) 1349 { 1350 ri.Cmd_RemoveCommand ("modellist"); 1351 ri.Cmd_RemoveCommand ("screenshot"); 1352 ri.Cmd_RemoveCommand ("imagelist"); 1353 ri.Cmd_RemoveCommand ("gl_strings"); 1354 1355 Mod_FreeAll (); 1356 1357 GL_ShutdownImages (); 1358 1359 /* 1360 ** shut down OS specific OpenGL stuff like contexts, etc. 1361 */ 1362 GLimp_Shutdown(); 1363 1364 /* 1365 ** shutdown our QGL subsystem 1366 */ 1367 QGL_Shutdown(); 1368 } 1369 1370 1371 1372 /* 1373 @@@@@@@@@@@@@@@@@@@@@ 1374 R_BeginFrame 1375 @@@@@@@@@@@@@@@@@@@@@ 1376 */ 1377 void R_BeginFrame( float camera_separation ) 1378 { 1379 1380 gl_state.camera_separation = camera_separation; 1381 1382 /* 1383 ** change modes if necessary 1384 */ 1385 if ( gl_mode->modified || vid_fullscreen->modified ) 1386 { // FIXME: only restart if CDS is required 1387 cvar_t *ref; 1388 1389 ref = ri.Cvar_Get ("vid_ref", "gl", 0); 1390 ref->modified = true; 1391 } 1392 1393 if ( gl_log->modified ) 1394 { 1395 GLimp_EnableLogging( gl_log->value ); 1396 gl_log->modified = false; 1397 } 1398 1399 if ( gl_log->value ) 1400 { 1401 GLimp_LogNewFrame(); 1402 } 1403 1404 /* 1405 ** update 3Dfx gamma -- it is expected that a user will do a vid_restart 1406 ** after tweaking this value 1407 */ 1408 if ( vid_gamma->modified ) 1409 { 1410 vid_gamma->modified = false; 1411 1412 if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) ) 1413 { 1414 char envbuffer[1024]; 1415 float g; 1416 1417 g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F; 1418 Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g ); 1419 putenv( envbuffer ); 1420 Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g ); 1421 putenv( envbuffer ); 1422 } 1423 } 1424 1425 GLimp_BeginFrame( camera_separation ); 1426 1427 /* 1428 ** go into 2D mode 1429 */ 1430 qglViewport (0,0, vid.width, vid.height); 1431 qglMatrixMode(GL_PROJECTION); 1432 qglLoadIdentity (); 1433 qglOrtho (0, vid.width, vid.height, 0, -99999, 99999); 1434 qglMatrixMode(GL_MODELVIEW); 1435 qglLoadIdentity (); 1436 qglDisable (GL_DEPTH_TEST); 1437 qglDisable (GL_CULL_FACE); 1438 qglDisable (GL_BLEND); 1439 qglEnable (GL_ALPHA_TEST); 1440 qglColor4f (1,1,1,1); 1441 1442 /* 1443 ** draw buffer stuff 1444 */ 1445 if ( gl_drawbuffer->modified ) 1446 { 1447 gl_drawbuffer->modified = false; 1448 1449 if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled ) 1450 { 1451 if ( Q_stricmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 ) 1452 qglDrawBuffer( GL_FRONT ); 1453 else 1454 qglDrawBuffer( GL_BACK ); 1455 } 1456 } 1457 1458 /* 1459 ** texturemode stuff 1460 */ 1461 if ( gl_texturemode->modified ) 1462 { 1463 GL_TextureMode( gl_texturemode->string ); 1464 gl_texturemode->modified = false; 1465 } 1466 1467 if ( gl_texturealphamode->modified ) 1468 { 1469 GL_TextureAlphaMode( gl_texturealphamode->string ); 1470 gl_texturealphamode->modified = false; 1471 } 1472 1473 if ( gl_texturesolidmode->modified ) 1474 { 1475 GL_TextureSolidMode( gl_texturesolidmode->string ); 1476 gl_texturesolidmode->modified = false; 1477 } 1478 1479 /* 1480 ** swapinterval stuff 1481 */ 1482 GL_UpdateSwapInterval(); 1483 1484 // 1485 // clear screen if desired 1486 // 1487 R_Clear (); 1488 } 1489 1490 /* 1491 ============= 1492 R_SetPalette 1493 ============= 1494 */ 1495 unsigned r_rawpalette[256]; 1496 1497 void R_SetPalette ( const unsigned char *palette) 1498 { 1499 int i; 1500 1501 byte *rp = ( byte * ) r_rawpalette; 1502 1503 if ( palette ) 1504 { 1505 for ( i = 0; i < 256; i++ ) 1506 { 1507 rp[i*4+0] = palette[i*3+0]; 1508 rp[i*4+1] = palette[i*3+1]; 1509 rp[i*4+2] = palette[i*3+2]; 1510 rp[i*4+3] = 0xff; 1511 } 1512 } 1513 else 1514 { 1515 for ( i = 0; i < 256; i++ ) 1516 { 1517 rp[i*4+0] = d_8to24table[i] & 0xff; 1518 rp[i*4+1] = ( d_8to24table[i] >> 8 ) & 0xff; 1519 rp[i*4+2] = ( d_8to24table[i] >> 16 ) & 0xff; 1520 rp[i*4+3] = 0xff; 1521 } 1522 } 1523 GL_SetTexturePalette( r_rawpalette ); 1524 1525 qglClearColor (0,0,0,0); 1526 qglClear (GL_COLOR_BUFFER_BIT); 1527 qglClearColor (1,0, 0.5 , 0.5); 1528 } 1529 1530 /* 1531 ** R_DrawBeam 1532 */ 1533 void R_DrawBeam( entity_t *e ) 1534 { 1535 #define NUM_BEAM_SEGS 6 1536 1537 int i; 1538 float r, g, b; 1539 1540 vec3_t perpvec; 1541 vec3_t direction, normalized_direction; 1542 vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; 1543 vec3_t oldorigin, origin; 1544 1545 oldorigin[0] = e->oldorigin[0]; 1546 oldorigin[1] = e->oldorigin[1]; 1547 oldorigin[2] = e->oldorigin[2]; 1548 1549 origin[0] = e->origin[0]; 1550 origin[1] = e->origin[1]; 1551 origin[2] = e->origin[2]; 1552 1553 normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; 1554 normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; 1555 normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; 1556 1557 if ( VectorNormalize( normalized_direction ) == 0 ) 1558 return; 1559 1560 PerpendicularVector( perpvec, normalized_direction ); 1561 VectorScale( perpvec, e->frame / 2, perpvec ); 1562 1563 for ( i = 0; i < 6; i++ ) 1564 { 1565 RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); 1566 VectorAdd( start_points[i], origin, start_points[i] ); 1567 VectorAdd( start_points[i], direction, end_points[i] ); 1568 } 1569 1570 qglDisable( GL_TEXTURE_2D ); 1571 qglEnable( GL_BLEND ); 1572 qglDepthMask( GL_FALSE ); 1573 1574 r = ( d_8to24table[e->skinnum & 0xFF] ) & 0xFF; 1575 g = ( d_8to24table[e->skinnum & 0xFF] >> 8 ) & 0xFF; 1576 b = ( d_8to24table[e->skinnum & 0xFF] >> 16 ) & 0xFF; 1577 1578 r *= 1/255.0F; 1579 g *= 1/255.0F; 1580 b *= 1/255.0F; 1581 1582 qglColor4f( r, g, b, e->alpha ); 1583 1584 qglBegin( GL_TRIANGLE_STRIP ); 1585 for ( i = 0; i < NUM_BEAM_SEGS; i++ ) 1586 { 1587 qglVertex3fv( start_points[i] ); 1588 qglVertex3fv( end_points[i] ); 1589 qglVertex3fv( start_points[(i+1)%NUM_BEAM_SEGS] ); 1590 qglVertex3fv( end_points[(i+1)%NUM_BEAM_SEGS] ); 1591 } 1592 qglEnd(); 1593 1594 qglEnable( GL_TEXTURE_2D ); 1595 qglDisable( GL_BLEND ); 1596 qglDepthMask( GL_TRUE ); 1597 } 1598 1599 //=================================================================== 1600 1601 1602 void R_BeginRegistration (char *map); 1603 struct model_s *R_RegisterModel (char *name); 1604 struct image_s *R_RegisterSkin (char *name); 1605 void R_SetSky (char *name, float rotate, vec3_t axis); 1606 void R_EndRegistration (void); 1607 1608 void R_RenderFrame (refdef_t *fd); 1609 1610 struct image_s *Draw_FindPic (char *name); 1611 1612 void Draw_Pic (int x, int y, char *name); 1613 void Draw_Char (int x, int y, int c); 1614 void Draw_TileClear (int x, int y, int w, int h, char *name); 1615 void Draw_Fill (int x, int y, int w, int h, int c); 1616 void Draw_FadeScreen (void); 1617 1618 /* 1619 @@@@@@@@@@@@@@@@@@@@@ 1620 GetRefAPI 1621 1622 @@@@@@@@@@@@@@@@@@@@@ 1623 */ 1624 refexport_t GetRefAPI (refimport_t rimp ) 1625 { 1626 refexport_t re; 1627 1628 ri = rimp; 1629 1630 re.api_version = API_VERSION; 1631 1632 re.BeginRegistration = R_BeginRegistration; 1633 re.RegisterModel = R_RegisterModel; 1634 re.RegisterSkin = R_RegisterSkin; 1635 re.RegisterPic = Draw_FindPic; 1636 re.SetSky = R_SetSky; 1637 re.EndRegistration = R_EndRegistration; 1638 1639 re.RenderFrame = R_RenderFrame; 1640 1641 re.DrawGetPicSize = Draw_GetPicSize; 1642 re.DrawPic = Draw_Pic; 1643 re.DrawStretchPic = Draw_StretchPic; 1644 re.DrawChar = Draw_Char; 1645 re.DrawTileClear = Draw_TileClear; 1646 re.DrawFill = Draw_Fill; 1647 re.DrawFadeScreen= Draw_FadeScreen; 1648 1649 re.DrawStretchRaw = Draw_StretchRaw; 1650 1651 re.Init = R_Init; 1652 re.Shutdown = R_Shutdown; 1653 1654 re.CinematicSetPalette = R_SetPalette; 1655 re.BeginFrame = R_BeginFrame; 1656 re.EndFrame = GLimp_EndFrame; 1657 1658 re.AppActivate = GLimp_AppActivate; 1659 1660 Swap_Init (); 1661 1662 return re; 1663 } 1664 1665 1666 #ifndef REF_HARD_LINKED 1667 // this is only here so the functions in q_shared.c and q_shwin.c can link 1668 void Sys_Error (char *error, ...) 1669 { 1670 va_list argptr; 1671 char text[1024]; 1672 1673 va_start (argptr, error); 1674 vsprintf (text, error, argptr); 1675 va_end (argptr); 1676 1677 ri.Sys_Error (ERR_FATAL, "%s", text); 1678 } 1679 1680 void Com_Printf (char *fmt, ...) 1681 { 1682 va_list argptr; 1683 char text[1024]; 1684 1685 va_start (argptr, fmt); 1686 vsprintf (text, fmt, argptr); 1687 va_end (argptr); 1688 1689 ri.Con_Printf (PRINT_ALL, "%s", text); 1690 } 1691 1692 #endif