UFO: Alien Invasion
Loading...
Searching...
No Matches
r_light.cpp
Go to the documentation of this file.
1
4
5/*
6Copyright (C) 1997-2001 Id Software, Inc.
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, 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
36void R_AddLight (const vec3_t origin, float radius, const vec3_t color)
37{
38 int i;
39
40 if (refdef.numDynamicLights == MAX_GL_LIGHTS)
41 return;
42
43 i = refdef.numDynamicLights++;
44
45 VectorCopy(origin, refdef.dynamicLights[i].origin);
46 refdef.dynamicLights[i].radius = radius;
47 VectorCopy(color, refdef.dynamicLights[i].color);
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
58void 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
120 if (!r_dynamic_lights->integer)
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
149void 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) {
201 if (r_state.dynamic_lighting_enabled) {
202 R_DisableAttribute("TANGENTS");
203
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
214 r_state.dynamic_lighting_enabled = false;
215 return;
216 }
217
219 if (numLights > maxLights)
220 numLights = maxLights;
221
222 r_state.dynamic_lighting_enabled = true;
223
224 R_EnableAttribute("TANGENTS");
225
227
228 R_ProgramParameter3fv("AMBIENT", refdef.modelAmbientColor);
229
230 if (inShadow) {
231 R_ProgramParameter3fv("SUNCOLOR", blackColor);
232 } else {
233 R_ProgramParameter3fv("SUNCOLOR", refdef.sunDiffuseColor);
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
261void R_AddStaticLight (const vec3_t origin, float radius, const vec3_t color)
262{
263 if (refdef.numStaticLights >= MAX_STATIC_LIGHTS) {
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
273 light_t* light = &refdef.staticLights[refdef.numStaticLights++];
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 */
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{
302 refdef.numStaticLights = 0;
303}
304
350static 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
385
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) */
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
451 if (!r_dynamic_lights->integer)
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}
#define MAX_GL_LIGHTS
Definition cl_renderer.h:55
rendererData_t refdef
Definition r_main.cpp:45
void getDiagonal(vec3_t diagonal) const
Definition aabb.h:159
Definition line.h:31
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define DEBUG_RENDERER
Definition defines.h:62
#define MASK_SOLID
Definition defines.h:272
voidpf uLong int origin
Definition ioapi.h:45
static light_t * lights[LIGHTMAP_MAX]
Definition lightmap.cpp:285
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition mathlib.cpp:434
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
void GLPositionTransform(const float m[16], const vec3_t in, vec3_t out)
Transform position (xyz) vector by OpenGL rules.
Definition mathlib.cpp:380
#define RF_ACTOR
Definition r_entity.h:46
QGL_EXTERN GLint i
Definition r_gl.h:113
static sustain_t r_sustainArray[MAX_GL_LIGHTS]
Definition r_light.cpp:30
void R_AddSustainedLight(const vec3_t org, float radius, const vec3_t color, float sustain)
Definition r_light.cpp:58
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
void R_ClearStaticLights(void)
Remove all static light data.
Definition r_light.cpp:300
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
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
void R_UpdateSustainedLights(void)
Updates state of sustained lights; should be called once per frame right before world rendering.
Definition r_light.cpp:83
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
static lighting_t fakeLightingData
Definition r_light.cpp:384
void R_DisableLights(void)
Definition r_light.cpp:282
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
void R_EnableWorldLights(void)
Set up lighting data for the GLSL world shader.
Definition r_light.cpp:108
#define MAX_STATIC_LIGHTS
Definition r_light.h:47
#define CACHE_CLEAR_TRESHOLD
Definition r_lighting.h:48
void R_Trace(const Line &trLine, float size, int contentmask)
Moves the given mins/maxs volume through the world from start to end.
local graphics definitions
#define MIN_GL_CONSTANT_ATTENUATION
Definition r_local.h:45
cvar_t * r_programs
Definition r_main.cpp:97
cvar_t * r_dynamic_lights
Definition r_main.cpp:96
rlocals_t r_locals
Definition r_main.cpp:49
rstate_t r_state
Definition r_main.cpp:48
material_t defaultMaterial
void R_EnableAttribute(const char *name)
void R_ProgramParameter3fvs(const char *name, GLint size, GLfloat *value)
void R_ProgramParameter4fvs(const char *name, GLint size, GLfloat *value)
void R_DisableAttribute(const char *name)
void R_ProgramParameter3fv(const char *name, GLfloat *value)
void R_UseMaterial(const material_t *material)
Definition r_state.cpp:105
#define OBJZERO(obj)
Definition shared.h:178
int flags
Definition r_entity.h:112
lighting_t * lighting
Definition r_entity.h:125
transform_t transform
Definition r_entity.h:119
struct entity_s * tagent
Definition r_entity.h:106
AABB eBox
Definition r_entity.h:103
a light source
Definition r_light.h:29
vec4_t color
Definition r_light.h:31
vec3_t origin
Definition r_light.h:30
float radius
Definition r_light.h:32
lighting structure which contains static and dynamic lighting info for entities
Definition r_lighting.h:29
bool inShadow
Definition r_lighting.h:41
vec3_t lastCachePos
Definition r_lighting.h:31
int numCachedLights
Definition r_lighting.h:33
const light_t * cachedLights[MAX_ENTITY_LIGHTS]
Definition r_lighting.h:32
int lastLitFrame
Definition r_lighting.h:38
int numLights
Definition r_lighting.h:37
const light_t * lights[MAX_ENTITY_LIGHTS]
Definition r_lighting.h:36
sustains are light flashes which slowly decay
Definition r_light.h:36
float sustain
Definition r_light.h:39
light_t light
Definition r_light.h:37
float time
Definition r_light.h:38
float matrix[16]
Definition r_entity.h:88
float vec_t
Definition ufotypes.h:37
vec_t vec3_t[3]
Definition ufotypes.h:39
vec_t vec4_t[4]
Definition ufotypes.h:40
#define VectorDist(a, b)
Definition vector.h:69
#define Vector4Set(v, r, g, b, a)
Definition vector.h:62
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorDistSqr(a, b)
Definition vector.h:68
#define VectorScale(in, scale, out)
Definition vector.h:79