Quake II RTX doxygen  1.0 dev
light.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 // r_light.c
19 
20 #include "sw.h"
21 
23 
24 
25 /*
26 =============================================================================
27 
28 DYNAMIC LIGHTS
29 
30 =============================================================================
31 */
32 
33 /*
34 =============
35 R_MarkLights_r
36 =============
37 */
38 static void R_MarkLights_r(mnode_t *node, dlight_t *light,
39  vec3_t transformed, int bit)
40 {
41  float dist;
42  mface_t *surf;
43  int i;
44 
45  while (node->plane) {
46  dist = PlaneDiffFast(transformed, node->plane);
47  if (dist > light->intensity - DLIGHT_CUTOFF) {
48  node = node->children[0];
49  continue;
50  }
51  if (dist < -light->intensity + DLIGHT_CUTOFF) {
52  node = node->children[1];
53  continue;
54  }
55 
56  // mark the polygons
57  surf = node->firstface;
58  for (i = 0; i < node->numfaces; i++, surf++) {
59  if (surf->dlightframe != r_dlightframecount) {
60  surf->dlightbits = 0;
61  surf->dlightframe = r_dlightframecount;
62  }
63  surf->dlightbits |= bit;
64  }
65 
66  R_MarkLights_r(node->children[0], light, transformed, bit);
67  node = node->children[1];
68  }
69 }
70 
71 /*
72 =============
73 R_MarkLights
74 =============
75 */
76 void R_MarkLights(mnode_t *headnode)
77 {
78  dlight_t *light;
79  vec3_t transformed;
80  int i;
81 
83  for (i = 0, light = r_newrefdef.dlights; i < r_newrefdef.num_dlights; i++, light++) {
84  if (insubmodel) {
85  vec3_t temp;
86 
87  VectorSubtract(light->origin, currententity->origin, temp);
88  transformed[0] = DotProduct(temp, entity_rotation[0]);
89  transformed[1] = DotProduct(temp, entity_rotation[1]);
90  transformed[2] = DotProduct(temp, entity_rotation[2]);
91  } else {
92  VectorCopy(light->origin, transformed);
93  }
94  R_MarkLights_r(headnode, light, transformed, 1 << i);
95  }
96 }
97 
98 /*
99 =============================================================================
100 
101 LIGHT SAMPLING
102 
103 =============================================================================
104 */
105 
106 static qboolean _R_LightPoint(vec3_t start, vec3_t color)
107 {
108  mface_t *surf;
109  int s, t, maps;
110  byte *lightmap;
111  byte *b1, *b2, *b3, *b4;
112  int fracu, fracv;
113  int w1, w2, w3, w4;
114  byte temp[3];
115  int smax, tmax, size;
116  float scale;
117  vec3_t end;
118  lightpoint_t lightpoint;
119 
120  end[0] = start[0];
121  end[1] = start[1];
122  end[2] = start[2] - 2048;
123 
124  BSP_LightPoint(&lightpoint, start, end, r_worldmodel->nodes);
125 
126  surf = lightpoint.surf;
127  if (!surf)
128  return qfalse;
129 
130  fracu = lightpoint.s & 15;
131  fracv = lightpoint.t & 15;
132 
133  // compute weights of lightmap blocks
134  w1 = (16 - fracu) * (16 - fracv);
135  w2 = fracu * (16 - fracv);
136  w3 = fracu * fracv;
137  w4 = (16 - fracu) * fracv;
138 
139  s = lightpoint.s >> 4;
140  t = lightpoint.t >> 4;
141 
142  smax = S_MAX(surf);
143  tmax = T_MAX(surf);
144  size = smax * tmax * LIGHTMAP_BYTES;
145 
146  // add all the lightmaps with bilinear filtering
147  lightmap = surf->lightmap;
148  for (maps = 0; maps < surf->numstyles; maps++) {
149  b1 = &lightmap[LIGHTMAP_BYTES * ((t + 0) * smax + (s + 0))];
150  b2 = &lightmap[LIGHTMAP_BYTES * ((t + 0) * smax + (s + 1))];
151  b3 = &lightmap[LIGHTMAP_BYTES * ((t + 1) * smax + (s + 1))];
152  b4 = &lightmap[LIGHTMAP_BYTES * ((t + 1) * smax + (s + 0))];
153 
154  temp[0] = (w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0]) >> 8;
155  temp[1] = (w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1]) >> 8;
156  temp[2] = (w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2]) >> 8;
157 
158  scale = r_newrefdef.lightstyles[surf->styles[maps]].white * (1.0f / 255);
159  color[0] += temp[0] * scale;
160  color[1] += temp[1] * scale;
161  color[2] += temp[2] * scale;
162 
163  lightmap += size;
164  }
165 
166  return qtrue;
167 }
168 
169 /*
170 ===============
171 R_LightPoint
172 ===============
173 */
174 void R_LightPoint(vec3_t point, vec3_t color)
175 {
176  int lnum;
177  dlight_t *dl;
178  float add;
179 
180  if (!r_worldmodel || !r_worldmodel->lightmap || r_fullbright->integer) {
181  VectorSet(color, 1, 1, 1);
182  return;
183  }
184 
185  VectorClear(color);
186 
187  if (!_R_LightPoint(point, color))
188  VectorSet(color, 1, 1, 1);
189 
190  //
191  // add dynamic lights
192  //
193  for (lnum = 0; lnum < r_newrefdef.num_dlights; lnum++) {
194  dl = &r_newrefdef.dlights[lnum];
195  add = dl->intensity - DLIGHT_CUTOFF - Distance(point, dl->origin);
196  if (add > 0) {
197  add *= (1.0f / 255);
198  VectorMA(color, add, dl->color, color);
199  }
200  }
201 
202  VectorScale(color, sw_modulate->value, color);
203 }
204 
205 //===================================================================
206 
208 
209 /*
210 ===============
211 R_AddDynamicLights
212 ===============
213 */
214 static void R_AddDynamicLights(void)
215 {
216  mface_t *surf;
217  dlight_t *light;
218  mtexinfo_t *tex;
219  vec3_t transformed, impact;
220  int local[2];
221  vec_t dist, rad, minlight, scale, frac;
222  blocklight_t *block;
223  int i, smax, tmax, s, t, sd, td;
224 
225  surf = r_drawsurf.surf;
226  smax = S_MAX(surf);
227  tmax = T_MAX(surf);
228  tex = surf->texinfo;
229 
230  for (i = 0; i < r_newrefdef.num_dlights; i++) {
231  if (!(surf->dlightbits & (1 << i)))
232  continue;
233 
234  light = &r_newrefdef.dlights[i];
235 
237  vec3_t temp;
238 
239  VectorSubtract(light->origin, currententity->origin, temp);
240  transformed[0] = DotProduct(temp, entity_rotation[0]);
241  transformed[1] = DotProduct(temp, entity_rotation[1]);
242  transformed[2] = DotProduct(temp, entity_rotation[2]);
243  } else {
244  VectorCopy(light->origin, transformed);
245  }
246 
247  dist = PlaneDiffFast(transformed, surf->plane);
248  rad = light->intensity - fabs(dist);
249  if (rad < DLIGHT_CUTOFF)
250  continue;
251  minlight = rad - DLIGHT_CUTOFF * 0.8f;
252  scale = rad / minlight;
253 
254  VectorMA(transformed, -dist, surf->plane->normal, impact);
255 
256  local[0] = DotProduct(impact, tex->axis[0]) + tex->offset[0];
257  local[1] = DotProduct(impact, tex->axis[1]) + tex->offset[1];
258 
259  local[0] -= surf->texturemins[0];
260  local[1] -= surf->texturemins[1];
261 
262  block = blocklights;
263  for (t = 0; t < tmax; t++) {
264  td = abs(local[1] - (t << 4));
265  for (s = 0; s < smax; s++) {
266  sd = abs(local[0] - (s << 4));
267  if (sd > td)
268  dist = sd + (td >> 1);
269  else
270  dist = td + (sd >> 1);
271  if (dist < minlight) {
272  frac = (rad - dist * scale) * sw_modulate->value * 256;
273  block[0] += light->color[0] * frac;
274  block[1] += light->color[1] * frac;
275  block[2] += light->color[2] * frac;
276  }
277  block += LIGHTMAP_BYTES;
278  }
279  }
280  }
281 }
282 
283 /*
284 ===============
285 R_BuildLightMap
286 
287 Combine and scale multiple lightmaps into the 8.8 format in blocklights
288 ===============
289 */
290 void R_BuildLightMap(void)
291 {
292  int i, maps, smax, tmax, size;
293  byte *lightmap;
294  mface_t *surf;
295  blocklight_t *block;
296 
297  surf = r_drawsurf.surf;
298  smax = S_MAX(surf);
299  tmax = T_MAX(surf);
300  size = smax * tmax;
301 
302  if (size > MAX_BLOCKLIGHTS)
303  Com_Error(ERR_DROP, "R_BuildLightMap: surface blocklights size %i > %i", size, MAX_BLOCKLIGHTS);
304 
305  if (r_fullbright->integer || !surf->lightmap) {
306  block = blocklights;
307  for (i = 0; i < size; i++) {
308  block[0] = block[1] = block[2] = 0xffff;
309  block += LIGHTMAP_BYTES;
310  }
311  return;
312  }
313 
314 // clear to no light
315  memset(blocklights, 0, sizeof(blocklights[0]) * size * LIGHTMAP_BYTES);
316 
317 // add all the lightmaps
318  lightmap = surf->lightmap;
319  for (maps = 0; maps < surf->numstyles; maps++) {
320  fixed8_t scale;
321 
322  block = blocklights;
323  scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
324  for (i = 0; i < size; i++) {
325  block[0] += lightmap[0] * scale;
326  block[1] += lightmap[1] * scale;
327  block[2] += lightmap[2] * scale;
328 
329  lightmap += LIGHTMAP_BYTES;
330  block += LIGHTMAP_BYTES;
331  }
332  }
333 
334 // add all the dynamic lights
335  if (surf->dlightframe == r_framecount)
337 
338 // bound
339  block = blocklights;
340  for (i = 0; i < size; i++) {
341  blocklight_t r, g, b, max;
342 
343  r = block[0];
344  g = block[1];
345  b = block[2];
346 
347  // catch negative lights
348  if (r < 255)
349  r = 255;
350  if (g < 255)
351  g = 255;
352  if (b < 255)
353  b = 255;
354 
355  // determine the brightest of the three color components
356  max = g;
357  if (r > max)
358  max = r;
359  if (b > max)
360  max = b;
361 
362  // rescale all the color components if the intensity of the greatest
363  // channel exceeds 1.0
364  if (max > 65535) {
365  float y;
366 
367  y = 65535.0f / max;
368  r *= y;
369  g *= y;
370  b *= y;
371  }
372 
373  block[0] = r;
374  block[1] = g;
375  block[2] = b;
376 
377  block += LIGHTMAP_BYTES;
378  }
379 }
380 
blocklight_t
int blocklight_t
Definition: sw.h:205
r_dlightframecount
int r_dlightframecount
Definition: light.c:22
r_newrefdef
refdef_t r_newrefdef
Definition: main.c:28
R_MarkLights_r
static void R_MarkLights_r(mnode_t *node, dlight_t *light, vec3_t transformed, int bit)
Definition: light.c:38
R_LightPoint
void R_LightPoint(vec3_t point, vec3_t color)
Definition: light.c:174
entity_rotation
vec3_t entity_rotation[3]
Definition: bsp.c:32
r_framecount
int r_framecount
Definition: main.c:64
R_AddDynamicLights
static void R_AddDynamicLights(void)
Definition: light.c:214
_R_LightPoint
static qboolean _R_LightPoint(vec3_t start, vec3_t color)
Definition: light.c:106
r_fullbright
cvar_t * r_fullbright
Definition: main.c:98
currententity
entity_t * currententity
Definition: bsp.c:26
drawsurf_s::surf
mface_t * surf
Definition: sw.h:179
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
R_BuildLightMap
void R_BuildLightMap(void)
Definition: light.c:290
drawsurf_s::lightadj
fixed8_t lightadj[MAX_LIGHTMAPS]
Definition: sw.h:180
sw.h
areanode_s::dist
float dist
Definition: world.c:33
r_worldentity
entity_t r_worldentity
Definition: main.c:26
sw_modulate
cvar_t * sw_modulate
Definition: main.c:87
LIGHTMAP_BYTES
#define LIGHTMAP_BYTES
Definition: sw.h:203
r_drawsurf
drawsurf_t r_drawsurf
Definition: surf.c:22
intensity
cvar_t * intensity
Definition: god_rays.c:38
blocklights
blocklight_t blocklights[MAX_BLOCKLIGHTS *LIGHTMAP_BYTES]
Definition: light.c:207
color
static vec4_t color
Definition: mesh.c:33
insubmodel
qboolean insubmodel
Definition: bsp.c:25
r_worldmodel
bsp_t * r_worldmodel
Definition: main.c:31
R_MarkLights
void R_MarkLights(mnode_t *headnode)
Definition: light.c:76
MAX_BLOCKLIGHTS
#define MAX_BLOCKLIGHTS
Definition: surf.c:110