UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_lightmap.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 1997-2001 Id Software, Inc.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25 */
26 
27 #include "r_local.h"
28 #include "r_error.h"
29 #include "r_entity.h"
30 #include "r_lightmap.h"
31 
33 
34 static void R_UploadLightmapPage (void)
35 {
36 #ifdef GL_VERSION_ES_CM_1_0
37  const int texFormat = GL_RGB;
38 #else
40 #endif
41  GLuint texid;
42  if (r_lightmaps.lightmap_count >= MAX_GL_LIGHTMAPS) {
43  Com_Printf("R_UploadLightmapPage: MAX_GL_LIGHTMAPS reached.\n");
44  return;
45  }
46 
47  if (!r_lightmaps.incomplete_atlas) {
48  glGenTextures(1, &texid);
49  r_lightmaps.lightmap_texnums[r_lightmaps.lightmap_count++] = texid;
50  } else {
51  texid = r_lightmaps.lightmap_texnums[r_lightmaps.lightmap_count];
52  }
53 
54  R_BindTexture(texid);
55 
56  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
57  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
58 
59  glTexImage2D(GL_TEXTURE_2D, 0, texFormat, r_lightmaps.size, r_lightmaps.size,
60  0, GL_RGB, GL_UNSIGNED_BYTE, r_lightmaps.sample_buffer);
61 
62  R_CheckError();
63 
64  if (r_lightmaps.deluxemap_count >= MAX_GL_DELUXEMAPS) {
65  Com_Printf("R_UploadLightmapPage: MAX_GL_DELUXEMAPS reached.\n");
66  return;
67  }
68 
69  if (!r_lightmaps.incomplete_atlas) {
70  glGenTextures(1, &texid);
71  r_lightmaps.deluxemap_texnums[r_lightmaps.deluxemap_count++] = texid;
72  } else {
73  texid = r_lightmaps.deluxemap_texnums[r_lightmaps.deluxemap_count];
74  }
75 
76  R_BindTexture(texid);
77 
78  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
79  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
80 
81  glTexImage2D(GL_TEXTURE_2D, 0, texFormat, r_lightmaps.size, r_lightmaps.size,
82  0, GL_RGB, GL_UNSIGNED_BYTE, r_lightmaps.direction_buffer);
83 
84  /* clear the allocation heightmap and buffers */
85  memset(r_lightmaps.allocated, 0, r_lightmaps.size * sizeof(unsigned));
86  memset(r_lightmaps.sample_buffer, 0, r_lightmaps.size * r_lightmaps.size * LIGHTMAP_SAMPLE_SIZE);
87  memset(r_lightmaps.direction_buffer, 0, r_lightmaps.size * r_lightmaps.size * DELUXEMAP_SAMPLE_SIZE);
88 
89  r_lightmaps.incomplete_atlas = false;
90 }
91 
96 static bool R_AllocLightmapBlock (int w, int h, int* x, int* y)
97 {
98  if (!r_lightmaps.incomplete_atlas) {
99  r_lightmaps.incomplete_atlas = true;
100  glGenTextures(1, &r_lightmaps.lightmap_texnums[++r_lightmaps.lightmap_count]);
101  glGenTextures(1, &r_lightmaps.deluxemap_texnums[++r_lightmaps.deluxemap_count]);
102  }
103 
104  /* the height to store the data in the atlas */
105  int best = r_lightmaps.size;
106 
107  int i;
108  for (i = 0; i < r_lightmaps.size - w; i++) {
109  int best2 = 0;
110  int j;
111 
112  for (j = 0; j < w; j++) {
113  if (r_lightmaps.allocated[i + j] >= best)
114  break;
115  if (r_lightmaps.allocated[i + j] > best2)
116  best2 = r_lightmaps.allocated[i + j];
117  }
118  /* this is a valid spot */
119  if (j == w) {
120  *x = i;
121  *y = best = best2;
122  }
123  }
124 
125  if (best + h > r_lightmaps.size)
126  return false;
127 
128  for (i = 0; i < w; i++)
129  r_lightmaps.allocated[*x + i] = best + h;
130 
131  return true;
132 }
133 
138 static void R_BuildDefaultLightmap (mBspSurface_t* surf, byte* sout, byte* dout, int stride)
139 {
140  const int smax = (surf->stextents[0] / surf->lightmap_scale) + 1;
141  const int tmax = (surf->stextents[1] / surf->lightmap_scale) + 1;
142 
143  /* Allocatate attached-to-surface cache for fast point lighting lookups */
145 
146  for (int t = 0; t < tmax; t++) {
147  byte* lmPtr = sout, *dmPtr = dout;
148  for (int s = 0; s < smax; s++) {
149  /* fill lightmap samples */
150  l[0] = lmPtr[0] = 255;
151  l[1] = lmPtr[1] = 255;
152  l[2] = lmPtr[2] = 255;
153  /* fill deluxemap samples */
154  dmPtr[0] = 127;
155  dmPtr[1] = 127;
156  dmPtr[2] = 255;
157  /* advance pointers */
158  lmPtr += LIGHTMAP_SAMPLE_SIZE;
159  dmPtr += DELUXEMAP_SAMPLE_SIZE;
161  }
162  sout += stride * LIGHTMAP_SAMPLE_SIZE;
163  dout += stride * DELUXEMAP_SAMPLE_SIZE;
164  }
165 
166  Vector4Set(surf->lightColor, 1.0, 1.0, 1.0, 1.0);
167 }
168 
174 static void R_BuildLightmap (mBspSurface_t* surf, byte* sout, byte* dout, int stride)
175 {
176  const int smax = (surf->stextents[0] / surf->lightmap_scale) + 1;
177  const int tmax = (surf->stextents[1] / surf->lightmap_scale) + 1;
178  const int area = smax * tmax;
179 
180  int color[3] = {0, 0, 0};
181  byte* src = surf->samples;
182 
183  /* Allocatate attached-to-surface cache for fast point lighting lookups and keep the pointer to fill it a bit later */
185 
186  for (int t = 0; t < tmax; t++) {
187  byte* lmPtr = sout, *dmPtr = dout;
188  for (int s = 0; s < smax; s++) {
189  /* process lightmap samples and accumulate the average color */
190  color[0] += l[0] = lmPtr[0] = src[0];
191  color[1] += l[1] = lmPtr[1] = src[1];
192  color[2] += l[2] = lmPtr[2] = src[2];
193  /* process deluxemap samples */
194  dmPtr[0] = src[3];
195  dmPtr[1] = src[4];
196  dmPtr[2] = src[5];
197  /* advance pointers */
198  lmPtr += LIGHTMAP_SAMPLE_SIZE;
199  dmPtr += DELUXEMAP_SAMPLE_SIZE;
201  src += 6;
202  }
203  sout += stride * LIGHTMAP_SAMPLE_SIZE;
204  dout += stride * DELUXEMAP_SAMPLE_SIZE;
205  }
206 
207  /* store average lightmap color and surface alpha */
208  surf->lightColor[0] = color[0] / (255.0 * area);
209  surf->lightColor[1] = color[1] / (255.0 * area);
210  surf->lightColor[2] = color[2] / (255.0 * area);
211 
212  if (surf->texinfo->flags & (SURF_BLEND33 | SURF_ALPHATEST))
213  surf->lightColor[3] = 0.25;
214  else if (surf->texinfo->flags & SURF_BLEND66)
215  surf->lightColor[3] = 0.50;
216  else
217  surf->lightColor[3] = 1.0;
218 }
219 
224 {
225  int smax, tmax;
226  byte* samples, *directions;
227 
228  if (!(surf->flags & MSURF_LIGHTMAP))
229  return;
230 
231  smax = (surf->stextents[0] / surf->lightmap_scale) + 1;
232  tmax = (surf->stextents[1] / surf->lightmap_scale) + 1;
233 
234  if (!R_AllocLightmapBlock(smax, tmax, &surf->light_s, &surf->light_t)) {
235  /* upload the last page */
237  if (!R_AllocLightmapBlock(smax, tmax, &surf->light_s, &surf->light_t))
238  Com_Error(ERR_DROP, "R_CreateSurfaceLightmap: Consecutive calls to R_AllocLightmapBlock(%d,%d) failed (lightmap_scale: %i, stextents: %f %f)\n",
239  smax, tmax, surf->lightmap_scale, surf->stextents[0], surf->stextents[1]);
240  }
241 
242  surf->lightmap_texnum = r_lightmaps.lightmap_texnums[r_lightmaps.lightmap_count];
243  surf->deluxemap_texnum = r_lightmaps.deluxemap_texnums[r_lightmaps.deluxemap_count];
244 
245  samples = r_lightmaps.sample_buffer;
246  samples += (surf->light_t* r_lightmaps.size + surf->light_s) * LIGHTMAP_SAMPLE_SIZE;
247 
248  directions = r_lightmaps.direction_buffer;
249  directions += (surf->light_t* r_lightmaps.size + surf->light_s) * DELUXEMAP_SAMPLE_SIZE;
250 
251  if (!surf->samples) /* make it fullbright */
252  R_BuildDefaultLightmap(surf, samples, directions, r_lightmaps.size);
253  else /* or light it properly */
254  R_BuildLightmap(surf, samples, directions, r_lightmaps.size);
255 }
256 
257 static void R_DisposeLightmaps (void)
258 {
259  if (r_lightmaps.lightmap_count) {
260  glDeleteTextures(r_lightmaps.lightmap_count, r_lightmaps.lightmap_texnums);
261  r_lightmaps.lightmap_count = 0;
262  }
263  if (r_lightmaps.deluxemap_count) {
264  glDeleteTextures(r_lightmaps.deluxemap_count, r_lightmaps.deluxemap_texnums);
265  r_lightmaps.deluxemap_count = 0;
266  }
267 }
268 
274 {
275  static bool gotAllocatedLightmaps = false;
276 
277  if (gotAllocatedLightmaps)
279 
280  gotAllocatedLightmaps = true;
281 
282  /* users can tune lightmap size for their card */
283  r_lightmaps.size = r_maxlightmap->integer;
284 
285  r_lightmaps.allocated = Mem_PoolAllocTypeN(unsigned, r_lightmaps.size, vid_lightPool);
286  r_lightmaps.sample_buffer = Mem_PoolAllocTypeN(byte, r_lightmaps.size * r_lightmaps.size * LIGHTMAP_SAMPLE_SIZE, vid_lightPool);
287  r_lightmaps.direction_buffer = Mem_PoolAllocTypeN(byte, r_lightmaps.size * r_lightmaps.size * DELUXEMAP_SAMPLE_SIZE, vid_lightPool);
288 
289  r_lightmaps.lightmap_count = 0;
290  r_lightmaps.deluxemap_count = 0;
291  r_lightmaps.incomplete_atlas = false;
292 }
293 
299 {
300  /* upload the pending lightmap page */
302  Mem_Free(r_lightmaps.allocated);
303  Mem_Free(r_lightmaps.sample_buffer);
304  Mem_Free(r_lightmaps.direction_buffer);
305  r_lightmaps.allocated = nullptr;
306  r_lightmaps.sample_buffer = nullptr;
307  r_lightmaps.direction_buffer = nullptr;
308 }
309 
310 
317 void R_Trace (const Line& trLine, float size, int contentmask)
318 {
319  r_locals.tracenum++;
320 
321  if (r_locals.tracenum > 0xffff) /* avoid overflows */
322  r_locals.tracenum = 0;
323 
324  AABB box;
325  box.expand(size);
326 
327  refdef.trace = CM_CompleteBoxTrace(refdef.mapTiles, trLine, box, TRACE_ALL_LEVELS, contentmask, 0);
328  refdef.traceEntity = nullptr;
329 
330  float frac = refdef.trace.fraction;
331 
332  /* check bsp models */
333  for (int i = 0; i < refdef.numEntities; i++) {
334  entity_t* ent = R_GetEntity(i);
335  const model_t* m = ent->model;
336 
337  if (!m || m->type != mod_bsp_submodel)
338  continue;
339 
341  contentmask, 0, ent->origin, ent->angles);
342 
343  if (tr.fraction < frac) {
344  refdef.trace = tr;
345  refdef.traceEntity = ent;
346 
347  frac = tr.fraction;
348  }
349  }
350 
351  assert(refdef.trace.mapTile >= 0);
352  assert(refdef.trace.mapTile < r_numMapTiles);
353 }
static void R_UploadLightmapPage(void)
Definition: r_lightmap.cpp:34
int gl_solid_format
Definition: r_local.h:189
#define CM_TransformedBoxTrace(tile, line, box, headnode, brushmask, brushreject, origin, angles)
Definition: cmodel.h:48
entity_t * R_GetEntity(int id)
Returns a specific entity from the list.
Definition: r_entity.cpp:694
cvar_t * r_maxlightmap
Definition: r_main.cpp:101
#define DELUXEMAP_SAMPLE_SIZE
Definition: r_lightmap.h:34
GLuint deluxemap_texnums[MAX_GL_DELUXEMAPS]
Definition: r_lightmap.h:44
vec3_t origin
Definition: bspfile.h:47
struct entity_s * traceEntity
Definition: cl_renderer.h:201
#define MAX_GL_LIGHTMAPS
Definition: r_image.h:77
vec2_t stextents
Definition: r_model_brush.h:97
#define SURF_ALPHATEST
Definition: defines.h:268
#define TRACE_ALL_LEVELS
Definition: tracing.h:52
Definition: aabb.h:42
void R_EndBuildingLightmaps(void)
Definition: r_lightmap.cpp:298
byte * direction_buffer
Definition: r_lightmap.h:56
int tracenum
Definition: r_local.h:110
local graphics definitions
byte * sample_buffer
Definition: r_lightmap.h:55
bool incomplete_atlas
Definition: r_lightmap.h:49
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
rconfig_t r_config
Definition: r_main.cpp:47
GLuint lightmap_texnums[MAX_GL_LIGHTMAPS]
Definition: r_lightmap.h:43
void R_CreateSurfaceLightmap(mBspSurface_t *surf)
Definition: r_lightmap.cpp:223
QGL_EXTERN GLuint
Definition: r_gl.h:124
int integer
Definition: cvar.h:81
unsigned * allocated
Definition: r_lightmap.h:53
int r_numMapTiles
Definition: r_model.cpp:33
float fraction
Definition: tracing.h:58
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
void expand(const float byVal)
expand the box in all directions, but clip them to the maximum boundaries
Definition: aabb.h:240
#define MAX_GL_DELUXEMAPS
Definition: r_image.h:78
lightmap definitions
#define SURF_BLEND33
Definition: defines.h:257
#define ERR_DROP
Definition: common.h:211
GLsizei size
Definition: r_gl.h:152
rendererData_t refdef
Definition: r_main.cpp:45
#define Vector4Set(v, r, g, b, a)
Definition: vector.h:62
rlocals_t r_locals
Definition: r_main.cpp:49
modtype_t type
Definition: r_model.h:46
mBspTexInfo_t * texinfo
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels)
Definition: gldummy.cpp:17
static transfer_t tr
Definition: line.h:31
memPool_t * vid_lightPool
Definition: cl_main.cpp:89
QGL_EXTERN GLint GLenum GLboolean GLsizei stride
Definition: r_gl.h:94
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
void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
Definition: gldummy.cpp:13
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
static void R_DisposeLightmaps(void)
Definition: r_lightmap.cpp:257
lightmaps_t r_lightmaps
Definition: r_lightmap.cpp:32
uint32_t flags
Definition: r_model_brush.h:70
TR_TILE_TYPE mapTiles[MAX_MAPTILES]
Definition: tracing.h:79
static void R_BuildDefaultLightmap(mBspSurface_t *surf, byte *sout, byte *dout, int stride)
Fullbridght lightmap.
Definition: r_lightmap.cpp:138
QGL_EXTERN GLint i
Definition: r_gl.h:113
int mapTile
Definition: tracing.h:65
static void R_BuildLightmap(mBspSurface_t *surf, byte *sout, byte *dout, int stride)
Consume raw lightmap and deluxemap RGB/XYZ data from the surface samples, and write them into the str...
Definition: r_lightmap.cpp:174
#define Mem_Free(ptr)
Definition: mem.h:35
Error checking function.
void glGenTextures(GLsizei n, GLuint *textures)
Definition: gldummy.cpp:22
#define R_CheckError()
Definition: r_error.h:30
int deluxemap_count
Definition: r_lightmap.h:47
#define SURF_BLEND66
Definition: defines.h:258
void R_BeginBuildingLightmaps(void)
Definition: r_lightmap.cpp:273
uint8_t byte
Definition: ufotypes.h:34
static struct mdfour * m
Definition: md4.cpp:35
mapTiles_t * mapTiles
Definition: cl_renderer.h:203
int lightmap_count
Definition: r_lightmap.h:46
#define R_BindTexture(tn)
Definition: r_state.h:184
trace_t CM_CompleteBoxTrace(mapTiles_t *mapTiles, const Line &trLine, const AABB &box, int levelmask, int brushmask, int brushreject)
Traces all submodels in all tiles. Used by ufo and ufo_ded.
Definition: cmodel.cpp:283
#define LIGHTMAP_SAMPLE_SIZE
Definition: r_lightmap.h:33
int gl_compressed_solid_format
Definition: r_local.h:192
#define MSURF_LIGHTMAP
Definition: r_model_brush.h:51
static bool R_AllocLightmapBlock(int w, int h, int *x, int *y)
returns a texture number and the position inside it
Definition: r_lightmap.cpp:96
mBspModel_t bsp
Definition: r_model.h:60