1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19*/ 20// r_light.c 21 22#include "quakedef.h" 23 24int r_dlightframecount; 25 26 27/* 28================== 29R_AnimateLight 30================== 31*/ 32void R_AnimateLight (void) 33{ 34 int i,j,k; 35 36// 37// light animations 38// 'm' is normal light, 'a' is no light, 'z' is double bright 39 i = (int)(cl.time*10); 40 for (j=0 ; j<MAX_LIGHTSTYLES ; j++) 41 { 42 if (!cl_lightstyle[j].length) 43 { 44 d_lightstylevalue[j] = 256; 45 continue; 46 } 47 k = i % cl_lightstyle[j].length; 48 k = cl_lightstyle[j].map[k] - 'a'; 49 k = k*22; 50 d_lightstylevalue[j] = k; 51 } 52} 53 54/* 55============================================================================= 56 57DYNAMIC LIGHTS BLEND RENDERING 58 59============================================================================= 60*/ 61 62void AddLightBlend (float r, float g, float b, float a2) 63{ 64 float a; 65 66 v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]); 67 68 a2 = a2/a; 69 70 v_blend[0] = v_blend[1]*(1-a2) + r*a2; 71 v_blend[1] = v_blend[1]*(1-a2) + g*a2; 72 v_blend[2] = v_blend[2]*(1-a2) + b*a2; 73} 74 75void R_RenderDlight (dlight_t *light) 76{ 77 int i, j; 78 float a; 79 vec3_t v; 80 float rad; 81 82 rad = light->radius * 0.35; 83 84 VectorSubtract (light->origin, r_origin, v); 85 if (Length (v) < rad) 86 { // view is inside the dlight 87 AddLightBlend (1, 0.5, 0, light->radius * 0.0003); 88 return; 89 } 90 91#ifdef USE_OPENGLES 92 glEnableClientState(GL_COLOR_ARRAY); 93 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 94 glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer); 95 glColorPointer(4, GL_FLOAT, 0, gColorBuffer); 96 97 { 98 float* pPos = gVertexBuffer; 99 float* pColor = gColorBuffer; 100 *pColor++ = 0.2f; 101 *pColor++ = 0.1f; 102 *pColor++ = 0.0f; 103 *pColor++ = 1.0f; 104 for (i=0 ; i<3 ; i++) 105 *pPos++ = light->origin[i] - vpn[i]*rad; 106 for (i=16 ; i>=0 ; i--) 107 { 108 *pColor++ = 0.0f; 109 *pColor++ = 0.0f; 110 *pColor++ = 0.0f; 111 *pColor++ = 0.0f; 112 a = i/16.0 * M_PI*2; 113 for (j=0 ; j<3 ; j++) 114 *pPos++ = light->origin[j] + vright[j]*cos(a)*rad 115 + vup[j]*sin(a)*rad; 116 } 117 } 118 glDrawArrays(GL_TRIANGLE_FAN, 0, 18); 119 glDisableClientState(GL_COLOR_ARRAY); 120 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 121 glColor3f(0,0,0); // Ensure the color ends up being zero just like the non-OpenGLES code 122 123#else 124 glBegin (GL_TRIANGLE_FAN); 125 glColor3f (0.2,0.1,0.0); 126 for (i=0 ; i<3 ; i++) 127 v[i] = light->origin[i] - vpn[i]*rad; 128 glVertex3fv (v); 129 glColor3f (0,0,0); 130 for (i=16 ; i>=0 ; i--) 131 { 132 a = i/16.0 * M_PI*2; 133 for (j=0 ; j<3 ; j++) 134 v[j] = light->origin[j] + vright[j]*cos(a)*rad 135 + vup[j]*sin(a)*rad; 136 glVertex3fv (v); 137 } 138 glEnd (); 139#endif 140} 141 142/* 143============= 144R_RenderDlights 145============= 146*/ 147void R_RenderDlights (void) 148{ 149 int i; 150 dlight_t *l; 151 152 if (!gl_flashblend.value) 153 return; 154 155 r_dlightframecount = r_framecount + 1; // because the count hasn't 156 // advanced yet for this frame 157 glDepthMask (0); 158 glDisable (GL_TEXTURE_2D); 159 glShadeModel (GL_SMOOTH); 160 glEnable (GL_BLEND); 161 glBlendFunc (GL_ONE, GL_ONE); 162 163 l = cl_dlights; 164 for (i=0 ; i<MAX_DLIGHTS ; i++, l++) 165 { 166 if (l->die < cl.time || !l->radius) 167 continue; 168 R_RenderDlight (l); 169 } 170 171 glColor3f (1,1,1); 172 glDisable (GL_BLEND); 173 glEnable (GL_TEXTURE_2D); 174 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 175 glDepthMask (1); 176} 177 178 179/* 180============================================================================= 181 182DYNAMIC LIGHTS 183 184============================================================================= 185*/ 186 187/* 188============= 189R_MarkLights 190============= 191*/ 192void R_MarkLights (dlight_t *light, int bit, mnode_t *node) 193{ 194 mplane_t *splitplane; 195 float dist; 196 msurface_t *surf; 197 int i; 198 199 if (node->contents < 0) 200 return; 201 202 splitplane = node->plane; 203 dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; 204 205 if (dist > light->radius) 206 { 207 R_MarkLights (light, bit, node->children[0]); 208 return; 209 } 210 if (dist < -light->radius) 211 { 212 R_MarkLights (light, bit, node->children[1]); 213 return; 214 } 215 216// mark the polygons 217 surf = cl.worldmodel->surfaces + node->firstsurface; 218 for (i=0 ; i<node->numsurfaces ; i++, surf++) 219 { 220 if (surf->dlightframe != r_dlightframecount) 221 { 222 surf->dlightbits = 0; 223 surf->dlightframe = r_dlightframecount; 224 } 225 surf->dlightbits |= bit; 226 } 227 228 R_MarkLights (light, bit, node->children[0]); 229 R_MarkLights (light, bit, node->children[1]); 230} 231 232 233/* 234============= 235R_PushDlights 236============= 237*/ 238void R_PushDlights (void) 239{ 240 int i; 241 dlight_t *l; 242 243 if (gl_flashblend.value) 244 return; 245 246 r_dlightframecount = r_framecount + 1; // because the count hasn't 247 // advanced yet for this frame 248 l = cl_dlights; 249 250 for (i=0 ; i<MAX_DLIGHTS ; i++, l++) 251 { 252 if (l->die < cl.time || !l->radius) 253 continue; 254 R_MarkLights ( l, 1<<i, cl.worldmodel->nodes ); 255 } 256} 257 258 259/* 260============================================================================= 261 262LIGHT SAMPLING 263 264============================================================================= 265*/ 266 267mplane_t *lightplane; 268vec3_t lightspot; 269 270int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) 271{ 272 int r; 273 float front, back, frac; 274 int side; 275 mplane_t *plane; 276 vec3_t mid; 277 msurface_t *surf; 278 int s, t, ds, dt; 279 int i; 280 mtexinfo_t *tex; 281 byte *lightmap; 282 unsigned scale; 283 int maps; 284 285 if (node->contents < 0) 286 return -1; // didn't hit anything 287 288// calculate mid point 289 290// FIXME: optimize for axial 291 plane = node->plane; 292 front = DotProduct (start, plane->normal) - plane->dist; 293 back = DotProduct (end, plane->normal) - plane->dist; 294 side = front < 0; 295 296 if ( (back < 0) == side) 297 return RecursiveLightPoint (node->children[side], start, end); 298 299 frac = front / (front-back); 300 mid[0] = start[0] + (end[0] - start[0])*frac; 301 mid[1] = start[1] + (end[1] - start[1])*frac; 302 mid[2] = start[2] + (end[2] - start[2])*frac; 303 304// go down front side 305 r = RecursiveLightPoint (node->children[side], start, mid); 306 if (r >= 0) 307 return r; // hit something 308 309 if ( (back < 0) == side ) 310 return -1; // didn't hit anuthing 311 312// check for impact on this node 313 VectorCopy (mid, lightspot); 314 lightplane = plane; 315 316 surf = cl.worldmodel->surfaces + node->firstsurface; 317 for (i=0 ; i<node->numsurfaces ; i++, surf++) 318 { 319 if (surf->flags & SURF_DRAWTILED) 320 continue; // no lightmaps 321 322 tex = surf->texinfo; 323 324 s = (int) (DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]); 325 t = (int) (DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3]); 326 327 if (s < surf->texturemins[0] || 328 t < surf->texturemins[1]) 329 continue; 330 331 ds = s - surf->texturemins[0]; 332 dt = t - surf->texturemins[1]; 333 334 if ( ds > surf->extents[0] || dt > surf->extents[1] ) 335 continue; 336 337 if (!surf->samples) 338 return 0; 339 340 ds >>= 4; 341 dt >>= 4; 342 343 lightmap = surf->samples; 344 r = 0; 345 if (lightmap) 346 { 347 348 lightmap += dt * ((surf->extents[0]>>4)+1) + ds; 349 350 for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 351 maps++) 352 { 353 scale = d_lightstylevalue[surf->styles[maps]]; 354 r += *lightmap * scale; 355 lightmap += ((surf->extents[0]>>4)+1) * 356 ((surf->extents[1]>>4)+1); 357 } 358 359 r >>= 8; 360 } 361 362 return r; 363 } 364 365// go down back side 366 return RecursiveLightPoint (node->children[!side], mid, end); 367} 368 369int R_LightPoint (vec3_t p) 370{ 371 vec3_t end; 372 int r; 373 374 if (!cl.worldmodel->lightdata) 375 return 255; 376 377 end[0] = p[0]; 378 end[1] = p[1]; 379 end[2] = p[2] - 2048; 380 381 r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); 382 383 if (r == -1) 384 r = 0; 385 386 return r; 387} 388