mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-30 00:10:53 +00:00
e1903dd925
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".
293 lines
6.3 KiB
C
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);
|
|
}
|
|
|