From 8a5658ed618b007de5ec49047d79b5974cc1eadd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 Jan 2012 14:53:23 +0900 Subject: [PATCH] Implement the bulk of the lightmap code. Now just to get surface rendering going and hook in the lights. --- include/QF/GLSL/qf_lightmap.h | 46 +++++ include/QF/model.h | 1 + libs/video/renderer/glsl/Makefile.am | 4 +- libs/video/renderer/glsl/glsl_lightmap.c | 246 +++++++++++++++++++++++ 4 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 include/QF/GLSL/qf_lightmap.h create mode 100644 libs/video/renderer/glsl/glsl_lightmap.c diff --git a/include/QF/GLSL/qf_lightmap.h b/include/QF/GLSL/qf_lightmap.h new file mode 100644 index 000000000..cb45987aa --- /dev/null +++ b/include/QF/GLSL/qf_lightmap.h @@ -0,0 +1,46 @@ +/* + qf_lightmap.h + + GLSL lightmap stuff from the renderer. + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __QF_GLSL_lightmap_h +#define __QF_GLSL_lightmap_h + +// LordHavoc: since lightmaps are now allocated only as needed, allow a ridiculous number :) +#define MAX_LIGHTMAPS 1024 +#define BLOCK_WIDTH 64 +#define BLOCK_HEIGHT 64 + +extern model_t *currentmodel; +extern mvertex_t *r_pcurrentvertbase; + +void BuildSurfaceDisplayList (msurface_t *fa); +void gl_lightmap_init (void); +void R_BuildLightmaps (struct model_s **models, int num_models); +void R_CalcLightmaps (void); +extern void (*R_BuildLightMap) (msurface_t *surf); + +#endif//__QF_GLSL_lightmap_h diff --git a/include/QF/model.h b/include/QF/model.h index c393662de..154f8f092 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -160,6 +160,7 @@ typedef struct msurface_s { mtexinfo_t *texinfo; // lighting info + struct subpic_s *lightpic; ///< light map texture ref (glsl) int dlightframe; int dlightbits; diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am index ea7af4f57..e8be74b40 100644 --- a/libs/video/renderer/glsl/Makefile.am +++ b/libs/video/renderer/glsl/Makefile.am @@ -11,8 +11,8 @@ shader_gen= \ quaketxt.vc glsl_src = \ - glsl_alias.c glsl_draw.c glsl_main.c glsl_particles.c glsl_screen.c \ - glsl_sprite.c glsl_textures.c + glsl_alias.c glsl_draw.c glsl_lightmap.c glsl_main.c glsl_particles.c \ + glsl_screen.c glsl_sprite.c glsl_textures.c if BUILD_GLSL noinst_LTLIBRARIES= libglsl.la diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c new file mode 100644 index 000000000..bc25d40be --- /dev/null +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -0,0 +1,246 @@ +/* + glsl_lightmap.c + + GLSL lightmaps + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Joseph Carter + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/1/6 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((used)) const char rcsid[] = "$Id$"; + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/render.h" +#include "QF/sys.h" + +#include "QF/GLSL/defines.h" +#include "QF/GLSL/funcs.h" +#include "QF/GLSL/qf_alias.h" +#include "QF/GLSL/qf_lightmap.h" +#include "QF/GLSL/qf_textures.h" +#include "QF/GLSL/qf_vid.h" + +#include "r_local.h" + +#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) + +static scrap_t *light_scrap; +static byte *light_data; +static unsigned *blocklights; +static int bl_extents[2]; + +void (*R_BuildLightMap) (msurface_t *surf); + +static void +R_AddDynamicLights_1 (msurface_t *surf) +{ + unsigned lnum; + int sd, td; + float dist, rad, minlight; + vec3_t impact, local, lightorigin; + int s, t; + int smax, tmax; + mtexinfo_t *tex; + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + tex = surf->texinfo; + + for (lnum = 0; lnum < r_maxdlights; lnum++) { + if (!(surf->dlightbits & (1 << lnum))) + continue; // not lit by this light + + VectorSubtract (r_dlights[lnum].origin, currententity->origin, + lightorigin); + rad = r_dlights[lnum].radius; + dist = DotProduct (lightorigin, surf->plane->normal) + - surf->plane->dist; + rad -= fabs (dist); + minlight = r_dlights[lnum].minlight; + if (rad < minlight) + continue; + minlight = rad - minlight; + + VectorMultSub (lightorigin, dist, surf->plane->normal, impact); + + local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; + local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; + + local[0] -= surf->texturemins[0]; + local[1] -= surf->texturemins[1]; + + for (t = 0; t < tmax; t++) { + td = local[1] - t * 16; + if (td < 0) + td = -td; + for (s = 0; s < smax; s++) { + sd = local[0] - s * 16; + if (sd < 0) + sd = -sd; + if (sd > td) + dist = sd + (td >> 1); + else + dist = td + (sd >> 1); + if (dist < minlight) + blocklights[t * smax + s] += (rad - dist) * 256; + } + } + } +} + +static void +R_BuildLightMap_1 (msurface_t *surf) +{ + int smax, tmax, size; + unsigned scale, t; + int i; + byte *out; + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + size = smax * tmax; + + // clear to no light + memset (blocklights, 0, size * sizeof (blocklights[0])); + if (!r_worldentity.model->lightdata) { + // because we by-pass the inversion, "no light" = "full bright" + GL_SubpicUpdate (surf->lightpic, (byte *) blocklights); + return; + } + + // add all the lightmaps + if (surf->samples) { + int lmap; + byte *lightmap = surf->samples; + + for (lmap = 0; lmap < MAXLIGHTMAPS && surf->styles[lmap] != 255; + lmap++) { + unsigned int *bl; + + scale = d_lightstylevalue[surf->styles[lmap]]; + surf->cached_light[lmap] = scale; + bl = blocklights; + for (i = 0; i < size; i++) + *bl++ += *lightmap++ * scale; + } + } + // add all the dynamic lights + if (surf->dlightframe == r_framecount) + R_AddDynamicLights_1 (surf); + + // bound, invert, and shift + out = (byte *) blocklights; + for (i = 0; i < size; i++) { + t = (255 * 256 - (int) blocklights[i]) >> (8 - VID_CBITS); + + t = max (t, 1 << 6); + *out++ = t >> 8; + } + + GL_SubpicUpdate (surf->lightpic, (byte *) blocklights); +} + +void +R_CalcLightmaps (void) +{ +} + +static void +create_surf_lightmap (msurface_t *surf) +{ + int smax, tmax; + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + surf->lightpic = GL_ScrapSubpic (light_scrap, smax, tmax); + if (!surf->lightpic) + Sys_Error ("FIXME taniwha is being lazy"); + if (smax > bl_extents[0]) + bl_extents[0] = smax; + if (tmax > bl_extents[1]) + bl_extents[1] = tmax; +} + +void +R_BuildLightmaps (model_t **models, int num_models) +{ + int i, j, size; + model_t *m; + + //FIXME RGB support + if (!light_scrap) { + light_scrap = GL_CreateScrap (2048, GL_LUMINANCE); + light_data = malloc (BLOCK_SIZE * MAX_LIGHTMAPS); + } + R_BuildLightMap = R_BuildLightMap_1; + + bl_extents[1] = bl_extents[0] = 0; + for (j = 1; j < num_models; j++) { + m = models[j]; + if (!m) + break; + if (m->name[0] == '*') { + // sub model surfaces are processed as part of the main model + continue; + } + // non-bsp models don't have surfaces. + for (i = 0; i < m->numsurfaces; i++) { + msurface_t *surf = m->surfaces + i; + surf->lightpic = 0; // paranoia + if (surf->flags & SURF_DRAWTURB) + continue; + if (surf->flags & SURF_DRAWSKY) + continue; + create_surf_lightmap (surf); + } + } + size = bl_extents[0] * bl_extents[1] * 3; // * 3 for rgb support + blocklights = realloc (blocklights, size * sizeof (blocklights[0])); + for (j = 1; j < num_models; j++) { + m = models[j]; + if (!m) + break; + if (m->name[0] == '*') { + // sub model surfaces are processed as part of the main model + continue; + } + // non-bsp models don't have surfaces. + for (i = 0; i < m->numsurfaces; i++) { + msurface_t *surf = m->surfaces + i; + if (surf->lightpic) + R_BuildLightMap (surf); + } + } +}