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