r_light.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 1997-2001 Id Software, Inc.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "r_local.h"
00026 #include "r_light.h"
00027 #include "r_entity.h"
00028 #include "r_state.h"
00029 
00030 #define LIGHT_RADIUS_FACTOR 80.0
00031 
00032 
00034 static light_t r_lightsArray[MAX_GL_LIGHTS];
00035 static sustain_t r_sustainArray[MAX_GL_LIGHTS];
00036 
00037 void R_AddLight (const vec3_t origin, float radius, const vec3_t color)
00038 {
00039     int i;
00040 
00041     if (!r_lights->integer)
00042         return;
00043 
00044     if (refdef.numLights == MAX_GL_LIGHTS)
00045         return;
00046 
00047     i = refdef.numLights++;
00048 
00049     VectorCopy(origin, r_lightsArray[i].origin);
00050     r_lightsArray[i].radius = radius;
00051     VectorCopy(color, r_lightsArray[i].color);
00052 }
00053 
00057 void R_AddSustainedLight (const vec3_t org, float radius, const vec3_t color, float sustain)
00058 {
00059     sustain_t *s;
00060     int i;
00061 
00062     if (!r_lights->integer)
00063         return;
00064 
00065     s = r_sustainArray;
00066 
00067     for (i = 0; i < MAX_GL_LIGHTS; i++, s++)
00068         if (!s->sustain)
00069             break;
00070 
00071     if (i == MAX_GL_LIGHTS)
00072         return;
00073 
00074     VectorCopy(org, s->light.origin);
00075     s->light.radius = radius;
00076     VectorCopy(color, s->light.color);
00077 
00078     s->time = refdef.time;
00079     s->sustain = refdef.time + sustain;
00080 }
00081 
00086 static void R_AddSustainedLights (void)
00087 {
00088     sustain_t *s;
00089     int i;
00090 
00091     /* sustains must be recalculated every frame */
00092     for (i = 0, s = r_sustainArray; i < MAX_GL_LIGHTS; i++, s++) {
00093         float intensity;
00094         vec3_t color;
00095 
00096         if (s->sustain <= refdef.time) {  /* clear it */
00097             s->sustain = 0;
00098             continue;
00099         }
00100 
00101         intensity = (s->sustain - refdef.time) / (s->sustain - s->time);
00102         VectorScale(s->light.color, intensity, color);
00103 
00104         R_AddLight(s->light.origin, s->light.radius, color);
00105     }
00106 }
00107 
00108 static vec3_t lights_offset;
00109 
00113 void R_ShiftLights (const vec3_t offset)
00114 {
00115     VectorCopy(offset, lights_offset);
00116 }
00117 
00118 void R_EnableLights (void)
00119 {
00120     light_t *l;
00121     vec4_t position;
00122     vec4_t diffuse;
00123     int i;
00124 
00125     R_AddSustainedLights();
00126 
00127     position[3] = diffuse[3] = 1.0;
00128 
00129     for (i = 0, l = r_lightsArray; i < refdef.numLights; i++, l++) {
00130         VectorSubtract(l->origin, lights_offset, position);
00131         glLightfv(GL_LIGHT0 + i, GL_POSITION, position);
00132         VectorCopy(l->color, diffuse);
00133         glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, diffuse);
00134         glLightf(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, l->radius * LIGHT_RADIUS_FACTOR);
00135     }
00136 
00137     for (; i < MAX_GL_LIGHTS; i++)  /* disable the rest */
00138         glLightf(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, 0.0);
00139 }
00140 
00141 void R_AddLightsource (const r_light_t *source)
00142 {
00143     if (r_state.numActiveLights >= MAX_DYNAMIC_LIGHTS) {
00144         Com_Printf("Failed to add lightsource: MAX_DYNAMIC_LIGHTS exceeded\n");
00145         return;
00146     }
00147 
00148     Com_Printf("added light, ambient=%f\n", source->ambientColor[0]);
00149 
00150     r_state.dynamicLights[r_state.numActiveLights++] = *source;
00151 }
00152 
00153 void R_ClearActiveLights (void)
00154 {
00155     int i;
00156 
00157     r_state.numActiveLights = 0;
00158     glDisable(GL_LIGHTING);
00159     for (i = 0; i < r_dynamic_lights->integer; i++) {
00160         glLightf(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, 0.0);
00161         glDisable(GL_LIGHT0 + i);
00162     }
00163 }
00164 
00209 /* global variable - NOT THREAD SAFE */
00210 static vec3_t origin;
00211 
00212 static inline int R_LightDistCompare (const void *a, const void *b)
00213 {
00214     const r_light_t *light1 = *(const r_light_t * const *)a;
00215     const r_light_t *light2 = *(const r_light_t * const *)b;
00216     return
00217         light1->loc[3] == 0 ? -1 :
00218         light2->loc[3] == 0 ?  1 :
00219         VectorDistSqr(light1->loc, origin) - VectorDistSqr(light2->loc, origin);
00220 }
00221 
00222 static inline void R_SortLightList_qsort (r_light_t **list)
00223 {
00224     qsort(list, r_state.numActiveLights, sizeof(*list), &R_LightDistCompare);
00225 }
00226 
00233 static void R_SortLightList (r_light_t **list, vec3_t v)
00234 {
00235     VectorCopy(v, origin);
00236     R_SortLightList_qsort(list);
00237 }
00238 
00239 void R_UpdateLightList (entity_t *ent)
00240 {
00241     if (ent->numLights > r_state.numActiveLights)
00242         ent->numLights = 0;
00243 
00244     while (ent->numLights < r_state.numActiveLights) {
00245         ent->lights[ent->numLights] = &r_state.dynamicLights[ent->numLights];
00246         ent->numLights++;
00247     }
00248 
00249     R_SortLightList(ent->lights, ent->origin);
00250 }

Generated by  doxygen 1.6.2