Quake II RTX doxygen  1.0 dev
surf.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2003-2006 Andrey Nazarov
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 
19 /*
20  * gl_surf.c -- surface post-processing code
21  *
22  */
23 #include "gl.h"
24 
26 
27 /*
28 =============================================================================
29 
30 LIGHTMAP COLOR ADJUSTING
31 
32 =============================================================================
33 */
34 
35 static inline void
36 adjust_color_f(vec_t *out, const vec_t *in, float modulate)
37 {
38  float r, g, b, y, max;
39 
40  // add & modulate
41  r = (in[0] + lm.add) * modulate;
42  g = (in[1] + lm.add) * modulate;
43  b = (in[2] + lm.add) * modulate;
44 
45  // catch negative lights
46  if (r < 0) r = 0;
47  if (g < 0) g = 0;
48  if (b < 0) b = 0;
49 
50  // determine the brightest of the three color components
51  max = g;
52  if (r > max) {
53  max = r;
54  }
55  if (b > max) {
56  max = b;
57  }
58 
59  // rescale all the color components if the intensity of the greatest
60  // channel exceeds 1.0
61  if (max > 255) {
62  y = 255.0f / max;
63  r *= y;
64  g *= y;
65  b *= y;
66  }
67 
68  // transform to grayscale by replacing color components with
69  // overall pixel luminance computed from weighted color sum
70  if (lm.scale != 1) {
71  y = LUMINANCE(r, g, b);
72  r = y + (r - y) * lm.scale;
73  g = y + (g - y) * lm.scale;
74  b = y + (b - y) * lm.scale;
75  }
76 
77  out[0] = r;
78  out[1] = g;
79  out[2] = b;
80 }
81 
82 static inline void
83 adjust_color_ub(byte *out, const vec_t *in)
84 {
85  vec3_t tmp;
86 
87  adjust_color_f(tmp, in, lm.modulate);
88  out[0] = (byte)tmp[0];
89  out[1] = (byte)tmp[1];
90  out[2] = (byte)tmp[2];
91  out[3] = 255;
92 }
93 
94 void GL_AdjustColor(vec3_t color)
95 {
97  VectorScale(color, (1.0f / 255), color);
98 }
99 
100 /*
101 =============================================================================
102 
103 DYNAMIC BLOCKLIGHTS
104 
105 =============================================================================
106 */
107 
108 #define MAX_SURFACE_EXTENTS 2048
109 #define MAX_LIGHTMAP_EXTENTS ((MAX_SURFACE_EXTENTS >> 4) + 1)
110 #define MAX_BLOCKLIGHTS (MAX_LIGHTMAP_EXTENTS * MAX_LIGHTMAP_EXTENTS)
111 
112 static float blocklights[MAX_BLOCKLIGHTS * 3];
113 
114 #if USE_DLIGHTS
115 static void add_dynamic_lights(mface_t *surf)
116 {
117  dlight_t *light;
118  mtexinfo_t *tex;
119  vec3_t point;
120  int local[2];
121  vec_t dist, rad, minlight, scale, frac;
122  float *bl;
123  int i, smax, tmax, s, t, sd, td;
124 
125  smax = S_MAX(surf);
126  tmax = T_MAX(surf);
127  tex = surf->texinfo;
128 
129  for (i = 0; i < glr.fd.num_dlights; i++) {
130  if (!(surf->dlightbits & (1 << i)))
131  continue;
132 
133  light = &glr.fd.dlights[i];
134  dist = PlaneDiffFast(light->transformed, surf->plane);
135  rad = light->intensity - fabs(dist);
136  if (rad < DLIGHT_CUTOFF)
137  continue;
138 
139  if (gl_dlight_falloff->integer) {
140  minlight = rad - DLIGHT_CUTOFF * 0.8f;
141  scale = rad / minlight; // fall off from rad to 0
142  } else {
143  minlight = rad - DLIGHT_CUTOFF;
144  scale = 1; // fall off from rad to minlight
145  }
146 
147  VectorMA(light->transformed, -dist, surf->plane->normal, point);
148 
149  local[0] = DotProduct(point, tex->axis[0]) + tex->offset[0];
150  local[1] = DotProduct(point, tex->axis[1]) + tex->offset[1];
151 
152  local[0] -= surf->texturemins[0];
153  local[1] -= surf->texturemins[1];
154 
155  bl = blocklights;
156  for (t = 0; t < tmax; t++) {
157  td = abs(local[1] - (t << 4));
158  for (s = 0; s < smax; s++) {
159  sd = abs(local[0] - (s << 4));
160  if (sd > td)
161  dist = sd + (td >> 1);
162  else
163  dist = td + (sd >> 1);
164  if (dist < minlight) {
165  frac = rad - dist * scale;
166  bl[0] += light->color[0] * frac;
167  bl[1] += light->color[1] * frac;
168  bl[2] += light->color[2] * frac;
169  }
170  bl += 3;
171  }
172  }
173  }
174 }
175 #endif
176 
177 static void add_light_styles(mface_t *surf, int size)
178 {
179  lightstyle_t *style;
180  byte *src;
181  float *bl;
182  int i, j;
183 
184  if (!surf->numstyles) {
185  // should this ever happen?
186  memset(blocklights, 0, sizeof(blocklights[0]) * size * 3);
187  return;
188  }
189 
190  // init primary lightmap
191  style = LIGHT_STYLE(surf, 0);
192 
193  src = surf->lightmap;
194  bl = blocklights;
195  if (style->white == 1) {
196  for (j = 0; j < size; j++) {
197  bl[0] = src[0];
198  bl[1] = src[1];
199  bl[2] = src[2];
200 
201  bl += 3; src += 3;
202  }
203  } else {
204  for (j = 0; j < size; j++) {
205  bl[0] = src[0] * style->rgb[0];
206  bl[1] = src[1] * style->rgb[1];
207  bl[2] = src[2] * style->rgb[2];
208 
209  bl += 3; src += 3;
210  }
211  }
212 
213  surf->stylecache[0] = style->white;
214 
215  // add remaining lightmaps
216  for (i = 1; i < surf->numstyles; i++) {
217  style = LIGHT_STYLE(surf, i);
218 
219  bl = blocklights;
220  for (j = 0; j < size; j++) {
221  bl[0] += src[0] * style->rgb[0];
222  bl[1] += src[1] * style->rgb[1];
223  bl[2] += src[2] * style->rgb[2];
224 
225  bl += 3; src += 3;
226  }
227 
228  surf->stylecache[i] = style->white;
229  }
230 }
231 
232 static void update_dynamic_lightmap(mface_t *surf)
233 {
234  byte temp[MAX_BLOCKLIGHTS * 4], *dst;
235  int smax, tmax, size, i;
236  float *bl;
237 
238  smax = S_MAX(surf);
239  tmax = T_MAX(surf);
240  size = smax * tmax;
241 
242  // add all the lightmaps
243  add_light_styles(surf, size);
244 
245 #if USE_DLIGHTS
246  // add all the dynamic lights
247  if (surf->dlightframe == glr.dlightframe) {
248  add_dynamic_lights(surf);
249  } else {
250  surf->dlightframe = 0;
251  }
252 #endif
253 
254  // put into texture format
255  bl = blocklights;
256  dst = temp;
257  for (i = 0; i < size; i++) {
258  adjust_color_ub(dst, bl);
259  bl += 3; dst += 4;
260  }
261 
262  // upload lightmap subimage
263  GL_ForceTexture(1, surf->texnum[1]);
264  qglTexSubImage2D(GL_TEXTURE_2D, 0,
265  surf->light_s, surf->light_t, smax, tmax,
266  GL_RGBA, GL_UNSIGNED_BYTE, temp);
267 
268  c.texUploads++;
269 }
270 
271 void GL_PushLights(mface_t *surf)
272 {
273  lightstyle_t *style;
274  int i;
275 
276  if (!surf->lightmap) {
277  return;
278  }
279  if (surf->drawflags & SURF_NOLM_MASK) {
280  return;
281  }
282  if (!surf->texnum[1]) {
283  return;
284  }
285 
286 #if USE_DLIGHTS
287  // dynamic this frame or dynamic previously
288  if (surf->dlightframe) {
290  return;
291  }
292 #endif
293 
294  // check for light style updates
295  for (i = 0; i < surf->numstyles; i++) {
296  style = LIGHT_STYLE(surf, i);
297  if (style->white != surf->stylecache[i]) {
299  return;
300  }
301  }
302 }
303 
304 /*
305 =============================================================================
306 
307 LIGHTMAPS BUILDING
308 
309 =============================================================================
310 */
311 
312 #define LM_AllocBlock(w, h, s, t) \
313  GL_AllocBlock(LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, lm.inuse, w, h, s, t)
314 
315 static void LM_InitBlock(void)
316 {
317  int i;
318 
319  for (i = 0; i < LM_BLOCK_WIDTH; i++) {
320  lm.inuse[i] = 0;
321  }
322 
323  lm.dirty = qfalse;
324 }
325 
326 static void LM_UploadBlock(void)
327 {
328  if (!lm.dirty) {
329  return;
330  }
331 
333  qglTexImage2D(GL_TEXTURE_2D, 0, lm.comp, LM_BLOCK_WIDTH, LM_BLOCK_HEIGHT, 0,
334  GL_RGBA, GL_UNSIGNED_BYTE, lm.buffer);
335  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
336  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
337 }
338 
339 static void build_style_map(int dynamic)
340 {
341  static lightstyle_t fake;
342  int i;
343 
344  if (!dynamic) {
345  // make all styles fullbright
346  fake.rgb[0] = 1;
347  fake.rgb[1] = 1;
348  fake.rgb[2] = 1;
349  fake.white = 1;
350  glr.fd.lightstyles = &fake;
351 
352  memset(gl_static.lightstylemap, 0, sizeof(gl_static.lightstylemap));
353  return;
354  }
355 
356  for (i = 0; i < MAX_LIGHTSTYLES; i++) {
357  gl_static.lightstylemap[i] = i;
358  }
359 
360  if (dynamic != 1) {
361  // make dynamic styles fullbright
362  for (i = 1; i < 32; i++) {
363  gl_static.lightstylemap[i] = 0;
364  }
365  }
366 }
367 
368 static void LM_BeginBuilding(void)
369 {
370  // lightmap textures are not deleted from memory when changing maps,
371  // they are merely reused
372  lm.nummaps = 0;
373 
374  LM_InitBlock();
375 
376  // start up with fullbright styles
377  build_style_map(0);
378 }
379 
380 static void LM_EndBuilding(void)
381 {
382  // upload the last lightmap
383  LM_UploadBlock();
384  LM_InitBlock();
385 
386  // vertex lighting implies fullbright styles
387  if (gl_fullbright->integer || gl_vertexlight->integer)
388  return;
389 
390  // now build the real lightstyle map
391  build_style_map(gl_dynamic->integer);
392 
393  Com_DPrintf("%s: %d lightmaps built\n", __func__, lm.nummaps);
394 }
395 
396 static void build_primary_lightmap(mface_t *surf)
397 {
398  byte *ptr, *dst;
399  int smax, tmax, size, i, j;
400  float *bl;
401 
402  smax = S_MAX(surf);
403  tmax = T_MAX(surf);
404  size = smax * tmax;
405 
406  // add all the lightmaps
407  add_light_styles(surf, size);
408 
409 #if USE_DLIGHTS
410  surf->dlightframe = 0;
411 #endif
412 
413  // put into texture format
414  bl = blocklights;
415  dst = &lm.buffer[(surf->light_t * LM_BLOCK_WIDTH + surf->light_s) << 2];
416  for (i = 0; i < tmax; i++) {
417  ptr = dst;
418  for (j = 0; j < smax; j++) {
419  adjust_color_ub(ptr, bl);
420  bl += 3; ptr += 4;
421  }
422 
423  dst += LM_BLOCK_WIDTH * 4;
424  }
425 }
426 
427 static void LM_BuildSurface(mface_t *surf, vec_t *vbo)
428 {
429  int smax, tmax, s, t;
430 
431  smax = S_MAX(surf);
432  tmax = T_MAX(surf);
433 
434  if (!LM_AllocBlock(smax, tmax, &s, &t)) {
435  LM_UploadBlock();
436  if (lm.nummaps == LM_MAX_LIGHTMAPS) {
437  Com_EPrintf("%s: LM_MAX_LIGHTMAPS exceeded\n", __func__);
438  return;
439  }
440  LM_InitBlock();
441  if (!LM_AllocBlock(smax, tmax, &s, &t)) {
442  Com_EPrintf("%s: LM_AllocBlock(%d, %d) failed\n",
443  __func__, smax, tmax);
444  return;
445  }
446  }
447 
448  lm.dirty = qtrue;
449 
450  // store the surface lightmap parameters
451  surf->light_s = s;
452  surf->light_t = t;
453  surf->texnum[1] = lm.texnums[lm.nummaps];
454 
455  // build the primary lightmap
457 }
458 
459 static void LM_RebuildSurfaces(void)
460 {
461  bsp_t *bsp = gl_static.world.cache;
462  mface_t *surf;
463  int i, texnum;
464 
465  build_style_map(gl_dynamic->integer);
466 
467  if (!lm.nummaps) {
468  return;
469  }
470 
471  GL_ForceTexture(1, lm.texnums[0]);
472  texnum = lm.texnums[0];
473 
474  for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
475  if (!surf->lightmap) {
476  continue;
477  }
478  if (surf->drawflags & SURF_NOLM_MASK) {
479  continue;
480  }
481  if (!surf->texnum[1]) {
482  continue;
483  }
484 
485  if (surf->texnum[1] != texnum) {
486  // done with previous lightmap
487  qglTexImage2D(GL_TEXTURE_2D, 0, lm.comp,
489  GL_RGBA, GL_UNSIGNED_BYTE, lm.buffer);
490  GL_ForceTexture(1, surf->texnum[1]);
491  texnum = surf->texnum[1];
492 
493  c.texUploads++;
494  }
495 
497  }
498 
499  // upload the last lightmap
500  qglTexImage2D(GL_TEXTURE_2D, 0, lm.comp,
502  GL_RGBA, GL_UNSIGNED_BYTE, lm.buffer);
503 
504  c.texUploads++;
505 }
506 
507 
508 /*
509 =============================================================================
510 
511 POLYGONS BUILDING
512 
513 =============================================================================
514 */
515 
516 static uint32_t color_for_surface(mface_t *surf)
517 {
518  if (surf->drawflags & SURF_TRANS33)
520 
521  if (surf->drawflags & SURF_TRANS66)
523 
524  if (surf->drawflags & SURF_WARP)
526 
527  return U32_WHITE;
528 }
529 
530 static void build_surface_poly(mface_t *surf, vec_t *vbo)
531 {
532  msurfedge_t *src_surfedge;
533  mvertex_t *src_vert;
534  medge_t *src_edge;
535  mtexinfo_t *texinfo = surf->texinfo;
536  vec2_t scale, tc, mins, maxs;
537  int i, bmins[2], bmaxs[2];
538  uint32_t color;
539 
540  surf->texnum[0] = texinfo->image->texnum;
541  surf->texnum[1] = 0;
542 
543  color = color_for_surface(surf);
544 
545  // convert surface flags to state bits
546  surf->statebits = GLS_DEFAULT;
547  if (!(surf->drawflags & SURF_COLOR_MASK)) {
548  surf->statebits |= GLS_TEXTURE_REPLACE;
549  }
550 
551  if (surf->drawflags & SURF_WARP) {
552  surf->statebits |= GLS_WARP_ENABLE;
553  }
554 
555  if (surf->drawflags & SURF_TRANS_MASK) {
556  surf->statebits |= GLS_BLEND_BLEND | GLS_DEPTHMASK_FALSE;
557  } else if (surf->drawflags & SURF_ALPHATEST) {
558  surf->statebits |= GLS_ALPHATEST_ENABLE;
559  }
560 
561  if (surf->drawflags & SURF_FLOWING) {
562  surf->statebits |= GLS_FLOW_ENABLE;
563  }
564 
565  // normalize texture coordinates
566  scale[0] = 1.0f / texinfo->image->width;
567  scale[1] = 1.0f / texinfo->image->height;
568 
569  mins[0] = mins[1] = 99999;
570  maxs[0] = maxs[1] = -99999;
571 
572  src_surfedge = surf->firstsurfedge;
573  for (i = 0; i < surf->numsurfedges; i++) {
574  src_edge = src_surfedge->edge;
575  src_vert = src_edge->v[src_surfedge->vert];
576  src_surfedge++;
577 
578  // vertex coordinates
579  VectorCopy(src_vert->point, vbo);
580 
581  // vertex color
582  memcpy(vbo + 3, &color, sizeof(color));
583 
584  // texture0 coordinates
585  tc[0] = DotProduct(vbo, texinfo->axis[0]) + texinfo->offset[0];
586  tc[1] = DotProduct(vbo, texinfo->axis[1]) + texinfo->offset[1];
587 
588  if (mins[0] > tc[0]) mins[0] = tc[0];
589  if (maxs[0] < tc[0]) maxs[0] = tc[0];
590 
591  if (mins[1] > tc[1]) mins[1] = tc[1];
592  if (maxs[1] < tc[1]) maxs[1] = tc[1];
593 
594  vbo[4] = tc[0] * scale[0];
595  vbo[5] = tc[1] * scale[1];
596 
597  // texture1 coordinates
598  vbo[6] = tc[0];
599  vbo[7] = tc[1];
600 
601  vbo += VERTEX_SIZE;
602  }
603 
604  // calculate surface extents
605  bmins[0] = floor(mins[0] / 16);
606  bmins[1] = floor(mins[1] / 16);
607  bmaxs[0] = ceil(maxs[0] / 16);
608  bmaxs[1] = ceil(maxs[1] / 16);
609 
610  surf->texturemins[0] = bmins[0] << 4;
611  surf->texturemins[1] = bmins[1] << 4;
612 
613  surf->extents[0] = (bmaxs[0] - bmins[0]) << 4;
614  surf->extents[1] = (bmaxs[1] - bmins[1]) << 4;
615 }
616 
617 // vertex lighting approximation
618 static void sample_surface_verts(mface_t *surf, vec_t *vbo)
619 {
620  int i;
621  vec3_t color;
622 
623  glr.lightpoint.surf = surf;
624 
625  for (i = 0; i < surf->numsurfedges; i++) {
626  glr.lightpoint.s = (int)vbo[6] - surf->texturemins[0];
627  glr.lightpoint.t = (int)vbo[7] - surf->texturemins[1];
628 
630  adjust_color_ub((byte *)(vbo + 3), color);
631 
632  vbo += VERTEX_SIZE;
633  }
634 
635  surf->statebits &= ~GLS_TEXTURE_REPLACE;
636  surf->statebits |= GLS_SHADE_SMOOTH;
637 }
638 
639 // validates and processes surface lightmap
640 static void build_surface_light(mface_t *surf, vec_t *vbo)
641 {
642  int smax, tmax, size;
643  byte *src, *ptr;
644  bsp_t *bsp;
645 
646  if (gl_fullbright->integer)
647  return;
648 
649  if (!surf->lightmap)
650  return;
651 
652  if (surf->drawflags & SURF_NOLM_MASK)
653  return;
654 
655  // validate extents
656  if (surf->extents[0] < 0 || surf->extents[0] > MAX_SURFACE_EXTENTS ||
657  surf->extents[1] < 0 || surf->extents[1] > MAX_SURFACE_EXTENTS) {
658  Com_EPrintf("%s: bad surface extents\n", __func__);
659  surf->lightmap = NULL; // don't use this lightmap
660  return;
661  }
662 
663  // validate blocklights size
664  smax = S_MAX(surf);
665  tmax = T_MAX(surf);
666  size = smax * tmax;
667  if (size > MAX_BLOCKLIGHTS) {
668  Com_EPrintf("%s: MAX_BLOCKLIGHTS exceeded\n", __func__);
669  surf->lightmap = NULL; // don't use this lightmap
670  return;
671  }
672 
673  // validate lightmap bounds
674  bsp = gl_static.world.cache;
675  src = surf->lightmap + surf->numstyles * size * 3;
676  ptr = bsp->lightmap + bsp->numlightmapbytes;
677  if (src > ptr) {
678  Com_EPrintf("%s: bad surface lightmap\n", __func__);
679  surf->lightmap = NULL; // don't use this lightmap
680  return;
681  }
682 
683  if (gl_vertexlight->integer)
684  sample_surface_verts(surf, vbo);
685  else
686  LM_BuildSurface(surf, vbo);
687 }
688 
689 // normalizes and stores lightmap texture coordinates in vertices
690 static void normalize_surface_lmtc(mface_t *surf, vec_t *vbo)
691 {
692  float s, t;
693  int i;
694 
695  s = ((surf->light_s << 4) + 8) - surf->texturemins[0];
696  t = ((surf->light_t << 4) + 8) - surf->texturemins[1];
697 
698  for (i = 0; i < surf->numsurfedges; i++) {
699  vbo[6] += s;
700  vbo[7] += t;
701  vbo[6] *= 1.0f / (LM_BLOCK_WIDTH * 16);
702  vbo[7] *= 1.0f / (LM_BLOCK_HEIGHT * 16);
703 
704  vbo += VERTEX_SIZE;
705  }
706 }
707 
708 // duplicates normalized texture0 coordinates for non-lit surfaces in texture1
709 // to make them render properly when gl_lightmap hack is used
710 static void duplicate_surface_lmtc(mface_t *surf, vec_t *vbo)
711 {
712  int i;
713 
714  for (i = 0; i < surf->numsurfedges; i++) {
715  vbo[6] = vbo[4];
716  vbo[7] = vbo[5];
717 
718  vbo += VERTEX_SIZE;
719  }
720 }
721 
722 static qboolean create_surface_vbo(size_t size)
723 {
724  GLuint buf = 0;
725 
729  return qfalse;
730  }
731 
732  QGL_ClearErrors();
733 
734  qglGenBuffersARB(1, &buf);
735  qglBindBufferARB(GL_ARRAY_BUFFER_ARB, buf);
736  qglBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB);
737 
738  if (GL_ShowErrors("Failed to create world model VBO")) {
739  qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
740  qglDeleteBuffersARB(1, &buf);
741  return qfalse;
742  }
743 
744  gl_static.world.vertices = NULL;
745  gl_static.world.bufnum = buf;
746  return qtrue;
747 }
748 
749 static void upload_surface_vbo(int lastvert)
750 {
751  GLintptrARB offset = lastvert * VERTEX_SIZE * sizeof(vec_t);
752  GLsizeiptrARB size = tess.numverts * VERTEX_SIZE * sizeof(vec_t);
753 
754  Com_DDPrintf("%s: %"PRIz" bytes at %"PRIz"\n", __func__, size, offset);
755 
756  qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, size, tess.vertices);
757  tess.numverts = 0;
758 }
759 
760 static void upload_world_surfaces(void)
761 {
762  bsp_t *bsp = gl_static.world.cache;
763  vec_t *vbo;
764  mface_t *surf;
765  int i, currvert, lastvert;
766 
767  // force vertex lighting if multitexture is not supported
769  Cvar_Set("gl_vertexlight", "1");
770 
771  if (!gl_static.world.vertices)
772  qglBindBufferARB(GL_ARRAY_BUFFER_ARB, gl_static.world.bufnum);
773 
774  currvert = 0;
775  lastvert = 0;
776  for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
777  if (surf->drawflags & SURF_SKY)
778  continue;
779 
780  if (gl_static.world.vertices) {
781  vbo = gl_static.world.vertices + currvert * VERTEX_SIZE;
782  } else {
783  // upload VBO chunk if needed
784  if (tess.numverts + surf->numsurfedges > TESS_MAX_VERTICES) {
785  upload_surface_vbo(lastvert);
786  lastvert = currvert;
787  }
788 
790  tess.numverts += surf->numsurfedges;
791  }
792 
793  surf->firstvert = currvert;
794  build_surface_poly(surf, vbo);
795  build_surface_light(surf, vbo);
796 
797  if (surf->texnum[1])
798  normalize_surface_lmtc(surf, vbo);
799  else
800  duplicate_surface_lmtc(surf, vbo);
801 
802  currvert += surf->numsurfedges;
803  }
804 
805  // upload the last VBO chunk
806  if (!gl_static.world.vertices) {
807  upload_surface_vbo(lastvert);
808  qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
809  }
810 
811  gl_fullbright->modified = qfalse;
812  gl_vertexlight->modified = qfalse;
813 }
814 
815 static void set_world_size(void)
816 {
817  mnode_t *node = gl_static.world.cache->nodes;
818  vec_t size, temp;
819  int i;
820 
821  for (i = 0, size = 0; i < 3; i++) {
822  temp = node->maxs[i] - node->mins[i];
823  if (temp > size)
824  size = temp;
825  }
826 
827  if (size > 4096)
828  gl_static.world.size = 8192;
829  else if (size > 2048)
830  gl_static.world.size = 4096;
831  else
832  gl_static.world.size = 2048;
833 }
834 
835 // called from the main loop whenever lighting parameters change
837 {
838  if (!gl_static.world.cache)
839  return;
840 
841  // if doing vertex lighting, rebuild all surfaces
842  if (gl_fullbright->integer || gl_vertexlight->integer) {
844  return;
845  }
846 
847  // if did vertex lighting previously, rebuild all surfaces and lightmaps
848  if (gl_fullbright->modified || gl_vertexlight->modified) {
851  LM_EndBuilding();
852  return;
853  }
854 
855  // rebuild all lightmaps
857 }
858 
859 void GL_FreeWorld(void)
860 {
861  if (!gl_static.world.cache) {
862  return;
863  }
864 
866 
867  if (gl_static.world.vertices) {
869  } else if (qglDeleteBuffersARB) {
871  }
872 
873  memset(&gl_static.world, 0, sizeof(gl_static.world));
874 }
875 
876 void GL_LoadWorld(const char *name)
877 {
878  char buffer[MAX_QPATH];
879  size_t size;
880  bsp_t *bsp;
881  mtexinfo_t *info;
882  mface_t *surf;
883  qerror_t ret;
884  imageflags_t flags;
885  int i;
886 
887  ret = BSP_Load(name, &bsp);
888  if (!bsp) {
889  Com_Error(ERR_DROP, "%s: couldn't load %s: %s",
890  __func__, name, Q_ErrorString(ret));
891  }
892 
893  // check if the required world model was already loaded
894  if (gl_static.world.cache == bsp) {
895  for (i = 0; i < bsp->numtexinfo; i++) {
896  bsp->texinfo[i].image->registration_sequence = registration_sequence;
897  }
898  for (i = 0; i < bsp->numnodes; i++) {
899  bsp->nodes[i].visframe = 0;
900  }
901  for (i = 0; i < bsp->numleafs; i++) {
902  bsp->leafs[i].visframe = 0;
903  }
904  Com_DPrintf("%s: reused old world model\n", __func__);
905  bsp->refcount--;
906  return;
907  }
908 
909  // free previous model, if any
910  GL_FreeWorld();
911 
912  gl_static.world.cache = bsp;
913 
914  // calculate world size for far clip plane and sky box
915  set_world_size();
916 
917  // register all texinfo
918  for (i = 0, info = bsp->texinfo; i < bsp->numtexinfo; i++, info++) {
919  if (info->c.flags & SURF_WARP)
920  flags = IF_TURBULENT;
921  else
922  flags = IF_NONE;
923 
924  Q_concat(buffer, sizeof(buffer), "textures/", info->name, ".wal", NULL);
925  FS_NormalizePath(buffer, buffer);
926  info->image = IMG_Find(buffer, IT_WALL, flags);
927  }
928 
929  // calculate vertex buffer size in bytes
930  size = 0;
931  for (i = 0, surf = bsp->faces; i < bsp->numfaces; i++, surf++) {
932  // hack surface flags into drawflags for faster access
933  surf->drawflags |= surf->texinfo->c.flags & ~DSURF_PLANEBACK;
934 
935  // don't count sky surfaces
936  if (surf->drawflags & SURF_SKY)
937  continue;
938 
939  size += surf->numsurfedges * VERTEX_SIZE * sizeof(vec_t);
940  }
941 
942  // try VBO first, then allocate on hunk
943  if (create_surface_vbo(size)) {
944  Com_DPrintf("%s: %"PRIz" bytes of vertex data as VBO\n", __func__, size);
945  } else {
946  Hunk_Begin(&gl_static.world.hunk, size);
949 
950  Com_DPrintf("%s: %"PRIz" bytes of vertex data on hunk\n", __func__, size);
951  }
952 
953  // begin building lightmaps
955 
956  // post process all surfaces
958 
959  // end building lightmaps
960  LM_EndBuilding();
961 
962  GL_ShowErrors(__func__);
963 }
964 
GLS_SHADE_SMOOTH
@ GLS_SHADE_SMOOTH
Definition: gl.h:294
gl_fullbright
cvar_t * gl_fullbright
Definition: main.c:79
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
qglTexParameterf
#define qglTexParameterf
Definition: fixed.h:108
glStatic_t::entity_modulate
float entity_modulate
Definition: gl.h:71
qglClientActiveTextureARB
PFNGLCLIENTACTIVETEXTUREARBPROC qglClientActiveTextureARB
Definition: fixed.c:39
sample_surface_verts
static void sample_surface_verts(mface_t *surf, vec_t *vbo)
Definition: surf.c:618
qglBufferSubDataARB
PFNGLBUFFERSUBDATAARBPROC qglBufferSubDataARB
Definition: fixed.c:46
LM_RebuildSurfaces
static void LM_RebuildSurfaces(void)
Definition: surf.c:459
lightmap_builder_t::comp
int comp
Definition: gl.h:262
lm
lightmap_builder_t lm
Definition: surf.c:25
Hunk_Begin
void Hunk_Begin(memhunk_t *hunk, size_t maxsize)
Definition: hunk.c:23
GL_AdjustColor
void GL_AdjustColor(vec3_t color)
Definition: surf.c:94
glStatic_t::cache
bsp_t * cache
Definition: gl.h:62
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
adjust_color_f
static void adjust_color_f(vec_t *out, const vec_t *in, float modulate)
Definition: surf.c:36
normalize_surface_lmtc
static void normalize_surface_lmtc(mface_t *surf, vec_t *vbo)
Definition: surf.c:690
Hunk_Alloc
void * Hunk_Alloc(memhunk_t *hunk, size_t size)
Definition: hunk.c:38
glStatic_t::lightstylemap
byte lightstylemap[MAX_LIGHTSTYLES]
Definition: gl.h:77
glStatic_t::hunk
memhunk_t hunk
Definition: gl.h:63
glStatic_t::size
vec_t size
Definition: gl.h:66
lightmap_builder_t::scale
float scale
Definition: gl.h:263
GLS_TEXTURE_REPLACE
@ GLS_TEXTURE_REPLACE
Definition: gl.h:289
LM_BLOCK_HEIGHT
#define LM_BLOCK_HEIGHT
Definition: gl.h:256
create_surface_vbo
static qboolean create_surface_vbo(size_t size)
Definition: surf.c:722
lightmap_builder_t::buffer
byte buffer[LM_BLOCK_WIDTH *LM_BLOCK_HEIGHT *4]
Definition: gl.h:260
GL_FreeWorld
void GL_FreeWorld(void)
Definition: surf.c:859
GL_LoadWorld
void GL_LoadWorld(const char *name)
Definition: surf.c:876
GLS_WARP_ENABLE
@ GLS_WARP_ENABLE
Definition: gl.h:292
GLS_BLEND_BLEND
@ GLS_BLEND_BLEND
Definition: gl.h:285
qglDeleteBuffersARB
PFNGLDELETEBUFFERSARBPROC qglDeleteBuffersARB
Definition: fixed.c:43
lightmap_builder_t::inuse
int inuse[LM_BLOCK_WIDTH]
Definition: gl.h:259
gl_vertexlight
cvar_t * gl_vertexlight
Definition: main.c:80
glStatic_t::inverse_intensity_100
uint32_t inverse_intensity_100
Definition: gl.h:74
blocklights
static float blocklights[MAX_BLOCKLIGHTS *3]
Definition: surf.c:112
Hunk_Free
void Hunk_Free(memhunk_t *hunk)
Definition: hunk.c:75
qglBufferDataARB
PFNGLBUFFERDATAARBPROC qglBufferDataARB
Definition: fixed.c:45
statCounters_t::texUploads
int texUploads
Definition: gl.h:141
TESS_MAX_VERTICES
#define TESS_MAX_VERTICES
Definition: gl.h:459
GLS_FLOW_ENABLE
@ GLS_FLOW_ENABLE
Definition: gl.h:290
LM_EndBuilding
static void LM_EndBuilding(void)
Definition: surf.c:380
VERTEX_SIZE
#define VERTEX_SIZE
Definition: gl.h:245
qglGenBuffersARB
PFNGLGENBUFFERSARBPROC qglGenBuffersARB
Definition: fixed.c:44
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
BSP_Free
void BSP_Free(bsp_t *bsp)
Definition: bsp.c:932
QGL_ClearErrors
void QGL_ClearErrors(void)
Definition: main.c:531
build_surface_poly
static void build_surface_poly(mface_t *surf, vec_t *vbo)
Definition: surf.c:530
qglTexImage2D
#define qglTexImage2D
Definition: fixed.h:107
glStatic_t::world
struct glStatic_t::@11 world
GL_PushLights
void GL_PushLights(mface_t *surf)
Definition: surf.c:271
MAX_SURFACE_EXTENTS
#define MAX_SURFACE_EXTENTS
Definition: surf.c:108
color_for_surface
static uint32_t color_for_surface(mface_t *surf)
Definition: surf.c:516
Hunk_End
void Hunk_End(memhunk_t *hunk)
Definition: hunk.c:66
GL_SampleLightPoint
void GL_SampleLightPoint(vec3_t color)
Definition: world.c:21
add_light_styles
static void add_light_styles(mface_t *surf, int size)
Definition: surf.c:177
GL_RebuildLighting
void GL_RebuildLighting(void)
Definition: surf.c:836
glRefdef_t::lightpoint
lightpoint_t lightpoint
Definition: gl.h:96
lightmap_builder_t::dirty
qboolean dirty
Definition: gl.h:261
LM_InitBlock
static void LM_InitBlock(void)
Definition: surf.c:315
build_surface_light
static void build_surface_light(mface_t *surf, vec_t *vbo)
Definition: surf.c:640
GLS_DEFAULT
@ GLS_DEFAULT
Definition: gl.h:282
upload_world_surfaces
static void upload_world_surfaces(void)
Definition: surf.c:760
adjust_color_ub
static void adjust_color_ub(byte *out, const vec_t *in)
Definition: surf.c:83
qglActiveTextureARB
PFNGLACTIVETEXTUREARBPROC qglActiveTextureARB
Definition: fixed.c:38
GL_ForceTexture
void GL_ForceTexture(GLuint tmu, GLuint texnum)
Definition: state.c:25
IMG_Find
image_t * IMG_Find(const char *name, imagetype_t type, imageflags_t flags)
Definition: images.c:1122
gl_static
glStatic_t gl_static
Definition: main.c:28
lightmap_builder_t
Definition: gl.h:258
c
statCounters_t c
Definition: main.c:30
LM_UploadBlock
static void LM_UploadBlock(void)
Definition: surf.c:326
lightmap_builder_t::nummaps
int nummaps
Definition: gl.h:264
LM_MAX_LIGHTMAPS
#define LM_MAX_LIGHTMAPS
Definition: gl.h:254
gl_dynamic
cvar_t * gl_dynamic
Definition: main.c:46
glr
glRefdef_t glr
Definition: main.c:27
lightmap_builder_t::modulate
float modulate
Definition: gl.h:263
LM_AllocBlock
#define LM_AllocBlock(w, h, s, t)
Definition: surf.c:312
registration_sequence
int registration_sequence
Definition: main.c:34
tess
tesselator_t tess
Definition: tess.c:21
LM_BeginBuilding
static void LM_BeginBuilding(void)
Definition: surf.c:368
build_style_map
static void build_style_map(int dynamic)
Definition: surf.c:339
upload_surface_vbo
static void upload_surface_vbo(int lastvert)
Definition: surf.c:749
qglBindBufferARB
PFNGLBINDBUFFERARBPROC qglBindBufferARB
Definition: fixed.c:42
glStatic_t::inverse_intensity_33
uint32_t inverse_intensity_33
Definition: gl.h:72
LIGHT_STYLE
#define LIGHT_STYLE(surf, i)
Definition: gl.h:251
lightmap_builder_t::add
float add
Definition: gl.h:263
lightmap_builder_t::texnums
GLuint texnums[LM_MAX_LIGHTMAPS]
Definition: gl.h:265
gl.h
BSP_Load
qerror_t BSP_Load(const char *name, bsp_t **bsp_p)
Definition: bsp.c:1087
update_dynamic_lightmap
static void update_dynamic_lightmap(mface_t *surf)
Definition: surf.c:232
GLS_ALPHATEST_ENABLE
@ GLS_ALPHATEST_ENABLE
Definition: gl.h:288
color
static vec4_t color
Definition: mesh.c:33
glStatic_t::bufnum
GLuint bufnum
Definition: gl.h:65
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
tesselator_t::vertices
GLfloat vertices[VERTEX_SIZE *TESS_MAX_VERTICES]
Definition: gl.h:463
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
GLS_DEPTHMASK_FALSE
@ GLS_DEPTHMASK_FALSE
Definition: gl.h:283
LM_BLOCK_WIDTH
#define LM_BLOCK_WIDTH
Definition: gl.h:255
build_primary_lightmap
static void build_primary_lightmap(mface_t *surf)
Definition: surf.c:396
duplicate_surface_lmtc
static void duplicate_surface_lmtc(mface_t *surf, vec_t *vbo)
Definition: surf.c:710
glStatic_t::vertices
vec_t * vertices
Definition: gl.h:64
glStatic_t::inverse_intensity_66
uint32_t inverse_intensity_66
Definition: gl.h:73
qglTexSubImage2D
#define qglTexSubImage2D
Definition: fixed.h:110
MAX_BLOCKLIGHTS
#define MAX_BLOCKLIGHTS
Definition: surf.c:110
GL_ShowErrors
qboolean GL_ShowErrors(const char *func)
Definition: main.c:539
FS_NormalizePath
size_t FS_NormalizePath(char *out, const char *in)
Definition: files.c:331
glRefdef_t::fd
refdef_t fd
Definition: gl.h:81
tesselator_t::numverts
int numverts
Definition: gl.h:467
set_world_size
static void set_world_size(void)
Definition: surf.c:815
LM_BuildSurface
static void LM_BuildSurface(mface_t *surf, vec_t *vbo)
Definition: surf.c:427