yquake2remaster/src/refresh/r_lightmap.c
Yamagi Burmeister e1903dd925 Change some qglTexParameterf to qglTexParameteri
Scott S. pointed out that some the qglTexParameterf calls should be
qglTexParameteri. I don't know if all this changes are correct (I'm
an openGL noob) but they shouldn't make thinks worse and "works for me".
2013-03-10 10:20:42 +01:00

293 lines
6.3 KiB
C

/*
* Copyright (C) 1997-2001 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 the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Lightmap handling
*
* =======================================================================
*/
#include "header/local.h"
extern gllightmapstate_t gl_lms;
void R_SetCacheState(msurface_t *surf);
void R_BuildLightMap(msurface_t *surf, byte *dest, int stride);
void
LM_InitBlock(void)
{
memset(gl_lms.allocated, 0, sizeof(gl_lms.allocated));
}
void
LM_UploadBlock(qboolean dynamic)
{
int texture;
int height = 0;
if (dynamic)
{
texture = 0;
}
else
{
texture = gl_lms.current_lightmap_texture;
}
R_Bind(gl_state.lightmap_textures + texture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (dynamic)
{
int i;
for (i = 0; i < BLOCK_WIDTH; i++)
{
if (gl_lms.allocated[i] > height)
{
height = gl_lms.allocated[i];
}
}
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, BLOCK_WIDTH,
height, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE,
gl_lms.lightmap_buffer);
}
else
{
qglTexImage2D(GL_TEXTURE_2D, 0, gl_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE, gl_lms.lightmap_buffer);
if (++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS)
{
ri.Sys_Error(ERR_DROP,
"LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n");
}
}
}
/*
* returns a texture number and the position inside it
*/
qboolean
LM_AllocBlock(int w, int h, int *x, int *y)
{
int i, j;
int best, best2;
best = BLOCK_HEIGHT;
for (i = 0; i < BLOCK_WIDTH - w; i++)
{
best2 = 0;
for (j = 0; j < w; j++)
{
if (gl_lms.allocated[i + j] >= best)
{
break;
}
if (gl_lms.allocated[i + j] > best2)
{
best2 = gl_lms.allocated[i + j];
}
}
if (j == w)
{
/* this is a valid spot */
*x = i;
*y = best = best2;
}
}
if (best + h > BLOCK_HEIGHT)
{
return false;
}
for (i = 0; i < w; i++)
{
gl_lms.allocated[*x + i] = best + h;
}
return true;
}
void
LM_BuildPolygonFromSurface(msurface_t *fa)
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
float *vec;
float s, t;
glpoly_t *poly;
vec3_t total;
/* reconstruct the polygon */
pedges = currentmodel->edges;
lnumverts = fa->numedges;
VectorClear(total);
/* draw texture */
poly = Hunk_Alloc(sizeof(glpoly_t) +
(lnumverts - 4) * VERTEXSIZE * sizeof(float));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
for (i = 0; i < lnumverts; i++)
{
lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = currentmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = currentmodel->vertexes[r_pedge->v[1]].position;
}
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->image->width;
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->image->height;
VectorAdd(total, vec, total);
VectorCopy(vec, poly->verts[i]);
poly->verts[i][3] = s;
poly->verts[i][4] = t;
/* lightmap texture coordinates */
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s * 16;
s += 8;
s /= BLOCK_WIDTH * 16; /* fa->texinfo->texture->width; */
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t * 16;
t += 8;
t /= BLOCK_HEIGHT * 16; /* fa->texinfo->texture->height; */
poly->verts[i][5] = s;
poly->verts[i][6] = t;
}
poly->numverts = lnumverts;
}
void
LM_CreateSurfaceLightmap(msurface_t *surf)
{
int smax, tmax;
byte *base;
if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
return;
}
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
if (!LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
LM_UploadBlock(false);
LM_InitBlock();
if (!LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
ri.Sys_Error(ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n",
smax, tmax);
}
}
surf->lightmaptexturenum = gl_lms.current_lightmap_texture;
base = gl_lms.lightmap_buffer;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
R_SetCacheState(surf);
R_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES);
}
void
LM_BeginBuildingLightmaps(model_t *m)
{
static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
int i;
unsigned dummy[128 * 128];
memset(gl_lms.allocated, 0, sizeof(gl_lms.allocated));
r_framecount = 1; /* no dlightcache */
R_EnableMultitexture(true);
R_SelectTexture(QGL_TEXTURE1);
/* setup the base lightstyles so the lightmaps
won't have to be regenerated the first time
they're seen */
for (i = 0; i < MAX_LIGHTSTYLES; i++)
{
lightstyles[i].rgb[0] = 1;
lightstyles[i].rgb[1] = 1;
lightstyles[i].rgb[2] = 1;
lightstyles[i].white = 3;
}
r_newrefdef.lightstyles = lightstyles;
if (!gl_state.lightmap_textures)
{
gl_state.lightmap_textures = TEXNUM_LIGHTMAPS;
}
gl_lms.current_lightmap_texture = 1;
gl_lms.internal_format = gl_tex_solid_format;
/* initialize the dynamic lightmap texture */
R_Bind(gl_state.lightmap_textures + 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, gl_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE, dummy);
}
void
LM_EndBuildingLightmaps(void)
{
LM_UploadBlock(false);
R_EnableMultitexture(false);
}