|
|
1.1.1.2 ! root 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: */ 1.1 root 20: // r_light.c 21: 22: #include "gl_local.h" 23: 24: int r_dlightframecount; 25: 26: #define DLIGHT_CUTOFF 64 27: 28: /* 29: ============================================================================= 30: 31: DYNAMIC LIGHTS BLEND RENDERING 32: 33: ============================================================================= 34: */ 35: 36: void R_RenderDlight (dlight_t *light) 37: { 38: int i, j; 39: float a; 40: vec3_t v; 41: float rad; 42: 43: rad = light->intensity * 0.35; 44: 45: VectorSubtract (light->origin, r_origin, v); 46: #if 0 47: // FIXME? 48: if (VectorLength (v) < rad) 49: { // view is inside the dlight 50: V_AddBlend (light->color[0], light->color[1], light->color[2], light->intensity * 0.0003, v_blend); 51: return; 52: } 53: #endif 54: 55: qglBegin (GL_TRIANGLE_FAN); 56: qglColor3f (light->color[0]*0.2, light->color[1]*0.2, light->color[2]*0.2); 57: for (i=0 ; i<3 ; i++) 58: v[i] = light->origin[i] - vpn[i]*rad; 59: qglVertex3fv (v); 60: qglColor3f (0,0,0); 61: for (i=16 ; i>=0 ; i--) 62: { 63: a = i/16.0 * M_PI*2; 64: for (j=0 ; j<3 ; j++) 65: v[j] = light->origin[j] + vright[j]*cos(a)*rad 66: + vup[j]*sin(a)*rad; 67: qglVertex3fv (v); 68: } 69: qglEnd (); 70: } 71: 72: /* 73: ============= 74: R_RenderDlights 75: ============= 76: */ 77: void R_RenderDlights (void) 78: { 79: int i; 80: dlight_t *l; 81: 82: if (!gl_flashblend->value) 83: return; 84: 85: r_dlightframecount = r_framecount + 1; // because the count hasn't 86: // advanced yet for this frame 87: qglDepthMask (0); 88: qglDisable (GL_TEXTURE_2D); 89: qglShadeModel (GL_SMOOTH); 90: qglEnable (GL_BLEND); 91: qglBlendFunc (GL_ONE, GL_ONE); 92: 93: l = r_newrefdef.dlights; 94: for (i=0 ; i<r_newrefdef.num_dlights ; i++, l++) 95: R_RenderDlight (l); 96: 97: qglColor3f (1,1,1); 98: qglDisable (GL_BLEND); 99: qglEnable (GL_TEXTURE_2D); 100: qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 101: qglDepthMask (1); 102: } 103: 104: 105: /* 106: ============================================================================= 107: 108: DYNAMIC LIGHTS 109: 110: ============================================================================= 111: */ 112: 113: /* 114: ============= 115: R_MarkLights 116: ============= 117: */ 118: void R_MarkLights (dlight_t *light, int bit, mnode_t *node) 119: { 120: cplane_t *splitplane; 121: float dist; 122: msurface_t *surf; 123: int i; 124: 125: if (node->contents != -1) 126: return; 127: 128: splitplane = node->plane; 129: dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; 130: 131: if (dist > light->intensity-DLIGHT_CUTOFF) 132: { 133: R_MarkLights (light, bit, node->children[0]); 134: return; 135: } 136: if (dist < -light->intensity+DLIGHT_CUTOFF) 137: { 138: R_MarkLights (light, bit, node->children[1]); 139: return; 140: } 141: 142: // mark the polygons 143: surf = r_worldmodel->surfaces + node->firstsurface; 144: for (i=0 ; i<node->numsurfaces ; i++, surf++) 145: { 146: if (surf->dlightframe != r_dlightframecount) 147: { 148: surf->dlightbits = 0; 149: surf->dlightframe = r_dlightframecount; 150: } 151: surf->dlightbits |= bit; 152: } 153: 154: R_MarkLights (light, bit, node->children[0]); 155: R_MarkLights (light, bit, node->children[1]); 156: } 157: 158: 159: /* 160: ============= 161: R_PushDlights 162: ============= 163: */ 164: void R_PushDlights (void) 165: { 166: int i; 167: dlight_t *l; 168: 169: if (gl_flashblend->value) 170: return; 171: 172: r_dlightframecount = r_framecount + 1; // because the count hasn't 173: // advanced yet for this frame 174: l = r_newrefdef.dlights; 175: for (i=0 ; i<r_newrefdef.num_dlights ; i++, l++) 176: R_MarkLights ( l, 1<<i, r_worldmodel->nodes ); 177: } 178: 179: 180: /* 181: ============================================================================= 182: 183: LIGHT SAMPLING 184: 185: ============================================================================= 186: */ 187: 188: vec3_t pointcolor; 189: cplane_t *lightplane; // used as shadow plane 190: vec3_t lightspot; 191: 192: int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) 193: { 194: float front, back, frac; 195: int side; 196: cplane_t *plane; 197: vec3_t mid; 198: msurface_t *surf; 199: int s, t, ds, dt; 200: int i; 201: mtexinfo_t *tex; 202: byte *lightmap; 203: int maps; 204: int r; 205: 206: if (node->contents != -1) 207: return -1; // didn't hit anything 208: 209: // calculate mid point 210: 211: // FIXME: optimize for axial 212: plane = node->plane; 213: front = DotProduct (start, plane->normal) - plane->dist; 214: back = DotProduct (end, plane->normal) - plane->dist; 215: side = front < 0; 216: 217: if ( (back < 0) == side) 218: return RecursiveLightPoint (node->children[side], start, end); 219: 220: frac = front / (front-back); 221: mid[0] = start[0] + (end[0] - start[0])*frac; 222: mid[1] = start[1] + (end[1] - start[1])*frac; 223: mid[2] = start[2] + (end[2] - start[2])*frac; 224: 225: // go down front side 226: r = RecursiveLightPoint (node->children[side], start, mid); 227: if (r >= 0) 228: return r; // hit something 229: 230: if ( (back < 0) == side ) 231: return -1; // didn't hit anuthing 232: 233: // check for impact on this node 234: VectorCopy (mid, lightspot); 235: lightplane = plane; 236: 237: surf = r_worldmodel->surfaces + node->firstsurface; 238: for (i=0 ; i<node->numsurfaces ; i++, surf++) 239: { 240: if (surf->flags&(SURF_DRAWTURB|SURF_DRAWSKY)) 241: continue; // no lightmaps 242: 243: tex = surf->texinfo; 244: 245: s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; 246: t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; 247: 248: if (s < surf->texturemins[0] || 249: t < surf->texturemins[1]) 250: continue; 251: 252: ds = s - surf->texturemins[0]; 253: dt = t - surf->texturemins[1]; 254: 255: if ( ds > surf->extents[0] || dt > surf->extents[1] ) 256: continue; 257: 258: if (!surf->samples) 259: return 0; 260: 261: ds >>= 4; 262: dt >>= 4; 263: 264: lightmap = surf->samples; 265: VectorCopy (vec3_origin, pointcolor); 266: if (lightmap) 267: { 268: vec3_t scale; 269: 270: lightmap += 3*(dt * ((surf->extents[0]>>4)+1) + ds); 271: 272: for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 273: maps++) 274: { 275: for (i=0 ; i<3 ; i++) 276: scale[i] = gl_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[i]; 277: 278: pointcolor[0] += lightmap[0] * scale[0] * (1.0/255); 279: pointcolor[1] += lightmap[1] * scale[1] * (1.0/255); 280: pointcolor[2] += lightmap[2] * scale[2] * (1.0/255); 281: lightmap += 3*((surf->extents[0]>>4)+1) * 282: ((surf->extents[1]>>4)+1); 283: } 284: } 285: 286: return 1; 287: } 288: 289: // go down back side 290: return RecursiveLightPoint (node->children[!side], mid, end); 291: } 292: 293: /* 294: =============== 295: R_LightPoint 296: =============== 297: */ 298: void R_LightPoint (vec3_t p, vec3_t color) 299: { 300: vec3_t end; 301: float r; 302: int lnum; 303: dlight_t *dl; 304: float light; 305: vec3_t dist; 306: float add; 307: 308: if (!r_worldmodel->lightdata) 309: { 310: color[0] = color[1] = color[2] = 1.0; 311: return; 312: } 313: 314: end[0] = p[0]; 315: end[1] = p[1]; 316: end[2] = p[2] - 2048; 317: 318: r = RecursiveLightPoint (r_worldmodel->nodes, p, end); 319: 320: if (r == -1) 321: { 322: VectorCopy (vec3_origin, color); 323: } 324: else 325: { 326: VectorCopy (pointcolor, color); 327: } 328: 329: // 330: // add dynamic lights 331: // 332: light = 0; 333: dl = r_newrefdef.dlights; 334: for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++, dl++) 335: { 336: VectorSubtract (currententity->origin, 337: dl->origin, 338: dist); 339: add = dl->intensity - VectorLength(dist); 340: add *= (1.0/256); 341: if (add > 0) 342: { 343: VectorMA (color, add, dl->color, color); 344: } 345: } 346: 347: VectorScale (color, gl_modulate->value, color); 348: } 349: 350: 351: //=================================================================== 352: 353: static float s_blocklights[34*34*3]; 354: /* 355: =============== 356: R_AddDynamicLights 357: =============== 358: */ 359: void R_AddDynamicLights (msurface_t *surf) 360: { 361: int lnum; 362: int sd, td; 363: float fdist, frad, fminlight; 364: vec3_t impact, local; 365: int s, t; 366: int i; 367: int smax, tmax; 368: mtexinfo_t *tex; 369: dlight_t *dl; 370: float *pfBL; 371: float fsacc, ftacc; 372: 373: smax = (surf->extents[0]>>4)+1; 374: tmax = (surf->extents[1]>>4)+1; 375: tex = surf->texinfo; 376: 377: for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++) 378: { 379: if ( !(surf->dlightbits & (1<<lnum) ) ) 380: continue; // not lit by this light 381: 382: dl = &r_newrefdef.dlights[lnum]; 383: frad = dl->intensity; 384: fdist = DotProduct (dl->origin, surf->plane->normal) - 385: surf->plane->dist; 386: frad -= fabs(fdist); 387: // rad is now the highest intensity on the plane 388: 389: fminlight = DLIGHT_CUTOFF; // FIXME: make configurable? 390: if (frad < fminlight) 391: continue; 392: fminlight = frad - fminlight; 393: 394: for (i=0 ; i<3 ; i++) 395: { 396: impact[i] = dl->origin[i] - 397: surf->plane->normal[i]*fdist; 398: } 399: 400: local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3] - surf->texturemins[0]; 401: local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3] - surf->texturemins[1]; 402: 403: pfBL = s_blocklights; 404: for (t = 0, ftacc = 0 ; t<tmax ; t++, ftacc += 16) 405: { 406: td = local[1] - ftacc; 407: if ( td < 0 ) 408: td = -td; 409: 410: for ( s=0, fsacc = 0 ; s<smax ; s++, fsacc += 16, pfBL += 3) 411: { 412: sd = Q_ftol( local[0] - fsacc ); 413: 414: if ( sd < 0 ) 415: sd = -sd; 416: 417: if (sd > td) 418: fdist = sd + (td>>1); 419: else 420: fdist = td + (sd>>1); 421: 422: if ( fdist < fminlight ) 423: { 424: pfBL[0] += ( frad - fdist ) * dl->color[0]; 425: pfBL[1] += ( frad - fdist ) * dl->color[1]; 426: pfBL[2] += ( frad - fdist ) * dl->color[2]; 427: } 428: } 429: } 430: } 431: } 432: 433: 434: /* 435: ** R_SetCacheState 436: */ 437: void R_SetCacheState( msurface_t *surf ) 438: { 439: int maps; 440: 441: for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 442: maps++) 443: { 444: surf->cached_light[maps] = r_newrefdef.lightstyles[surf->styles[maps]].white; 445: } 446: } 447: 448: /* 449: =============== 450: R_BuildLightMap 451: 452: Combine and scale multiple lightmaps into the floating format in blocklights 453: =============== 454: */ 455: void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) 456: { 457: int smax, tmax; 458: int r, g, b, a, max; 459: int i, j, size; 460: byte *lightmap; 461: float scale[4]; 462: int nummaps; 463: float *bl; 464: lightstyle_t *style; 465: int monolightmap; 466: 467: if ( surf->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) ) 468: ri.Sys_Error (ERR_DROP, "R_BuildLightMap called for non-lit surface"); 469: 470: smax = (surf->extents[0]>>4)+1; 471: tmax = (surf->extents[1]>>4)+1; 472: size = smax*tmax; 473: if (size > (sizeof(s_blocklights)>>4) ) 474: ri.Sys_Error (ERR_DROP, "Bad s_blocklights size"); 475: 476: // set to full bright if no light data 477: if (!surf->samples) 478: { 479: int maps; 480: 481: for (i=0 ; i<size*3 ; i++) 482: s_blocklights[i] = 255; 483: for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 484: maps++) 485: { 486: style = &r_newrefdef.lightstyles[surf->styles[maps]]; 487: } 488: goto store; 489: } 490: 491: // count the # of maps 492: for ( nummaps = 0 ; nummaps < MAXLIGHTMAPS && surf->styles[nummaps] != 255 ; 493: nummaps++) 494: ; 495: 496: lightmap = surf->samples; 497: 498: // add all the lightmaps 499: if ( nummaps == 1 ) 500: { 501: int maps; 502: 503: for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 504: maps++) 505: { 506: bl = s_blocklights; 507: 508: for (i=0 ; i<3 ; i++) 509: scale[i] = gl_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[i]; 510: 511: if ( scale[0] == 1.0F && 512: scale[1] == 1.0F && 513: scale[2] == 1.0F ) 514: { 515: for (i=0 ; i<size ; i++, bl+=3) 516: { 517: bl[0] = lightmap[i*3+0]; 518: bl[1] = lightmap[i*3+1]; 519: bl[2] = lightmap[i*3+2]; 520: } 521: } 522: else 523: { 524: for (i=0 ; i<size ; i++, bl+=3) 525: { 526: bl[0] = lightmap[i*3+0] * scale[0]; 527: bl[1] = lightmap[i*3+1] * scale[1]; 528: bl[2] = lightmap[i*3+2] * scale[2]; 529: } 530: } 531: lightmap += size*3; // skip to next lightmap 532: } 533: } 534: else 535: { 536: int maps; 537: 538: memset( s_blocklights, 0, sizeof( s_blocklights[0] ) * size * 3 ); 539: 540: for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 541: maps++) 542: { 543: bl = s_blocklights; 544: 545: for (i=0 ; i<3 ; i++) 546: scale[i] = gl_modulate->value*r_newrefdef.lightstyles[surf->styles[maps]].rgb[i]; 547: 548: if ( scale[0] == 1.0F && 549: scale[1] == 1.0F && 550: scale[2] == 1.0F ) 551: { 552: for (i=0 ; i<size ; i++, bl+=3 ) 553: { 554: bl[0] += lightmap[i*3+0]; 555: bl[1] += lightmap[i*3+1]; 556: bl[2] += lightmap[i*3+2]; 557: } 558: } 559: else 560: { 561: for (i=0 ; i<size ; i++, bl+=3) 562: { 563: bl[0] += lightmap[i*3+0] * scale[0]; 564: bl[1] += lightmap[i*3+1] * scale[1]; 565: bl[2] += lightmap[i*3+2] * scale[2]; 566: } 567: } 568: lightmap += size*3; // skip to next lightmap 569: } 570: } 571: 572: // add all the dynamic lights 573: if (surf->dlightframe == r_framecount) 574: R_AddDynamicLights (surf); 575: 576: // put into texture format 577: store: 578: stride -= (smax<<2); 579: bl = s_blocklights; 580: 581: monolightmap = gl_monolightmap->string[0]; 582: 583: if ( monolightmap == '0' ) 584: { 585: for (i=0 ; i<tmax ; i++, dest += stride) 586: { 587: for (j=0 ; j<smax ; j++) 588: { 589: 590: r = Q_ftol( bl[0] ); 591: g = Q_ftol( bl[1] ); 592: b = Q_ftol( bl[2] ); 593: 594: // catch negative lights 595: if (r < 0) 596: r = 0; 597: if (g < 0) 598: g = 0; 599: if (b < 0) 600: b = 0; 601: 602: /* 603: ** determine the brightest of the three color components 604: */ 605: if (r > g) 606: max = r; 607: else 608: max = g; 609: if (b > max) 610: max = b; 611: 612: /* 613: ** alpha is ONLY used for the mono lightmap case. For this reason 614: ** we set it to the brightest of the color components so that 615: ** things don't get too dim. 616: */ 617: a = max; 618: 619: /* 620: ** rescale all the color components if the intensity of the greatest 621: ** channel exceeds 1.0 622: */ 623: if (max > 255) 624: { 625: float t = 255.0F / max; 626: 627: r = r*t; 628: g = g*t; 629: b = b*t; 630: a = a*t; 631: } 632: 633: dest[0] = r; 634: dest[1] = g; 635: dest[2] = b; 636: dest[3] = a; 637: 638: bl += 3; 639: dest += 4; 640: } 641: } 642: } 643: else 644: { 645: for (i=0 ; i<tmax ; i++, dest += stride) 646: { 647: for (j=0 ; j<smax ; j++) 648: { 649: 650: r = Q_ftol( bl[0] ); 651: g = Q_ftol( bl[1] ); 652: b = Q_ftol( bl[2] ); 653: 654: // catch negative lights 655: if (r < 0) 656: r = 0; 657: if (g < 0) 658: g = 0; 659: if (b < 0) 660: b = 0; 661: 662: /* 663: ** determine the brightest of the three color components 664: */ 665: if (r > g) 666: max = r; 667: else 668: max = g; 669: if (b > max) 670: max = b; 671: 672: /* 673: ** alpha is ONLY used for the mono lightmap case. For this reason 674: ** we set it to the brightest of the color components so that 675: ** things don't get too dim. 676: */ 677: a = max; 678: 679: /* 680: ** rescale all the color components if the intensity of the greatest 681: ** channel exceeds 1.0 682: */ 683: if (max > 255) 684: { 685: float t = 255.0F / max; 686: 687: r = r*t; 688: g = g*t; 689: b = b*t; 690: a = a*t; 691: } 692: 693: /* 694: ** So if we are doing alpha lightmaps we need to set the R, G, and B 695: ** components to 0 and we need to set alpha to 1-alpha. 696: */ 697: switch ( monolightmap ) 698: { 699: case 'L': 700: case 'I': 701: r = a; 702: g = b = 0; 703: break; 704: case 'C': 705: // try faking colored lighting 706: a = 255 - ((r+g+b)/3); 707: r *= a/255.0; 708: g *= a/255.0; 709: b *= a/255.0; 710: break; 711: case 'A': 712: default: 713: r = g = b = 0; 714: a = 255 - a; 715: break; 716: } 717: 718: dest[0] = r; 719: dest[1] = g; 720: dest[2] = b; 721: dest[3] = a; 722: 723: bl += 3; 724: dest += 4; 725: } 726: } 727: } 728: } 729:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.