UFO: Alien Invasion
Loading...
Searching...
No Matches
r_lightmap.cpp
Go to the documentation of this file.
1
6
7/*
8Copyright (C) 1997-2001 Id Software, Inc.
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
19See the GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, 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
34static void R_UploadLightmapPage (void)
35{
36#ifdef GL_VERSION_ES_CM_1_0
37 const int texFormat = GL_RGB;
38#else
39 const int texFormat = r_config.gl_compressed_solid_format ? r_config.gl_compressed_solid_format : r_config.gl_solid_format;
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
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
96static 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
138static 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 */
144 byte* l = surf->lightmap = Mem_PoolAllocTypeN(byte, smax * tmax * LIGHTMAP_SAMPLE_SIZE, vid_lightPool);
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 }
164 }
165
166 Vector4Set(surf->lightColor, 1.0, 1.0, 1.0, 1.0);
167}
168
174static 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 */
184 byte* l = surf->lightmap = Mem_PoolAllocTypeN(byte, area * LIGHTMAP_SAMPLE_SIZE, vid_lightPool);
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 }
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
257static 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);
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
317void 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
340 trace_t tr = CM_TransformedBoxTrace(refdef.mapTiles->mapTiles[m->bsp.maptile], trLine, box, m->bsp.firstnode,
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}
memPool_t * vid_lightPool
Definition cl_main.cpp:89
rendererData_t refdef
Definition r_main.cpp:45
Definition aabb.h:42
void expand(const float byVal)
expand the box in all directions, but clip them to the maximum boundaries
Definition aabb.h:240
Definition line.h:31
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 CM_TransformedBoxTrace(tile, line, box, headnode, brushmask, brushreject, origin, angles)
Definition cmodel.h:48
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define ERR_DROP
Definition common.h:211
static transfer_t tr
#define SURF_ALPHATEST
Definition defines.h:268
#define SURF_BLEND66
Definition defines.h:258
#define SURF_BLEND33
Definition defines.h:257
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
void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
Definition gldummy.cpp:13
void glGenTextures(GLsizei n, GLuint *textures)
Definition gldummy.cpp:22
voidpf void uLong size
Definition ioapi.h:42
static struct mdfour * m
Definition md4.cpp:35
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_Free(ptr)
Definition mem.h:35
entity_t * R_GetEntity(int id)
Returns a specific entity from the list.
Definition r_entity.cpp:694
Error checking function.
#define R_CheckError()
Definition r_error.h:30
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLint GLenum GLboolean GLsizei stride
Definition r_gl.h:94
QGL_EXTERN GLuint
Definition r_gl.h:124
#define MAX_GL_DELUXEMAPS
Definition r_image.h:78
#define MAX_GL_LIGHTMAPS
Definition r_image.h:77
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...
void R_BeginBuildingLightmaps(void)
static void R_DisposeLightmaps(void)
lightmaps_t r_lightmaps
void R_CreateSurfaceLightmap(mBspSurface_t *surf)
static bool R_AllocLightmapBlock(int w, int h, int *x, int *y)
returns a texture number and the position inside it
void R_Trace(const Line &trLine, float size, int contentmask)
Moves the given mins/maxs volume through the world from start to end.
void R_EndBuildingLightmaps(void)
static void R_UploadLightmapPage(void)
static void R_BuildDefaultLightmap(mBspSurface_t *surf, byte *sout, byte *dout, int stride)
Fullbridght lightmap.
lightmap definitions
#define LIGHTMAP_SAMPLE_SIZE
Definition r_lightmap.h:33
#define DELUXEMAP_SAMPLE_SIZE
Definition r_lightmap.h:34
local graphics definitions
cvar_t * r_maxlightmap
Definition r_main.cpp:101
rconfig_t r_config
Definition r_main.cpp:47
rlocals_t r_locals
Definition r_main.cpp:49
int r_numMapTiles
Definition r_model.cpp:33
@ mod_bsp_submodel
Definition r_model.h:41
#define MSURF_LIGHTMAP
#define R_BindTexture(tn)
Definition r_state.h:184
vec3_t angles
Definition r_entity.h:98
struct model_s * model
Definition r_entity.h:97
vec3_t origin
Definition r_entity.h:101
mBspTexInfo_t * texinfo
#define TRACE_ALL_LEVELS
Definition tracing.h:52
#define Vector4Set(v, r, g, b, a)
Definition vector.h:62