r_light.c
Go to the documentation of this file.00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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) {
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++)
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
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 }