UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_light.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 1997-2001 Id Software, Inc.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "r_local.h"
26 #include "r_light.h"
27 #include "r_entity.h"
28 #include "r_state.h"
29 
31 
36 void R_AddLight (const vec3_t origin, float radius, const vec3_t color)
37 {
38  int i;
39 
41  return;
42 
44 
46  refdef.dynamicLights[i].radius = radius;
48 
49  Com_DPrintf(DEBUG_RENDERER, "added dynamic light, color (%f, %f, %f) position (%f, %f, %f) radius=%f\n",
50  color[0], color[1], color[2],
51  origin[0], origin[1], origin[2],
52  radius);
53 }
54 
58 void R_AddSustainedLight (const vec3_t org, float radius, const vec3_t color, float sustain)
59 {
61 
62  int i;
63  for (i = 0; i < MAX_GL_LIGHTS; i++, s++)
64  if (!s->sustain)
65  break;
66 
67  if (i == MAX_GL_LIGHTS)
68  return;
69 
70  VectorCopy(org, s->light.origin);
71  s->light.radius = radius;
72  VectorCopy(color, s->light.color);
73 
74  s->time = refdef.time;
75  s->sustain = refdef.time + sustain;
76 }
77 
84 {
85  sustain_t* s;
86  int i;
87 
88  /* sustains must be recalculated every frame */
89  for (i = 0, s = r_sustainArray; i < MAX_GL_LIGHTS; i++, s++) {
90  float intensity;
91  vec3_t color;
92 
93  if (s->sustain <= refdef.time) { /* clear it */
94  s->sustain = 0;
95  continue;
96  }
97 
98  intensity = (s->sustain - refdef.time) / (s->sustain - s->time);
99  VectorScale(s->light.color, intensity, color);
100 
101  R_AddLight(s->light.origin, s->light.radius, color);
102  }
103 }
104 
109 {
110  int i;
111  int maxLights = r_dynamic_lights->integer;
112  vec3_t lightPositions[MAX_GL_LIGHTS];
113  vec4_t lightParams[MAX_GL_LIGHTS];
114 
115  /* with the current blending model, lighting breaks FFP world render */
116  if (!r_programs->integer) {
117  return;
118  }
119 
121  return;
122 
123  for (i = 0; i < refdef.numDynamicLights && i < maxLights; i++) {
124  const light_t* light = &refdef.dynamicLights[i];
125 
126  GLPositionTransform(r_locals.world_matrix, light->origin, lightPositions[i]);
127  VectorCopy(light->color, lightParams[i]);
128  lightParams[i][3] = 16.0 / (light->radius * light->radius);
129  }
130 
131  /* if there aren't enough active lights, turn off the rest */
132  for (;i < maxLights ;i++)
133  Vector4Set(lightParams[i], 0, 0, 0, 1);
134 
135  /* Send light data to shaders */
136  R_ProgramParameter3fvs("LIGHTPOSITIONS", maxLights, (GLfloat*)lightPositions);
137  R_ProgramParameter4fvs("LIGHTPARAMS", maxLights, (GLfloat*)lightParams);
138 
139  R_EnableAttribute("TANGENTS");
140 }
141 
149 void R_EnableModelLights (const light_t** lights, int numLights, bool inShadow, bool enable)
150 {
151  int i;
152  int maxLights = r_dynamic_lights->integer;
153  vec4_t blackColor = {0.0, 0.0, 0.0, 1.0};
154  const vec4_t whiteColor = {1.0, 1.0, 1.0, 1.0};
155  const vec4_t defaultLight0Position = {0.0, 0.0, 1.0, 0.0};
156  vec3_t lightPositions[MAX_GL_LIGHTS];
157  vec4_t lightParams[MAX_GL_LIGHTS];
158 
159  if (r_programs->integer == 0) { /* Fixed function path renderer got only the sunlight */
160  /* Setup OpenGL light #0 to act as a sun and environment light */
161  glEnable(GL_LIGHTING);
162  glEnable(GL_LIGHT0);
163  glEnable(GL_COLOR_MATERIAL);
164 #ifndef GL_VERSION_ES_CM_1_0
165  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
166 #endif
167 
168  glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0);
169  glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0);
170  glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0);
171 
172  glLightfv(GL_LIGHT0, GL_SPECULAR, blackColor);
173  glLightfv(GL_LIGHT0, GL_AMBIENT, refdef.modelAmbientColor);
174 
175  glLightfv(GL_LIGHT0, GL_POSITION, refdef.sunVector);
176 
177  if (enable) {
178  if (inShadow) {
179  /* ambient only */
180  glLightfv(GL_LIGHT0, GL_DIFFUSE, blackColor);
181  } else {
182  /* Full sunlight */
183  glLightfv(GL_LIGHT0, GL_DIFFUSE, refdef.sunDiffuseColor);
184  }
185  } else {
186  /* restore the default OpenGL state */
187  glDisable(GL_LIGHTING);
188  glDisable(GL_COLOR_MATERIAL);
189 
190  glLightfv(GL_LIGHT0, GL_POSITION, defaultLight0Position);
191  glLightfv(GL_LIGHT0, GL_AMBIENT, blackColor);
192  glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteColor);
193  glLightfv(GL_LIGHT0, GL_SPECULAR, whiteColor);
194  }
195  return;
196  }
197 
198  assert(numLights <= MAX_GL_LIGHTS);
199 
200  if (!enable || !r_state.lighting_enabled) {
202  R_DisableAttribute("TANGENTS");
204  if (maxLights) {
205  for (i = 0; i < maxLights; i++)
206  Vector4Set(lightParams[i], 0, 0, 0, 1);
207 
208  /* Send light data to shaders */
209  R_ProgramParameter3fvs("LIGHTPOSITIONS", maxLights, (GLfloat*)lightPositions);
210  R_ProgramParameter4fvs("LIGHTPARAMS", maxLights, (GLfloat*)lightParams);
211  }
212  }
213 
215  return;
216  }
217 
219  if (numLights > maxLights)
220  numLights = maxLights;
221 
223 
224  R_EnableAttribute("TANGENTS");
225 
227 
229 
230  if (inShadow) {
231  R_ProgramParameter3fv("SUNCOLOR", blackColor);
232  } else {
234  }
235 
236  if (!maxLights)
237  return;
238 
239  for (i = 0; i < numLights; i++) {
240  const light_t* light = lights[i];
241 
242  GLPositionTransform(r_locals.world_matrix, light->origin, lightPositions[i]);
243  VectorCopy(light->color, lightParams[i]);
244  lightParams[i][3] = 16.0 / (light->radius * light->radius);
245  }
246 
247  /* if there aren't enough active lights, turn off the rest */
248  for (; i < maxLights; i++)
249  Vector4Set(lightParams[i], 0, 0, 0, 1);
250 
251  /* Send light data to shaders */
252  R_ProgramParameter3fvs("LIGHTPOSITIONS", maxLights, (GLfloat*)lightPositions);
253  R_ProgramParameter4fvs("LIGHTPARAMS", maxLights, (GLfloat*)lightParams);
254 }
255 
261 void R_AddStaticLight (const vec3_t origin, float radius, const vec3_t color)
262 {
264  Com_Printf("Failed to add lightsource: MAX_STATIC_LIGHTS exceeded\n");
265  return;
266  }
267 
268  Com_DPrintf(DEBUG_RENDERER, "added static light, color (%f, %f, %f) position (%f, %f, %f) radius=%f\n",
269  color[0], color[1], color[2],
270  origin[0], origin[1], origin[2],
271  radius);
272 
274 
275  VectorCopy(origin, light->origin);
276  VectorCopy(color, light->color);
277  light->color[3] = 1.0; /* needed if we pass this light as parameter to glLightxxx() */
278  light->radius = radius;
279 }
280 
281 /* If glow was enabled, disable it before calling this function, or rendering state will become incoherent */
282 void R_DisableLights (void)
283 {
284  vec4_t blackColor = {0.0, 0.0, 0.0, 1.0};
285 
286  for (int i = 0; i < MAX_GL_LIGHTS; i++) {
287  glLightf(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, MIN_GL_CONSTANT_ATTENUATION);
288  glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, blackColor);
289  glLightfv(GL_LIGHT0 + i, GL_AMBIENT, blackColor);
290  glLightfv(GL_LIGHT0 + i, GL_SPECULAR, blackColor);
291  glDisable(GL_LIGHT0 + i);
292  }
293  glDisable(GL_LIGHTING);
294 }
295 
301 {
303 }
304 
350 static void R_AddLightToEntity (const vec_t* pos, lighting_t* ltng, const light_t* light, const float distSqr)
351 {
352  int i;
353  int maxLights = r_dynamic_lights->integer;
354  const light_t** el = ltng->lights;
355 
356  for (i = 0; i < ltng->numLights; i++) {
357  if (i == maxLights)
358  return;
359  if (distSqr < VectorDistSqr((el[i]->origin), pos)) {
360  /* found more distant light, push it down the list and insert this one*/
361  if (i + 1 == maxLights) {
362  /* shortcut in case light we are replacing is the last light possible; also acts as the overflow guard */
363  el[i] = light;
364  return;
365  }
366 
367  while (i < ltng->numLights) {
368  const light_t* tmp = el[i];
369  el[i++] = light;
370  light = tmp;
371  }
372 
373  break;
374  }
375  }
376 
377  if (i == maxLights)
378  return;
379 
380  el[i++] = light;
381  ltng->numLights = i;
382 }
383 
395 {
396  int i;
397  vec_t* pos;
398  entity_t* rootEnt;
399  lighting_t* ltng;
400  vec3_t diametralVec;
401  float diameter;
402  bool cached = false;
403 
404  /* Find the root of tagent tree which actually owns the lighting data; it is assumed that there is no loops,
405  * since R_CalcTransform calls Com_Error on those */
406  for (rootEnt = ent; rootEnt->tagent; rootEnt = ent->tagent)
407  ;
408 
409  ltng = ent->lighting = rootEnt->lighting;
410 
411  if (!ltng) {
412  /* Entity got no lighting data, so substitute defaults (no dynamic lights, but exposed to sunlight) */
414  OBJZERO(fakeLightingData);
415  ent->lighting = &fakeLightingData;
416  return;
417  }
418 
419  if (ltng->lastLitFrame == r_locals.frame)
420  return; /* nothing to do, already calculated lighting for this frame */
421 
422  ltng->lastLitFrame = r_locals.frame;
423 
424  /* we have to use the offset from (accumulated) transform matrix, because entity origin is not necessarily the point where model is acually rendered */
425  pos = ent->transform.matrix + 12; /* type system hack, sorry */
426 
427  ent->eBox.getDiagonal(diametralVec);
428  diameter = VectorLength(diametralVec);
429 
431  if (VectorDist(pos, ltng->lastCachePos) < CACHE_CLEAR_TRESHOLD) {
432  cached = true;
433  } else {
434  ltng->numLights = 0; /* clear the list of lights */
435  ltng->numCachedLights = 0;
436  VectorCopy(pos, ltng->lastCachePos);
437  }
438 
439  /* Check if origin of this entity is hit by sunlight (not the best test, but at least fast) */
440  if (!cached) {
441  if (ent->flags & RF_ACTOR) {
442  vec3_t fakeSunPos;
443  VectorMA(pos, 8192.0, refdef.sunVector, fakeSunPos);
444  R_Trace(Line(pos, fakeSunPos), 0, MASK_SOLID);
445  ltng->inShadow = refdef.trace.fraction != 1.0;
446  } else {
447  ltng->inShadow = false;
448  }
449  }
450 
452  return;
453 
454  if (!cached) {
455  /* Rebuild list of static lights */
456  for (i = 0; i < refdef.numStaticLights; i++) {
457  light_t* light = &refdef.staticLights[i];
458  const float distSqr = VectorDistSqr(pos, light->origin);
459 
460  if (distSqr > (diameter + light->radius) * (diameter + light->radius))
461  continue;
462 
463  R_Trace(Line(pos, light->origin), 0, MASK_SOLID);
464 
465  if (refdef.trace.fraction == 1.0)
466  R_AddLightToEntity(pos, ltng, light, distSqr);
467  }
468  /* Save static lights to cache */
469  for (i = 0; i < ltng->numLights; i++)
470  ltng->cachedLights[i] = ltng->lights[i];
471  ltng->numCachedLights = ltng->numLights;
472  } else {
473  /* Copy static lights from cache */
474  for (i = 0; i < ltng->numCachedLights; i++)
475  ltng->lights[i] = ltng->cachedLights[i];
476  ltng->numLights = ltng->numCachedLights;
477  }
478 
479  /* add dynamic lights, too */
480  for (i = 0; i < refdef.numDynamicLights; i++) {
481  light_t* light = &refdef.dynamicLights[i];
482  const float distSqr = VectorDistSqr(pos, light->origin);
483 
484  if (distSqr > (diameter + light->radius) * (diameter + light->radius))
485  continue;
486 
487  R_Trace(Line(pos, light->origin), 0, MASK_SOLID);
488 
489  if (refdef.trace.fraction == 1.0)
490  R_AddLightToEntity(pos, ltng, light, distSqr);
491  }
492 }
vec4_t sunDiffuseColor
Definition: cl_renderer.h:184
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition: mathlib.cpp:434
void R_DisableAttribute(const char *name)
Definition: r_program.cpp:231
#define VectorCopy(src, dest)
Definition: vector.h:51
#define CACHE_CLEAR_TRESHOLD
Definition: r_lighting.h:48
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb)
Definition: mathlib.cpp:261
static sustain_t r_sustainArray[MAX_GL_LIGHTS]
Definition: r_light.cpp:30
light_t staticLights[MAX_STATIC_LIGHTS]
Definition: cl_renderer.h:194
void R_AddLight(const vec3_t origin, float radius, const vec3_t color)
Create light to be rendered in the current frame (will be removed before the next) ...
Definition: r_light.cpp:36
bool inShadow
Definition: r_lighting.h:41
void R_UpdateLightList(entity_t *ent)
Recalculate active lights list for the given entity; R_CalcTransform(ent) should be called before thi...
Definition: r_light.cpp:394
voidpf uLong int origin
Definition: ioapi.h:45
cvar_t * r_programs
Definition: r_main.cpp:97
void R_DisableLights(void)
Definition: r_light.cpp:282
float vec_t
Definition: ufotypes.h:37
vec4_t sunVector
Definition: cl_renderer.h:186
#define VectorDist(a, b)
Definition: vector.h:69
local graphics definitions
cvar_t * r_dynamic_lights
Definition: r_main.cpp:96
#define MIN_GL_CONSTANT_ATTENUATION
Definition: r_local.h:45
void GLPositionTransform(const float m[16], const vec3_t in, vec3_t out)
Transform position (xyz) vector by OpenGL rules.
Definition: mathlib.cpp:380
const light_t * lights[MAX_ENTITY_LIGHTS]
Definition: r_lighting.h:36
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
int integer
Definition: cvar.h:81
a light source
Definition: r_light.h:29
#define VectorScale(in, scale, out)
Definition: vector.h:79
float sustain
Definition: r_light.h:39
lighting structure which contains static and dynamic lighting info for entities
Definition: r_lighting.h:29
static void R_AddLightToEntity(const vec_t *pos, lighting_t *ltng, const light_t *light, const float distSqr)
Adds light to the entity's lights list, sorted by distance.
Definition: r_light.cpp:350
float fraction
Definition: tracing.h:58
static light_t * lights[LIGHTMAP_MAX]
Definition: lightmap.cpp:285
void R_ClearStaticLights(void)
Remove all static light data.
Definition: r_light.cpp:300
bool lighting_enabled
Definition: r_state.h:154
float world_matrix[16]
Definition: r_local.h:112
rendererData_t refdef
Definition: r_main.cpp:45
#define OBJZERO(obj)
Definition: shared.h:178
int numLights
Definition: r_lighting.h:37
#define Vector4Set(v, r, g, b, a)
Definition: vector.h:62
rlocals_t r_locals
Definition: r_main.cpp:49
void R_ProgramParameter3fv(const char *name, GLfloat *value)
Definition: r_program.cpp:161
#define MAX_GL_LIGHTS
Definition: cl_renderer.h:55
int frame
Definition: r_local.h:109
light_t dynamicLights[MAX_GL_LIGHTS]
Definition: cl_renderer.h:191
int numCachedLights
Definition: r_lighting.h:33
material_t defaultMaterial
Definition: r_material.cpp:34
#define MASK_SOLID
Definition: defines.h:272
Definition: line.h:31
const light_t * cachedLights[MAX_ENTITY_LIGHTS]
Definition: r_lighting.h:32
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
void R_AddSustainedLight(const vec3_t org, float radius, const vec3_t color, float sustain)
Definition: r_light.cpp:58
bool dynamic_lighting_enabled
Definition: r_state.h:160
void R_Trace(const Line &trLine, float size, int contentmask)
Moves the given mins/maxs volume through the world from start to end.
Definition: r_lightmap.cpp:317
vec4_t color
Definition: r_light.h:31
void R_ProgramParameter4fvs(const char *name, GLint size, GLfloat *value)
Definition: r_program.cpp:191
light_t light
Definition: r_light.h:37
void R_UpdateSustainedLights(void)
Updates state of sustained lights; should be called once per frame right before world rendering...
Definition: r_light.cpp:83
int lastLitFrame
Definition: r_lighting.h:38
void R_EnableAttribute(const char *name)
Definition: r_program.cpp:221
QGL_EXTERN GLint i
Definition: r_gl.h:113
vec3_t origin
Definition: r_light.h:30
void R_UseMaterial(const material_t *material)
Definition: r_state.cpp:105
static lighting_t fakeLightingData
Definition: r_light.cpp:384
vec_t vec3_t[3]
Definition: ufotypes.h:39
rstate_t r_state
Definition: r_main.cpp:48
void R_ProgramParameter3fvs(const char *name, GLint size, GLfloat *value)
Definition: r_program.cpp:171
vec4_t modelAmbientColor
Definition: cl_renderer.h:183
void R_EnableWorldLights(void)
Set up lighting data for the GLSL world shader.
Definition: r_light.cpp:108
sustains are light flashes which slowly decay
Definition: r_light.h:36
vec3_t lastCachePos
Definition: r_lighting.h:31
float time
Definition: r_light.h:38
#define DEBUG_RENDERER
Definition: defines.h:62
#define VectorDistSqr(a, b)
Definition: vector.h:68
void R_EnableModelLights(const light_t **lights, int numLights, bool inShadow, bool enable)
Enable or disable realtime dynamic lighting for models.
Definition: r_light.cpp:149
#define MAX_STATIC_LIGHTS
Definition: r_light.h:47
#define RF_ACTOR
Definition: r_entity.h:46
void R_AddStaticLight(const vec3_t origin, float radius, const vec3_t color)
Add static light for model lighting (world already got them baked into lightmap)
Definition: r_light.cpp:261
vec_t vec4_t[4]
Definition: ufotypes.h:40
float radius
Definition: r_light.h:32