|
|
1.1 ! root 1: // r_light.c ! 2: ! 3: #include "quakedef.h" ! 4: ! 5: int r_dlightframecount; ! 6: ! 7: ! 8: /* ! 9: ================== ! 10: R_AnimateLight ! 11: ================== ! 12: */ ! 13: void R_AnimateLight (void) ! 14: { ! 15: int i,j,k; ! 16: ! 17: // ! 18: // light animations ! 19: // 'm' is normal light, 'a' is no light, 'z' is double bright ! 20: i = (int)(cl.time*10); ! 21: for (j=0 ; j<MAX_LIGHTSTYLES ; j++) ! 22: { ! 23: if (!cl_lightstyle[j].length) ! 24: { ! 25: d_lightstylevalue[j] = 256; ! 26: continue; ! 27: } ! 28: k = i % cl_lightstyle[j].length; ! 29: k = cl_lightstyle[j].map[k] - 'a'; ! 30: k = k*22; ! 31: d_lightstylevalue[j] = k; ! 32: } ! 33: } ! 34: ! 35: /* ! 36: ============================================================================= ! 37: ! 38: DYNAMIC LIGHTS BLEND RENDERING ! 39: ! 40: ============================================================================= ! 41: */ ! 42: ! 43: void AddLightBlend (float r, float g, float b, float a2) ! 44: { ! 45: float a; ! 46: ! 47: v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]); ! 48: ! 49: a2 = a2/a; ! 50: ! 51: v_blend[0] = v_blend[1]*(1-a2) + r*a2; ! 52: v_blend[1] = v_blend[1]*(1-a2) + g*a2; ! 53: v_blend[2] = v_blend[2]*(1-a2) + b*a2; ! 54: } ! 55: ! 56: void R_RenderDlight (dlight_t *light) ! 57: { ! 58: int i, j; ! 59: float a; ! 60: vec3_t v; ! 61: float rad; ! 62: ! 63: rad = light->radius * 0.35; ! 64: ! 65: VectorSubtract (light->origin, r_origin, v); ! 66: if (Length (v) < rad) ! 67: { // view is inside the dlight ! 68: AddLightBlend (1, 0.5, 0, light->radius * 0.0003); ! 69: return; ! 70: } ! 71: ! 72: glBegin (GL_TRIANGLE_FAN); ! 73: glColor3f (0.2,0.1,0.0); ! 74: for (i=0 ; i<3 ; i++) ! 75: v[i] = light->origin[i] - vpn[i]*rad; ! 76: glVertex3fv (v); ! 77: glColor3f (0,0,0); ! 78: for (i=16 ; i>=0 ; i--) ! 79: { ! 80: a = i/16.0 * M_PI*2; ! 81: for (j=0 ; j<3 ; j++) ! 82: v[j] = light->origin[j] + vright[j]*cos(a)*rad ! 83: + vup[j]*sin(a)*rad; ! 84: glVertex3fv (v); ! 85: } ! 86: glEnd (); ! 87: } ! 88: ! 89: /* ! 90: ============= ! 91: R_RenderDlights ! 92: ============= ! 93: */ ! 94: void R_RenderDlights (void) ! 95: { ! 96: int i; ! 97: dlight_t *l; ! 98: ! 99: if (!gl_flashblend.value) ! 100: return; ! 101: ! 102: r_dlightframecount = r_framecount + 1; // because the count hasn't ! 103: // advanced yet for this frame ! 104: glDepthMask (0); ! 105: glDisable (GL_TEXTURE_2D); ! 106: glShadeModel (GL_SMOOTH); ! 107: glEnable (GL_BLEND); ! 108: glBlendFunc (GL_ONE, GL_ONE); ! 109: ! 110: l = cl_dlights; ! 111: for (i=0 ; i<MAX_DLIGHTS ; i++, l++) ! 112: { ! 113: if (l->die < cl.time || !l->radius) ! 114: continue; ! 115: R_RenderDlight (l); ! 116: } ! 117: ! 118: glColor3f (1,1,1); ! 119: glDisable (GL_BLEND); ! 120: glEnable (GL_TEXTURE_2D); ! 121: glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ! 122: glDepthMask (1); ! 123: } ! 124: ! 125: ! 126: /* ! 127: ============================================================================= ! 128: ! 129: DYNAMIC LIGHTS ! 130: ! 131: ============================================================================= ! 132: */ ! 133: ! 134: /* ! 135: ============= ! 136: R_MarkLights ! 137: ============= ! 138: */ ! 139: void R_MarkLights (dlight_t *light, int bit, mnode_t *node) ! 140: { ! 141: mplane_t *splitplane; ! 142: float dist; ! 143: msurface_t *surf; ! 144: int i; ! 145: ! 146: if (node->contents < 0) ! 147: return; ! 148: ! 149: splitplane = node->plane; ! 150: dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; ! 151: ! 152: if (dist > light->radius) ! 153: { ! 154: R_MarkLights (light, bit, node->children[0]); ! 155: return; ! 156: } ! 157: if (dist < -light->radius) ! 158: { ! 159: R_MarkLights (light, bit, node->children[1]); ! 160: return; ! 161: } ! 162: ! 163: // mark the polygons ! 164: surf = cl.worldmodel->surfaces + node->firstsurface; ! 165: for (i=0 ; i<node->numsurfaces ; i++, surf++) ! 166: { ! 167: if (surf->dlightframe != r_dlightframecount) ! 168: { ! 169: surf->dlightbits = 0; ! 170: surf->dlightframe = r_dlightframecount; ! 171: } ! 172: surf->dlightbits |= bit; ! 173: } ! 174: ! 175: R_MarkLights (light, bit, node->children[0]); ! 176: R_MarkLights (light, bit, node->children[1]); ! 177: } ! 178: ! 179: ! 180: /* ! 181: ============= ! 182: R_PushDlights ! 183: ============= ! 184: */ ! 185: void R_PushDlights (void) ! 186: { ! 187: int i; ! 188: dlight_t *l; ! 189: ! 190: if (gl_flashblend.value) ! 191: return; ! 192: ! 193: r_dlightframecount = r_framecount + 1; // because the count hasn't ! 194: // advanced yet for this frame ! 195: l = cl_dlights; ! 196: ! 197: for (i=0 ; i<MAX_DLIGHTS ; i++, l++) ! 198: { ! 199: if (l->die < cl.time || !l->radius) ! 200: continue; ! 201: R_MarkLights ( l, 1<<i, cl.worldmodel->nodes ); ! 202: } ! 203: } ! 204: ! 205: ! 206: /* ! 207: ============================================================================= ! 208: ! 209: LIGHT SAMPLING ! 210: ! 211: ============================================================================= ! 212: */ ! 213: ! 214: mplane_t *lightplane; ! 215: vec3_t lightspot; ! 216: ! 217: int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) ! 218: { ! 219: int r; ! 220: float front, back, frac; ! 221: int side; ! 222: mplane_t *plane; ! 223: vec3_t mid; ! 224: msurface_t *surf; ! 225: int s, t, ds, dt; ! 226: int i; ! 227: mtexinfo_t *tex; ! 228: byte *lightmap; ! 229: unsigned scale; ! 230: int maps; ! 231: ! 232: if (node->contents < 0) ! 233: return -1; // didn't hit anything ! 234: ! 235: // calculate mid point ! 236: ! 237: // FIXME: optimize for axial ! 238: plane = node->plane; ! 239: front = DotProduct (start, plane->normal) - plane->dist; ! 240: back = DotProduct (end, plane->normal) - plane->dist; ! 241: side = front < 0; ! 242: ! 243: if ( (back < 0) == side) ! 244: return RecursiveLightPoint (node->children[side], start, end); ! 245: ! 246: frac = front / (front-back); ! 247: mid[0] = start[0] + (end[0] - start[0])*frac; ! 248: mid[1] = start[1] + (end[1] - start[1])*frac; ! 249: mid[2] = start[2] + (end[2] - start[2])*frac; ! 250: ! 251: // go down front side ! 252: r = RecursiveLightPoint (node->children[side], start, mid); ! 253: if (r >= 0) ! 254: return r; // hit something ! 255: ! 256: if ( (back < 0) == side ) ! 257: return -1; // didn't hit anuthing ! 258: ! 259: // check for impact on this node ! 260: VectorCopy (mid, lightspot); ! 261: lightplane = plane; ! 262: ! 263: surf = cl.worldmodel->surfaces + node->firstsurface; ! 264: for (i=0 ; i<node->numsurfaces ; i++, surf++) ! 265: { ! 266: if (surf->flags & SURF_DRAWTILED) ! 267: continue; // no lightmaps ! 268: ! 269: tex = surf->texinfo; ! 270: ! 271: s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; ! 272: t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; ! 273: ! 274: if (s < surf->texturemins[0] || ! 275: t < surf->texturemins[1]) ! 276: continue; ! 277: ! 278: ds = s - surf->texturemins[0]; ! 279: dt = t - surf->texturemins[1]; ! 280: ! 281: if ( ds > surf->extents[0] || dt > surf->extents[1] ) ! 282: continue; ! 283: ! 284: if (!surf->samples) ! 285: return 0; ! 286: ! 287: ds >>= 4; ! 288: dt >>= 4; ! 289: ! 290: lightmap = surf->samples; ! 291: r = 0; ! 292: if (lightmap) ! 293: { ! 294: ! 295: lightmap += dt * ((surf->extents[0]>>4)+1) + ds; ! 296: ! 297: for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; ! 298: maps++) ! 299: { ! 300: scale = d_lightstylevalue[surf->styles[maps]]; ! 301: r += *lightmap * scale; ! 302: lightmap += ((surf->extents[0]>>4)+1) * ! 303: ((surf->extents[1]>>4)+1); ! 304: } ! 305: ! 306: r >>= 8; ! 307: } ! 308: ! 309: return r; ! 310: } ! 311: ! 312: // go down back side ! 313: return RecursiveLightPoint (node->children[!side], mid, end); ! 314: } ! 315: ! 316: int R_LightPoint (vec3_t p) ! 317: { ! 318: vec3_t end; ! 319: int r; ! 320: ! 321: if (!cl.worldmodel->lightdata) ! 322: return 255; ! 323: ! 324: end[0] = p[0]; ! 325: end[1] = p[1]; ! 326: end[2] = p[2] - 2048; ! 327: ! 328: r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); ! 329: ! 330: if (r == -1) ! 331: r = 0; ! 332: ! 333: return r; ! 334: } ! 335:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.