GL3: Multiple lightmaps/surface with lightstyles works

not sure if this is the very best solution..
Every surface can have up to 4 lightmaps.
I now always create 4 lightmaps (in separate textures, so the
corresponding texture coordinates are identical), the "fillers" are
set to 0, so in the shader they won't make a visible difference.
(The shader always adds up lightmaps from 4 textures, but how much
 they're actually visible depends on lmScales which also will be set to
 0 if "unused")

If all this turns out to be (too) slow, there could be a special case
for surfaces with only one lightmap, I /think/ that's the most common
case by far.
This commit is contained in:
Daniel Gibson 2017-03-19 05:43:44 +01:00
parent 5abf60de89
commit 2dc7b6e6eb
6 changed files with 125 additions and 289 deletions

View File

@ -27,13 +27,14 @@
#include "header/local.h"
extern gl3lightmapstate_t gl3_lms;
#define DLIGHT_CUTOFF 64
static int r_dlightframecount;
static vec3_t pointcolor;
static cplane_t *lightplane; /* used as shadow plane */
vec3_t lightspot;
static float s_blocklights[34 * 34 * 3];
void // bit: 1 << i for light number i, will be or'ed into msurface_t::dlightbits if surface is affected by this light
GL3_MarkLights(dlight_t *light, int bit, mnode_t *node)
@ -213,7 +214,7 @@ RecursiveLightPoint(mnode_t *node, vec3_t start, vec3_t end)
lightmap += 3 * (dt * ((surf->extents[0] >> 4) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
for (maps = 0; maps < MAX_LIGHTMAPS_PER_SURFACE && surf->styles[maps] != 255;
maps++)
{
for (i = 0; i < 3; i++)
@ -290,6 +291,7 @@ GL3_LightPoint(vec3_t p, vec3_t color)
VectorScale(color, gl_modulate->value, color);
}
#if 0 // TODO: REMOVE! (currently kept to look at when writing shader for this)
static void
AddDynamicLights(msurface_t *surf)
{
@ -382,31 +384,18 @@ AddDynamicLights(msurface_t *surf)
}
}
}
void
GL3_SetCacheState(msurface_t *surf)
{
int maps;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
surf->cached_light[maps] =
gl3_newrefdef.lightstyles[surf->styles[maps]].white;
}
}
#endif // 0
/*
* Combine and scale multiple lightmaps into the floating format in blocklights
*/
void
GL3_BuildLightMap(msurface_t *surf, byte *dest, int stride)
GL3_BuildLightMap(msurface_t *surf, int offsetInLMbuf, int stride)
{
int smax, tmax;
int r, g, b, a, max;
int i, j, size;
int i, j, size, map, numMaps;
byte *lightmap;
float scale[4];
float *bl;
if (surf->texinfo->flags &
(SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))
@ -418,126 +407,107 @@ GL3_BuildLightMap(msurface_t *surf, byte *dest, int stride)
tmax = (surf->extents[1] >> 4) + 1;
size = smax * tmax;
if (size > (sizeof(s_blocklights) >> 4))
stride -= (smax << 2);
if (size > 34*34*3)
{
ri.Sys_Error(ERR_DROP, "Bad s_blocklights size");
}
/* set to full bright if no light data */
// count number of lightmaps surf actually has
for (numMaps = 0; numMaps < MAX_LIGHTMAPS_PER_SURFACE && surf->styles[numMaps] != 255; ++numMaps)
{}
if (!surf->samples)
{
for (i = 0; i < size * 3; i++)
// no lightmap samples? set at least one lightmap to fullbright, rest to 0 as normal
if (numMaps == 0) numMaps = 1; // make sure at least one lightmap is set to fullbright
for (map = 0; map < MAX_LIGHTMAPS_PER_SURFACE; ++map)
{
s_blocklights[i] = 255;
// we always create 4 (MAXLIGHTMAP) lightmaps.
// if surf has less (numMaps < 4), the remaining ones are zeroed out.
// this makes sure that all 4 lightmap textures in gl3state.lightmap_textureIDs[i] have the same layout
// and the shader can use the same texture coordinates for all of them
int c = (map < numMaps) ? 255 : 0;
byte* dest = gl3_lms.lightmap_buffers[map] + offsetInLMbuf;
for (i = 0; i < tmax; i++, dest += stride)
{
memset(dest, c, 4*smax);
dest += 4*smax;
}
}
goto store;
return;
}
/* add all the lightmaps */
{
int maps;
memset(s_blocklights, 0, sizeof(s_blocklights[0]) * size * 3);
lightmap = surf->samples;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
bl = s_blocklights;
for (i = 0; i < 3; i++)
{
scale[i] = gl_modulate->value *
gl3_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
}
for (i = 0; i < size; i++, bl += 3)
{
bl[0] += lightmap[i * 3 + 0] * scale[0];
bl[1] += lightmap[i * 3 + 1] * scale[1];
bl[2] += lightmap[i * 3 + 2] * scale[2];
}
lightmap += size * 3; /* skip to next lightmap */
}
}
STUB_ONCE("TODO: handly dynamic lights (prolly somewhere else entirely)");
#if 0
/* add all the dynamic lights */
if (surf->dlightframe == gl3_framecount)
{
AddDynamicLights(surf);
}
#endif // 0
store:
// as we don't apply scale here anymore, nor blend the numMaps lightmaps together,
// the code has gotten a lot easier and we can copy directly from surf->samples to dest
// without converting to float first etc
stride -= (smax << 2);
bl = s_blocklights;
lightmap = surf->samples;
for(map=0; map<numMaps; ++map)
{
byte* dest = gl3_lms.lightmap_buffers[map] + offsetInLMbuf;
int idxInLightmap = 0;
for (i = 0; i < tmax; i++, dest += stride)
{
for (j = 0; j < smax; j++)
{
r = Q_ftol(bl[0]);
g = Q_ftol(bl[1]);
b = Q_ftol(bl[2]);
/* catch negative lights */
if (r < 0)
{
r = 0;
}
if (g < 0)
{
g = 0;
}
if (b < 0)
{
b = 0;
}
r = lightmap[idxInLightmap * 3 + 0];
g = lightmap[idxInLightmap * 3 + 1];
b = lightmap[idxInLightmap * 3 + 2];
/* determine the brightest of the three color components */
if (r > g)
{
max = r;
}
else
{
max = g;
}
if (r > g) max = r;
else max = g;
if (b > max)
{
max = b;
}
if (b > max) max = b;
/* alpha is ONLY used for the mono lightmap case. For this
reason we set it to the brightest of the color components
so that things don't get too dim. */
a = max;
/* rescale all the color components if the
intensity of the greatest channel exceeds
1.0 */
if (max > 255)
{
float t = 255.0F / max;
r = r * t;
g = g * t;
b = b * t;
a = a * t;
}
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
bl += 3;
dest += 4;
++idxInLightmap;
}
}
lightmap += size * 3; /* skip to next lightmap */
}
for ( ; map < MAX_LIGHTMAPS_PER_SURFACE; ++map)
{
// like above, fill up remaining lightmaps with 0
byte* dest = gl3_lms.lightmap_buffers[map] + offsetInLMbuf;
for (i = 0; i < tmax; i++, dest += stride)
{
memset(dest, 0, 4*smax);
dest += 4*smax;
}
}
}

View File

@ -39,53 +39,32 @@ GL3_LM_InitBlock(void)
}
void
GL3_LM_UploadBlock(qboolean dynamic)
GL3_LM_UploadBlock(void)
{
int texture;
int height = 0;
int map;
if (dynamic)
{
texture = 0;
}
else
{
texture = gl3_lms.current_lightmap_texture;
}
// NOTE: we don't use the dynamic lightmap anymore - all lightmaps are loaded at level load
// and not changed after that. they're blended dynamically depending on light styles
// though, and dynamic lights are (will be) applied in shader, hopefully per fragment.
GL3_BindLightmap(texture);
GL3_SelectTMU(GL_TEXTURE1);
GL3_BindLightmap(gl3_lms.current_lightmap_texture);
// upload all 4 lightmaps
for(map=0; map < MAX_LIGHTMAPS_PER_SURFACE; ++map)
{
GL3_SelectTMU(GL_TEXTURE1+map); // this relies on GL_TEXTURE2 being GL_TEXTURE1+1 etc
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (dynamic)
{
int i;
STUB_ONCE("TODO: dynamic lightmap!");
for (i = 0; i < BLOCK_WIDTH; i++)
{
if (gl3_lms.allocated[i] > height)
{
height = gl3_lms.allocated[i];
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, BLOCK_WIDTH,
height, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE,
gl3_lms.lightmap_buffer);
}
else
{
gl3_lms.internal_format = GL_LIGHTMAP_FORMAT;
glTexImage2D(GL_TEXTURE_2D, 0, gl3_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE, gl3_lms.lightmap_buffer);
GL_UNSIGNED_BYTE, gl3_lms.lightmap_buffers[map]);
}
if (++gl3_lms.current_lightmap_texture == MAX_LIGHTMAPS)
{
ri.Sys_Error(ERR_DROP,
"LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n");
}
ri.Sys_Error(ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n");
}
}
@ -212,7 +191,6 @@ void
GL3_LM_CreateSurfaceLightmap(msurface_t *surf)
{
int smax, tmax;
byte *base;
if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
@ -224,7 +202,7 @@ GL3_LM_CreateSurfaceLightmap(msurface_t *surf)
if (!GL3_LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
GL3_LM_UploadBlock(false);
GL3_LM_UploadBlock();
GL3_LM_InitBlock();
if (!GL3_LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
@ -236,11 +214,7 @@ GL3_LM_CreateSurfaceLightmap(msurface_t *surf)
surf->lightmaptexturenum = gl3_lms.current_lightmap_texture;
base = gl3_lms.lightmap_buffer;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
GL3_SetCacheState(surf);
GL3_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES);
GL3_BuildLightMap(surf, (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES, BLOCK_WIDTH * LIGHTMAP_BYTES);
}
void
@ -268,24 +242,15 @@ GL3_LM_BeginBuildingLightmaps(gl3model_t *m)
gl3_newrefdef.lightstyles = lightstyles;
STUB_ONCE("TODO: IMPLEMENT!");
gl3_lms.current_lightmap_texture = 1;
gl3_lms.internal_format = GL_LIGHTMAP_FORMAT;
/* initialize the dynamic lightmap texture */
GL3_SelectTMU(GL_TEXTURE1);
GL3_BindLightmap(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, gl3_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT, 0,
GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, dummy);
// Note: the dynamic lightmap used to be initialized here, we don't use that anymore.
}
void
GL3_LM_EndBuildingLightmaps(void)
{
GL3_LM_UploadBlock(false);
GL3_LM_UploadBlock();
}

View File

@ -525,8 +525,7 @@ Mod_LoadFaces(lump_t *l)
}
/* create lightmaps and polygons */
if (!(out->texinfo->flags &
(SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
{
GL3_LM_CreateSurfaceLightmap(out);
}

View File

@ -264,12 +264,12 @@ DrawTriangleOutlines(void)
}
static void
UpdateLMscales(const hmm_vec4 lmScales[MAXLIGHTMAPS], gl3ShaderInfo_t* si)
UpdateLMscales(const hmm_vec4 lmScales[MAX_LIGHTMAPS_PER_SURFACE], gl3ShaderInfo_t* si)
{
int i;
qboolean hasChanged = false;
for(i=0; i<MAXLIGHTMAPS; ++i)
for(i=0; i<MAX_LIGHTMAPS_PER_SURFACE; ++i)
{
if(hasChanged)
{
@ -287,7 +287,7 @@ UpdateLMscales(const hmm_vec4 lmScales[MAXLIGHTMAPS], gl3ShaderInfo_t* si)
if(hasChanged)
{
glUniform4fv(si->uniLmScales, MAXLIGHTMAPS, si->lmScales[0].Elements);
glUniform4fv(si->uniLmScales, MAX_LIGHTMAPS_PER_SURFACE, si->lmScales[0].Elements);
}
}
@ -347,7 +347,7 @@ RenderBrushPoly(msurface_t *fa)
// R_TexEnv(GL_REPLACE); TODO!
}
hmm_vec4 lmScales[MAXLIGHTMAPS] = {0};
hmm_vec4 lmScales[MAX_LIGHTMAPS_PER_SURFACE] = {0};
lmScales[0] = HMM_Vec4(1.0f, 1.0f, 1.0f, 1.0f);
// TODO: bind all the lightmaps
@ -355,7 +355,7 @@ RenderBrushPoly(msurface_t *fa)
GL3_BindLightmap(fa->lightmaptexturenum);
// Any dynamic lights on this surface?
for (map = 0; map < MAXLIGHTMAPS && fa->styles[map] != 255; map++)
for (map = 0; map < MAX_LIGHTMAPS_PER_SURFACE && fa->styles[map] != 255; map++)
{
lmScales[map].R = gl3_newrefdef.lightstyles[fa->styles[map]].rgb[0];
lmScales[map].G = gl3_newrefdef.lightstyles[fa->styles[map]].rgb[1];
@ -375,77 +375,6 @@ RenderBrushPoly(msurface_t *fa)
UpdateLMscales(lmScales, &gl3state.si3Dlm);
GL3_DrawGLPoly(fa->polys);
}
STUB_ONCE("TODO: dynamic lightmap in shaders");
/* check for lightmap modification */
for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++)
{
if (gl3_newrefdef.lightstyles[fa->styles[maps]].white !=
fa->cached_light[maps])
{
goto dynamic;
}
}
/* dynamic this frame or dynamic previously */
if (fa->dlightframe == gl3_framecount)
{
dynamic:
if (gl_dynamic->value)
{
if (!(fa->texinfo->flags &
(SURF_SKY | SURF_TRANS33 |
SURF_TRANS66 | SURF_WARP)))
{
is_dynamic = true;
}
}
}
STUB_ONCE("TODO: lightmap support (=> esp. LM textures)")
// TODO: 2D texture array für lightmaps?
if (is_dynamic)
{
/*if (((fa->styles[maps] >= 32) ||
(fa->styles[maps] == 0)) &&
(fa->dlightframe != gl3_framecount))
{
// undo dynamic light changes, put into non-dynamic lightmap chain?
// (not totally sure what's happening here)
unsigned temp[34 * 34];
int smax, tmax;
smax = (fa->extents[0] >> 4) + 1;
tmax = (fa->extents[1] >> 4) + 1;
GL3_BuildLightMap(fa, (void *)temp, smax * 4);
GL3_SetCacheState(fa);
GL3_SelectTMU(GL_TEXTURE1);
GL3_BindLightmap(fa->lightmaptexturenum);
glTexSubImage2D(GL_TEXTURE_2D, 0, fa->light_s, fa->light_t,
smax, tmax, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, temp);
fa->lightmapchain = gl3_lms.lightmap_surfaces[fa->lightmaptexturenum];
gl3_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
}
else*/
{
// dynamic lights: add to dynamic lightmap chain
fa->lightmapchain = gl3_lms.lightmap_surfaces[0];
gl3_lms.lightmap_surfaces[0] = fa;
}
}
else // non-dynamic lightmap chain
{
fa->lightmapchain = gl3_lms.lightmap_surfaces[fa->lightmaptexturenum];
gl3_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
}
}
/*
@ -471,8 +400,6 @@ GL3_DrawAlphaSurfaces(void)
//intens = gl3state.inverse_intensity;
STUB_ONCE("Something about inverse intensity??");
STUB_ONCE("TODO: more shaders for rendering brushes (w/o lightmap for translucent etc)");
for (s = gl3_alpha_surfaces; s != NULL; s = s->texturechain)
{
GL3_Bind(s->texinfo->image->texnum);
@ -573,7 +500,7 @@ RenderLightmappedPoly(msurface_t *surf)
unsigned lmtex;
unsigned temp[128 * 128];
hmm_vec4 lmScales[MAXLIGHTMAPS] = {0};
hmm_vec4 lmScales[MAX_LIGHTMAPS_PER_SURFACE] = {0};
lmScales[0] = HMM_Vec4(1.0f, 1.0f, 1.0f, 1.0f);
image = TextureAnimation(surf->texinfo);
@ -585,7 +512,7 @@ RenderLightmappedPoly(msurface_t *surf)
&& "RenderLightMappedPoly mustn't be called with transparent, sky or warping surfaces!");
// Any dynamic lights on this surface?
for (map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++)
for (map = 0; map < MAX_LIGHTMAPS_PER_SURFACE && surf->styles[map] != 255; map++)
{
lmScales[map].R = gl3_newrefdef.lightstyles[surf->styles[map]].rgb[0];
lmScales[map].G = gl3_newrefdef.lightstyles[surf->styles[map]].rgb[1];
@ -597,36 +524,20 @@ RenderLightmappedPoly(msurface_t *surf)
if (surf->dlightframe == gl3_framecount)
{
if (gl_dynamic->value)
{
if (!(surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
{
is_dynamic = true;
}
}
}
#if 0 // TODO!
if (is_dynamic)
{
// Dynamic lights on a surface
// Dynamic lights on a surface - NOTE: this is handled via lmScales
if (((surf->styles[map] >= 32) || (surf->styles[map] == 0)) && (surf->dlightframe != r_framecount))
{
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
//GL3_BuildLightMap(surf, (void *) temp, smax * 4);
//GL3_SetCacheState(surf);
//R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + surf->lightmaptexturenum);
//GL3_BindLightmap(surf->lightmaptexturenum);
//lmtex = surf->lightmaptexturenum;
FIXME;
//glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax,
// tmax, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, temp);
}
else // Normal dynamic lights
else // Normal dynamic lights - NOTE: This is still missing, but will not be done by creating a dynamic lightmap.
{
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
@ -646,16 +557,14 @@ RenderLightmappedPoly(msurface_t *surf)
R_MBind(GL_TEXTURE0_ARB, image->texnum);
R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + lmtex);
}
else // No dynamic lights
#endif // 0
{
c_brush_polys++;
//R_MBind(GL_TEXTURE0_ARB, image->texnum);
GL3_Bind(image->texnum);
//R_MBind(GL_TEXTURE1_ARB, gl_state.lightmap_textures + lmtex);
GL3_BindLightmap(lmtex);
}
if (surf->texinfo->flags & SURF_FLOWING)
{
@ -783,10 +692,6 @@ GL3_DrawBrushModel(entity_t *e)
glEnable(GL_POLYGON_OFFSET_FILL);
}
STUB_ONCE("TODO: something about setting color to 1,1,1,1");
//glColor4f(1, 1, 1, 1);
memset(gl3_lms.lightmap_surfaces, 0, sizeof(gl3_lms.lightmap_surfaces));
VectorSubtract(gl3_newrefdef.vieworg, e->origin, modelorg);
if (rotated)
@ -999,17 +904,14 @@ GL3_DrawWorld(void)
ent.frame = (int)(gl3_newrefdef.time * 2);
currententity = &ent;
gl3state.currenttexture = -1; //s[0] = gl3state.currenttextures[1] = -1;
gl3state.currenttexture = -1;
STUB_ONCE("somehow set color to 1,1,1,1 maybe");
//glColor4f(1, 1, 1, 1);
memset(gl3_lms.lightmap_surfaces, 0, sizeof(gl3_lms.lightmap_surfaces));
GL3_ClearSkyBox();
RecursiveWorldNode(gl3_worldmodel->nodes);
DrawTextureChains();
//BlendLightmaps();
GL3_DrawSkyBox();
DrawTriangleOutlines();

View File

@ -262,13 +262,13 @@ typedef struct
int internal_format;
int current_lightmap_texture; // index into gl3state.lightmap_textureIDs[]
msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];
//msurface_t *lightmap_surfaces[MAX_LIGHTMAPS]; - no more lightmap chains, lightmaps are rendered multitextured
int allocated[BLOCK_WIDTH];
/* the lightmap texture data needs to be kept in
main memory so texsubimage can update properly */
byte lightmap_buffer[4 * BLOCK_WIDTH * BLOCK_HEIGHT];
byte lightmap_buffers[MAX_LIGHTMAPS_PER_SURFACE][4 * BLOCK_WIDTH * BLOCK_HEIGHT];
} gl3lightmapstate_t;
// used for vertex array elements when drawing brushes, sprites, sky and more
@ -408,14 +408,13 @@ extern void GL3_ImageList_f(void);
extern void GL3_MarkLights(dlight_t *light, int bit, mnode_t *node);
extern void GL3_PushDlights(void);
extern void GL3_LightPoint(vec3_t p, vec3_t color);
extern void GL3_SetCacheState(msurface_t *surf);
extern void GL3_BuildLightMap(msurface_t *surf, byte *dest, int stride);
extern void GL3_BuildLightMap(msurface_t *surf, int offsetInLMbuf, int stride);
// gl3_lightmap.c
#define GL_LIGHTMAP_FORMAT GL_RGBA
extern void GL3_LM_InitBlock(void);
extern void GL3_LM_UploadBlock(qboolean dynamic);
extern void GL3_LM_UploadBlock(void);
extern qboolean GL3_LM_AllocBlock(int w, int h, int *x, int *y);
extern void GL3_LM_BuildPolygonFromSurface(msurface_t *fa);
extern void GL3_LM_CreateSurfaceLightmap(msurface_t *surf);

View File

@ -104,7 +104,7 @@ typedef struct msurface_s
glpoly_t *polys; /* multiple if warped */
struct msurface_s *texturechain;
struct msurface_s *lightmapchain;
// struct msurface_s *lightmapchain; not used/needed anymore
mtexinfo_t *texinfo;
@ -114,7 +114,8 @@ typedef struct msurface_s
int lightmaptexturenum;
byte styles[MAXLIGHTMAPS];
float cached_light[MAXLIGHTMAPS]; /* values currently used in lightmap */
// I think cached_light is not used/needed anymore
//float cached_light[MAXLIGHTMAPS]; /* values currently used in lightmap */
byte *samples; /* [numstyles*surfsize] */
} msurface_t;