1 /*
2 gl_lightmap.c
3
4 surface-related refresh code
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7 Copyright (C) 2000 Joseph Carter <knghtbrd@debian.org>
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18 See the GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to:
22
23 Free Software Foundation, Inc.
24 59 Temple Place - Suite 330
25 Boston, MA 02111-1307, USA
26
27 */
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #define NH_DEFINE
33 #include "namehack.h"
34
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #endif
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif
41
42 #include <math.h>
43 #include <stdio.h>
44
45 #include "QF/cvar.h"
46 #include "QF/render.h"
47 #include "QF/sys.h"
48 #include "QF/GL/defines.h"
49 #include "QF/GL/funcs.h"
50 #include "QF/GL/qf_lightmap.h"
51 #include "QF/GL/qf_rmain.h"
52 #include "QF/GL/qf_sky.h"
53 #include "QF/GL/qf_textures.h"
54 #include "QF/GL/qf_vid.h"
55
56 #include "compat.h"
57 #include "r_internal.h"
58
59 static int dlightdivtable[8192];
60 static int gl_internalformat; // 1 or 3
61 static int lightmap_bytes; // 1, 3, or 4
62 int gl_lightmap_textures;
63
64 // keep lightmap texture data in main memory so texsubimage can update properly
65 // LordHavoc: changed to be allocated at runtime (typically lower memory usage)
66 static byte *lightmaps[MAX_LIGHTMAPS];
67
68 static unsigned int blocklights[34 * 34 * 3]; //FIXME make dynamic
69 static int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
70
71 qboolean gl_lightmap_modified[MAX_LIGHTMAPS];
72 instsurf_t *gl_lightmap_polys[MAX_LIGHTMAPS];
73 glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS];
74
75 static int lmshift = 7;
76
77 void (*gl_R_BuildLightMap) (msurface_t *surf);
78
79 extern void gl_multitexture_f (cvar_t *var);
80
81
82 void
gl_lightmap_init(void)83 gl_lightmap_init (void)
84 {
85 int s;
86
87 memset (&lightmaps, 0, sizeof (lightmaps));
88 dlightdivtable[0] = 1048576 >> 7;
89 for (s = 1; s < 8192; s++)
90 dlightdivtable[s] = 1048576 / (s << 7);
91 }
92 /*
93 static void
94 R_RecursiveLightUpdate (mnode_t *node)
95 {
96 int c;
97 msurface_t *surf;
98
99 if (node->children[0]->contents >= 0)
100 R_RecursiveLightUpdate (node->children[0]);
101 if (node->children[1]->contents >= 0)
102 R_RecursiveLightUpdate (node->children[1]);
103 if ((c = node->numsurfaces))
104 for (surf = r_worldentity.model->surfaces + node->firstsurface; c;
105 c--, surf++)
106 surf->cached_dlight = true;
107 }
108 */
109 static inline void
R_AddDynamicLights_1(msurface_t * surf)110 R_AddDynamicLights_1 (msurface_t *surf)
111 {
112 float dist;
113 unsigned int maxdist, maxdist2, maxdist3;
114 int smax, smax_bytes, tmax,
115 grey, s, t;
116 unsigned int lnum, td, i, j;
117 unsigned int sdtable[18];
118 unsigned int *bl;
119 vec3_t impact, local;
120
121 smax = (surf->extents[0] >> 4) + 1;
122 smax_bytes = smax * gl_internalformat;
123 tmax = (surf->extents[1] >> 4) + 1;
124
125 for (lnum = 0; lnum < r_maxdlights; lnum++) {
126 if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
127 continue; // not lit by this light
128
129 VectorSubtract (r_dlights[lnum].origin, currententity->origin, local);
130 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
131 VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal,
132 impact);
133
134 i = DotProduct (impact, surf->texinfo->vecs[0]) +
135 surf->texinfo->vecs[0][3] - surf->texturemins[0];
136
137 // reduce calculations
138 t = dist * dist;
139 for (s = 0; s < smax; s++, i -= 16)
140 sdtable[s] = i * i + t;
141
142 i = DotProduct (impact, surf->texinfo->vecs[1]) +
143 surf->texinfo->vecs[1][3] - surf->texturemins[1];
144
145 // for comparisons to minimum acceptable light
146 maxdist = (int) (r_dlights[lnum].radius * r_dlights[lnum].radius);
147
148 // clamp radius to avoid exceeding 8192 entry division table
149 if (maxdist > 1048576)
150 maxdist = 1048576;
151 maxdist3 = maxdist - t;
152
153 // convert to 8.8 blocklights format
154 grey = (r_dlights[lnum].color[0] + r_dlights[lnum].color[1] +
155 r_dlights[lnum].color[2]) * maxdist / 3.0;
156 bl = blocklights;
157 for (t = 0; t < tmax; t++, i -= 16) {
158 td = i * i;
159 if (td < maxdist3) { // ensure part is visible on this line
160 maxdist2 = maxdist - td;
161 for (s = 0; s < smax; s++) {
162 if (sdtable[s] < maxdist2) {
163 j = dlightdivtable[(sdtable[s] + td) >> 7];
164 *bl++ += (grey * j) >> 7;
165 } else
166 bl++;
167 }
168 } else
169 bl += smax_bytes; // skip line
170 }
171 }
172 }
173
174 static inline void
R_AddDynamicLights_3(msurface_t * surf)175 R_AddDynamicLights_3 (msurface_t *surf)
176 {
177 float dist;
178 unsigned int maxdist, maxdist2, maxdist3;
179 int smax, smax_bytes, tmax,
180 red, green, blue, s, t;
181 unsigned int lnum, td, i, j;
182 unsigned int sdtable[18];
183 unsigned int *bl;
184 vec3_t impact, local;
185
186 smax = (surf->extents[0] >> 4) + 1;
187 smax_bytes = smax * gl_internalformat;
188 tmax = (surf->extents[1] >> 4) + 1;
189
190 for (lnum = 0; lnum < r_maxdlights; lnum++) {
191 if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
192 continue; // not lit by this light
193
194 VectorSubtract (r_dlights[lnum].origin, currententity->origin, local);
195 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
196 VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal,
197 impact);
198
199 i = DotProduct (impact, surf->texinfo->vecs[0]) +
200 surf->texinfo->vecs[0][3] - surf->texturemins[0];
201
202 // reduce calculations
203 t = dist * dist;
204 for (s = 0; s < smax; s++, i -= 16)
205 sdtable[s] = i * i + t;
206
207 i = DotProduct (impact, surf->texinfo->vecs[1]) +
208 surf->texinfo->vecs[1][3] - surf->texturemins[1];
209
210 // for comparisons to minimum acceptable light
211 maxdist = (int) (r_dlights[lnum].radius * r_dlights[lnum].radius);
212
213 // clamp radius to avoid exceeding 8192 entry division table
214 if (maxdist > 1048576)
215 maxdist = 1048576;
216 maxdist3 = maxdist - t;
217
218 // convert to 8.8 blocklights format
219 red = r_dlights[lnum].color[0] * maxdist;
220 green = r_dlights[lnum].color[1] * maxdist;
221 blue = r_dlights[lnum].color[2] * maxdist;
222 bl = blocklights;
223 for (t = 0; t < tmax; t++, i -= 16) {
224 td = i * i;
225 if (td < maxdist3) { // ensure part is visible on this line
226 maxdist2 = maxdist - td;
227 for (s = 0; s < smax; s++) {
228 if (sdtable[s] < maxdist2) {
229 j = dlightdivtable[(sdtable[s] + td) >> 7];
230 *bl++ += (red * j) >> 7;
231 *bl++ += (green * j) >> 7;
232 *bl++ += (blue * j) >> 7;
233 } else
234 bl += 3;
235 }
236 } else
237 bl += smax_bytes; // skip line
238 }
239 }
240 }
241
242 static void
R_BuildLightMap_1(msurface_t * surf)243 R_BuildLightMap_1 (msurface_t *surf)
244 {
245 byte *dest;
246 int maps, size, stride, smax, tmax, i, j;
247 unsigned int scale;
248 unsigned int *bl;
249
250 surf->cached_dlight = (surf->dlightframe == r_framecount);
251
252 smax = (surf->extents[0] >> 4) + 1;
253 tmax = (surf->extents[1] >> 4) + 1;
254 size = smax * tmax * gl_internalformat;
255
256 // set to full bright if no light data
257 if (!r_worldentity.model->lightdata) {
258 memset (&blocklights[0], 0xff, size * sizeof(int));
259 goto store;
260 }
261
262 // clear to no light
263 memset (&blocklights[0], 0, size * sizeof(int));
264
265 // add all the lightmaps
266 if (surf->samples) {
267 byte *lightmap;
268
269 lightmap = surf->samples;
270 for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
271 maps++) {
272 scale = d_lightstylevalue[surf->styles[maps]];
273 surf->cached_light[maps] = scale; // 8.8 fraction
274 bl = blocklights;
275 for (i = 0; i < size; i++) {
276 *bl++ += *lightmap++ * scale;
277 }
278 }
279 }
280 // add all the dynamic lights
281 if (surf->dlightframe == r_framecount)
282 R_AddDynamicLights_1 (surf);
283
284 store:
285 // bound and shift
286 // Also, invert because we're using a diff blendfunc now
287
288 stride = (BLOCK_WIDTH - smax) * lightmap_bytes;
289 bl = blocklights;
290
291 dest = lightmaps[surf->lightmaptexturenum]
292 + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
293
294 for (i = 0; i < tmax; i++, dest += stride) {
295 for (j = smax; j; j--) {
296 *dest++ = min (*bl >> lmshift, 255);
297 bl++;
298 }
299 }
300 }
301
302 static void
R_BuildLightMap_3(msurface_t * surf)303 R_BuildLightMap_3 (msurface_t *surf)
304 {
305 byte *dest;
306 int maps, size, stride, smax, tmax, i, j;
307 unsigned int scale;
308 unsigned int *bl;
309
310 surf->cached_dlight = (surf->dlightframe == r_framecount);
311
312 smax = (surf->extents[0] >> 4) + 1;
313 tmax = (surf->extents[1] >> 4) + 1;
314 size = smax * tmax * gl_internalformat;
315
316 // set to full bright if no light data
317 if (!r_worldentity.model->lightdata) {
318 memset (&blocklights[0], 0xff, size * sizeof(int));
319 goto store;
320 }
321
322 // clear to no light
323 memset (&blocklights[0], 0, size * sizeof(int));
324
325 // add all the lightmaps
326 if (surf->samples) {
327 byte *lightmap;
328
329 lightmap = surf->samples;
330 for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
331 maps++) {
332 scale = d_lightstylevalue[surf->styles[maps]];
333 surf->cached_light[maps] = scale; // 8.8 fraction
334 bl = blocklights;
335 for (i = 0; i < smax * tmax; i++) {
336 *bl++ += *lightmap++ * scale;
337 *bl++ += *lightmap++ * scale;
338 *bl++ += *lightmap++ * scale;
339 }
340 }
341 }
342 // add all the dynamic lights
343 if (surf->dlightframe == r_framecount)
344 R_AddDynamicLights_3 (surf);
345
346 store:
347 // bound and shift
348 // and invert too
349 stride = (BLOCK_WIDTH - smax) * lightmap_bytes;
350 bl = blocklights;
351
352 dest = lightmaps[surf->lightmaptexturenum]
353 + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
354
355 for (i = 0; i < tmax; i++, dest += stride) {
356 for (j = 0; j < smax; j++) {
357 *dest++ = min (*bl >> lmshift, 255);
358 bl++;
359 *dest++ = min (*bl >> lmshift, 255);
360 bl++;
361 *dest++ = min (*bl >> lmshift, 255);
362 bl++;
363 }
364 }
365 }
366
367 static void
R_BuildLightMap_4(msurface_t * surf)368 R_BuildLightMap_4 (msurface_t *surf)
369 {
370 byte *dest;
371 int maps, size, smax, tmax, i, j, stride;
372 unsigned int scale;
373 unsigned int *bl;
374
375 surf->cached_dlight = (surf->dlightframe == r_framecount);
376
377 smax = (surf->extents[0] >> 4) + 1;
378 tmax = (surf->extents[1] >> 4) + 1;
379 size = smax * tmax * gl_internalformat;
380
381 // set to full bright if no light data
382 if (!r_worldentity.model->lightdata) {
383 memset (&blocklights[0], 0xff, size * sizeof(int));
384 goto store;
385 }
386
387 // clear to no light
388 memset (&blocklights[0], 0, size * sizeof(int));
389
390 // add all the lightmaps
391 if (surf->samples) {
392 byte *lightmap;
393
394 lightmap = surf->samples;
395 for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
396 maps++) {
397 scale = d_lightstylevalue[surf->styles[maps]];
398 surf->cached_light[maps] = scale; // 8.8 fraction
399 bl = blocklights;
400 for (i = 0; i < smax * tmax; i++) {
401 *bl++ += *lightmap++ * scale;
402 *bl++ += *lightmap++ * scale;
403 *bl++ += *lightmap++ * scale;
404 }
405 }
406 }
407 // add all the dynamic lights
408 if (surf->dlightframe == r_framecount)
409 R_AddDynamicLights_3 (surf);
410
411 store:
412 // bound and shift
413 // and invert too
414 stride = (BLOCK_WIDTH - smax) * lightmap_bytes;
415 bl = blocklights;
416
417 dest = lightmaps[surf->lightmaptexturenum]
418 + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
419
420 for (i = 0; i < tmax; i++, dest += stride) {
421 for (j = 0; j < smax; j++) {
422 *dest++ = min (*bl >> lmshift, 255);
423 bl++;
424 *dest++ = min (*bl >> lmshift, 255);
425 bl++;
426 *dest++ = min (*bl >> lmshift, 255);
427 bl++;
428 *dest++ = 255;
429 }
430 }
431 }
432
433 // BRUSH MODELS ===============================================================
434
435 static inline void
do_subimage_2(int i)436 do_subimage_2 (int i)
437 {
438 byte *block, *lm, *b;
439 int stride, width;
440 glRect_t *rect = &gl_lightmap_rectchange[i];
441
442 width = rect->w * lightmap_bytes;
443 stride = BLOCK_WIDTH * lightmap_bytes;
444 b = block = Hunk_TempAlloc (rect->h * width);
445 lm = lightmaps[i] + (rect->t * BLOCK_WIDTH + rect->l) * lightmap_bytes;
446 for (i = rect->h; i > 0; i--) {
447 memcpy (b, lm, width);
448 b += width;
449 lm += stride;
450 }
451 qfglTexSubImage2D (GL_TEXTURE_2D, 0, rect->l, rect->t, rect->w, rect->h,
452 gl_lightmap_format, GL_UNSIGNED_BYTE, block);
453 }
454
455 static void
GL_UploadLightmap(int i)456 GL_UploadLightmap (int i)
457 {
458 switch (gl_lightmap_subimage->int_val) {
459 case 2:
460 do_subimage_2 (i);
461 break;
462 case 1:
463 qfglTexSubImage2D (GL_TEXTURE_2D, 0, 0, gl_lightmap_rectchange[i].t,
464 BLOCK_WIDTH, gl_lightmap_rectchange[i].h,
465 gl_lightmap_format, GL_UNSIGNED_BYTE,
466 lightmaps[i] + (gl_lightmap_rectchange[i].t *
467 BLOCK_WIDTH) * lightmap_bytes);
468 break;
469 default:
470 case 0:
471 qfglTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, BLOCK_WIDTH,
472 BLOCK_HEIGHT, 0, gl_lightmap_format, GL_UNSIGNED_BYTE,
473 lightmaps[i]);
474 break;
475 }
476 }
477
478 void
gl_R_CalcLightmaps(void)479 gl_R_CalcLightmaps (void)
480 {
481 int i;
482
483 for (i = 0; i < MAX_LIGHTMAPS; i++) {
484 if (!gl_lightmap_polys[i])
485 continue;
486 if (gl_lightmap_modified[i]) {
487 qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i);
488 GL_UploadLightmap (i);
489 gl_lightmap_modified[i] = false;
490 }
491 }
492 }
493
494 void
gl_R_BlendLightmaps(void)495 gl_R_BlendLightmaps (void)
496 {
497 float *v;
498 int i, j;
499 instsurf_t *sc;
500 glpoly_t *p;
501
502 qfglDepthMask (GL_FALSE); // don't bother writing Z
503 qfglBlendFunc (lm_src_blend, lm_dest_blend);
504
505 for (i = 0; i < MAX_LIGHTMAPS; i++) {
506 for (sc = gl_lightmap_polys[i]; sc; sc = sc->lm_chain) {
507 qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i);
508 if (sc->transform) {
509 qfglPushMatrix ();
510 qfglLoadMatrixf (sc->transform);
511 }
512 for (p = sc->surface->polys; p; p = p->next) {
513 qfglBegin (GL_POLYGON);
514 v = p->verts[0];
515 for (j = 0; j < p->numverts; j++, v += VERTEXSIZE) {
516 qfglTexCoord2fv (&v[5]);
517 qfglVertex3fv (v);
518 }
519 qfglEnd ();
520 }
521 if (sc->transform)
522 qfglPopMatrix ();
523 }
524 }
525
526 // Return to normal blending --KB
527 qfglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
528 qfglDepthMask (GL_TRUE); // back to normal Z buffering
529 }
530
531 void
gl_overbright_f(cvar_t * var)532 gl_overbright_f (cvar_t *var)
533 {
534 int num, i, j;
535 model_t *m;
536 msurface_t *fa;
537 entity_t *ent;
538
539 if (!var)
540 return;
541
542 if (var->int_val) {
543 if (!gl_combine_capable && gl_mtex_capable) {
544 Sys_Printf ("Warning: gl_overbright has no effect with "
545 "gl_multitexture enabled if you don't have "
546 "GL_COMBINE support in your driver.\n");
547 lm_src_blend = GL_ZERO;
548 lm_dest_blend = GL_SRC_COLOR;
549 lmshift = 7;
550 gl_rgb_scale = 1.0;
551 } else {
552 lm_src_blend = GL_DST_COLOR;
553 lm_dest_blend = GL_SRC_COLOR;
554
555 switch (var->int_val) {
556 case 2:
557 lmshift = 9;
558 gl_rgb_scale = 4.0;
559 break;
560 case 1:
561 lmshift = 8;
562 gl_rgb_scale = 2.0;
563 break;
564 default:
565 lmshift = 7;
566 gl_rgb_scale = 1.0;
567 break;
568 }
569 }
570 } else {
571 lm_src_blend = GL_ZERO;
572 lm_dest_blend = GL_SRC_COLOR;
573 lmshift = 7;
574 gl_rgb_scale = 1.0;
575 }
576
577 if (gl_multitexture)
578 gl_multitexture_f (gl_multitexture);
579
580 if (!gl_R_BuildLightMap)
581 return;
582
583 for (ent = r_ent_queue; ent; ent = ent->next) {
584 m = ent->model;
585
586 if (m->type != mod_brush)
587 continue;
588 if (m->name[0] == '*')
589 continue;
590
591 for (j = 0, fa = m->surfaces; j < m->numsurfaces; j++, fa++) {
592 if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
593 continue;
594
595 num = fa->lightmaptexturenum;
596 gl_lightmap_modified[num] = true;
597 gl_lightmap_rectchange[num].l = 0;
598 gl_lightmap_rectchange[num].t = 0;
599 gl_lightmap_rectchange[num].w = BLOCK_WIDTH;
600 gl_lightmap_rectchange[num].h = BLOCK_HEIGHT;
601
602 gl_R_BuildLightMap (fa);
603 }
604 }
605
606 m = r_worldentity.model;
607
608 for (i = 0, fa = m->surfaces; i < m->numsurfaces; i++, fa++) {
609 if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
610 continue;
611
612 num = fa->lightmaptexturenum;
613 gl_lightmap_modified[num] = true;
614 gl_lightmap_rectchange[num].l = 0;
615 gl_lightmap_rectchange[num].t = 0;
616 gl_lightmap_rectchange[num].w = BLOCK_WIDTH;
617 gl_lightmap_rectchange[num].h = BLOCK_HEIGHT;
618
619 gl_R_BuildLightMap (fa);
620 }
621 }
622
623 // LIGHTMAP ALLOCATION ========================================================
624
625 // returns a texture number and the position inside it
626 static int
AllocBlock(int w,int h,int * x,int * y)627 AllocBlock (int w, int h, int *x, int *y)
628 {
629 int best, best2, texnum, i, j;
630
631 for (texnum = 0; texnum < MAX_LIGHTMAPS; texnum++) {
632 best = BLOCK_HEIGHT;
633
634 for (i = 0; i < BLOCK_WIDTH - w; i++) {
635 best2 = 0;
636
637 for (j = 0; j < w; j++) {
638 if (allocated[texnum][i + j] >= best)
639 break;
640 if (allocated[texnum][i + j] > best2)
641 best2 = allocated[texnum][i + j];
642 }
643 if (j == w) {
644 // this is a valid spot
645 *x = i;
646 *y = best = best2;
647 }
648 }
649
650 if (best + h > BLOCK_HEIGHT)
651 continue;
652
653 // LordHavoc: allocate lightmaps only as needed
654 if (!lightmaps[texnum])
655 lightmaps[texnum] = calloc (BLOCK_WIDTH * BLOCK_HEIGHT,
656 lightmap_bytes);
657 for (i = 0; i < w; i++)
658 allocated[texnum][*x + i] = best + h;
659
660 return texnum;
661 }
662
663 Sys_Error ("AllocBlock: full");
664 return 0;
665 }
666
667 static void
GL_CreateSurfaceLightmap(msurface_t * surf)668 GL_CreateSurfaceLightmap (msurface_t *surf)
669 {
670 int smax, tmax;
671
672 if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
673 return;
674
675 smax = (surf->extents[0] >> 4) + 1;
676 tmax = (surf->extents[1] >> 4) + 1;
677
678 surf->lightmaptexturenum =
679 AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
680 gl_R_BuildLightMap (surf);
681 }
682
683 /*
684 GL_BuildLightmaps
685
686 Builds the lightmap texture with all the surfaces from all brush models
687 */
688 void
GL_BuildLightmaps(model_t ** models,int num_models)689 GL_BuildLightmaps (model_t **models, int num_models)
690 {
691 int i, j;
692 model_t *m;
693
694 memset (allocated, 0, sizeof (allocated));
695
696 r_framecount = 1; // no dlightcache
697
698 if (!gl_lightmap_textures) {
699 gl_lightmap_textures = gl_texture_number;
700 gl_texture_number += MAX_LIGHTMAPS;
701 }
702
703 switch (r_lightmap_components->int_val) {
704 case 1:
705 gl_internalformat = 1;
706 gl_lightmap_format = GL_LUMINANCE;
707 lightmap_bytes = 1;
708 gl_R_BuildLightMap = R_BuildLightMap_1;
709 break;
710 case 3:
711 gl_internalformat = 3;
712 if (gl_use_bgra)
713 gl_lightmap_format = GL_BGR;
714 else
715 gl_lightmap_format = GL_RGB;
716 lightmap_bytes = 3;
717 gl_R_BuildLightMap = R_BuildLightMap_3;
718 break;
719 case 4:
720 default:
721 gl_internalformat = 3;
722 if (gl_use_bgra)
723 gl_lightmap_format = GL_BGRA;
724 else
725 gl_lightmap_format = GL_RGBA;
726 lightmap_bytes = 4;
727 gl_R_BuildLightMap = R_BuildLightMap_4;
728 break;
729 }
730
731 for (j = 1; j < num_models; j++) {
732 m = models[j];
733 if (!m)
734 break;
735 if (m->name[0] == '*') {
736 // sub model surfaces are processed as part of the main model
737 continue;
738 }
739 r_pcurrentvertbase = m->vertexes;
740 gl_currentmodel = m;
741 // non-bsp models don't have surfaces.
742 for (i = 0; i < m->numsurfaces; i++) {
743 if (m->surfaces[i].flags & SURF_DRAWTURB)
744 continue;
745 if (gl_sky_divide->int_val && (m->surfaces[i].flags &
746 SURF_DRAWSKY))
747 continue;
748 GL_CreateSurfaceLightmap (m->surfaces + i);
749 GL_BuildSurfaceDisplayList (m->surfaces + i);
750 }
751 }
752
753 // upload all lightmaps that were filled
754 for (i = 0; i < MAX_LIGHTMAPS; i++) {
755 if (!allocated[i][0])
756 break; // no more used
757 gl_lightmap_modified[i] = false;
758 gl_lightmap_rectchange[i].l = BLOCK_WIDTH;
759 gl_lightmap_rectchange[i].t = BLOCK_HEIGHT;
760 gl_lightmap_rectchange[i].w = 0;
761 gl_lightmap_rectchange[i].h = 0;
762 qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i);
763 qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
764 qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
765 if (gl_Anisotropy)
766 qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
767 gl_aniso);
768 qfglTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes, BLOCK_WIDTH,
769 BLOCK_HEIGHT, 0, gl_lightmap_format,
770 GL_UNSIGNED_BYTE, lightmaps[i]);
771 }
772 }
773