- Benenne alle Funktionen in gl_rsurf um

- Lightmaps in ne eigene Datei
This commit is contained in:
Yamagi Burmeister 2010-10-23 08:24:28 +00:00
parent d6acc3b4ea
commit 4c9536e400
4 changed files with 356 additions and 314 deletions

View file

@ -325,6 +325,7 @@ OPENGL_OBJS = \
build/ref_gl/r_draw.o \
build/ref_gl/r_image.o \
build/ref_gl/r_light.o \
build/ref_gl/r_lightmap.o \
build/ref_gl/r_mesh.o \
build/ref_gl/r_model.o \
build/ref_gl/r_main.o \
@ -781,7 +782,10 @@ build/ref_gl/r_image.o: src/refresh/r_image.c
build/ref_gl/r_light.o: src/refresh/r_light.c
$(CC) $(CFLAGS_OPENGL) -o $@ -c $<
build/ref_gl/r_lightmap.o: src/refresh/r_lightmap.c
$(CC) $(CFLAGS_OPENGL) -o $@ -c $<
build/ref_gl/r_mesh.o: src/refresh/r_mesh.c
$(CC) $(CFLAGS_OPENGL) -o $@ -c $<

View file

@ -1,59 +1,45 @@
/*
* 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 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
* 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.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
* =======================================================================
*
* Surface generation and drawing
*
* =======================================================================
*/
#include <assert.h>
#include "header/local.h"
#define DYNAMIC_LIGHT_WIDTH 128
#define DYNAMIC_LIGHT_HEIGHT 128
#define LIGHTMAP_BYTES 4
#define MAX_LIGHTMAPS 128
#define GL_LIGHTMAP_FORMAT GL_RGBA
int c_visible_lightmaps;
int c_visible_textures;
static vec3_t modelorg; /* relative to viewpoint */
msurface_t *r_alpha_surfaces;
typedef struct
{
int internal_format;
int current_lightmap_texture;
gllightmapstate_t gl_lms;
msurface_t *lightmap_surfaces [ MAX_LIGHTMAPS ];
void LM_InitBlock ( void );
void LM_UploadBlock ( qboolean dynamic );
qboolean LM_AllocBlock ( int w, int h, int *x, int *y );
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 ];
} gllightmapstate_t;
static gllightmapstate_t gl_lms;
static void LM_InitBlock ( void );
static void LM_UploadBlock ( qboolean dynamic );
static qboolean LM_AllocBlock ( int w, int h, int *x, int *y );
extern void R_SetCacheState ( msurface_t *surf );
extern void R_BuildLightMap ( msurface_t *surf, byte *dest, int stride );
void R_SetCacheState ( msurface_t *surf );
void R_BuildLightMap ( msurface_t *surf, byte *dest, int stride );
/*
* Returns the proper texture for a given time and base texture
@ -80,7 +66,7 @@ R_TextureAnimation ( mtexinfo_t *tex )
}
void
DrawGLPoly ( glpoly_t *p )
R_DrawGLPoly ( glpoly_t *p )
{
int i;
float *v;
@ -98,7 +84,7 @@ DrawGLPoly ( glpoly_t *p )
}
void
DrawGLFlowingPoly ( msurface_t *fa )
R_DrawGLFlowingPoly ( msurface_t *fa )
{
int i;
float *v;
@ -169,7 +155,7 @@ R_DrawTriangleOutlines ( void )
}
void
DrawGLPolyChain ( glpoly_t *p, float soffset, float toffset )
R_DrawGLPolyChain ( glpoly_t *p, float soffset, float toffset )
{
if ( ( soffset == 0 ) && ( toffset == 0 ) )
{
@ -182,7 +168,7 @@ DrawGLPolyChain ( glpoly_t *p, float soffset, float toffset )
if ( v == NULL )
{
fprintf( stderr, "BUGFIX: DrawGLPolyChain: v==NULL\n" );
fprintf( stderr, "BUGFIX: R_DrawGLPolyChain: v==NULL\n" );
return;
}
@ -279,7 +265,7 @@ R_BlendLightmaps ( void )
{
if ( surf->polys )
{
DrawGLPolyChain( surf->polys, 0, 0 );
R_DrawGLPolyChain( surf->polys, 0, 0 );
}
}
}
@ -326,7 +312,7 @@ R_BlendLightmaps ( void )
{
if ( drawsurf->polys )
{
DrawGLPolyChain( drawsurf->polys,
R_DrawGLPolyChain( drawsurf->polys,
( drawsurf->light_s - drawsurf->dlight_s ) * ( 1.0 / 128.0 ),
( drawsurf->light_t - drawsurf->dlight_t ) * ( 1.0 / 128.0 ) );
}
@ -360,7 +346,7 @@ R_BlendLightmaps ( void )
{
if ( surf->polys )
{
DrawGLPolyChain( surf->polys, ( surf->light_s - surf->dlight_s ) * ( 1.0 / 128.0 ),
R_DrawGLPolyChain( surf->polys, ( surf->light_s - surf->dlight_s ) * ( 1.0 / 128.0 ),
( surf->light_t - surf->dlight_t ) * ( 1.0 / 128.0 ) );
}
}
@ -407,11 +393,11 @@ R_RenderBrushPoly ( msurface_t *fa )
if ( fa->texinfo->flags & SURF_FLOWING )
{
DrawGLFlowingPoly( fa );
R_DrawGLFlowingPoly( fa );
}
else
{
DrawGLPoly( fa->polys );
R_DrawGLPoly( fa->polys );
}
/* check for lightmap modification */
@ -519,11 +505,11 @@ R_DrawAlphaSurfaces ( void )
}
else if ( s->texinfo->flags & SURF_FLOWING )
{
DrawGLFlowingPoly( s );
R_DrawGLFlowingPoly( s );
}
else
{
DrawGLPoly( s->polys );
R_DrawGLPoly( s->polys );
}
}
@ -535,7 +521,7 @@ R_DrawAlphaSurfaces ( void )
}
void
DrawTextureChains ( void )
R_DrawTextureChains ( void )
{
int i;
msurface_t *s;
@ -862,7 +848,7 @@ R_DrawWorld ( void )
R_ClearSkyBox();
R_RecursiveWorldNode( r_worldmodel->nodes );
DrawTextureChains();
R_DrawTextureChains();
R_BlendLightmaps();
R_DrawSkyBox();
@ -962,269 +948,3 @@ R_MarkLeaves ( void )
}
}
static void
LM_InitBlock ( void )
{
memset( gl_lms.allocated, 0, sizeof ( gl_lms.allocated ) );
}
static 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 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( 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 */
static 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
GL_BuildPolygonFromSurface ( msurface_t *fa )
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
int vertpage;
float *vec;
float s, t;
glpoly_t *poly;
vec3_t total;
/* reconstruct the polygon */
pedges = currentmodel->edges;
lnumverts = fa->numedges;
vertpage = 0;
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
GL_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
GL_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 */
/* 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 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( 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
GL_EndBuildingLightmaps ( void )
{
LM_UploadBlock( false );
}

View file

@ -49,6 +49,11 @@
#define REF_VERSION "Yamagi Quake II OpenGL Refresher"
#define MAX_LBM_HEIGHT 480
#define BACKFACE_EPSILON 0.01
#define DYNAMIC_LIGHT_WIDTH 128
#define DYNAMIC_LIGHT_HEIGHT 128
#define LIGHTMAP_BYTES 4
#define MAX_LIGHTMAPS 128
#define GL_LIGHTMAP_FORMAT GL_RGBA
/* up / down */
#define PITCH 0
@ -355,6 +360,20 @@ typedef struct
unsigned char originalBlueGammaTable [ 256 ];
} glstate_t;
typedef struct
{
int internal_format;
int current_lightmap_texture;
msurface_t *lightmap_surfaces [ MAX_LIGHTMAPS ];
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 ];
} gllightmapstate_t;
extern glconfig_t gl_config;
extern glstate_t gl_state;
extern refimport_t ri;

299
src/refresh/r_lightmap.c Normal file
View file

@ -0,0 +1,299 @@
/*
* 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 );
static void
LM_InitBlock ( void )
{
memset( gl_lms.allocated, 0, sizeof ( gl_lms.allocated ) );
}
static 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 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( 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 */
static 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
GL_BuildPolygonFromSurface ( msurface_t *fa )
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
int vertpage;
float *vec;
float s, t;
glpoly_t *poly;
vec3_t total;
/* reconstruct the polygon */
pedges = currentmodel->edges;
lnumverts = fa->numedges;
vertpage = 0;
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
GL_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
GL_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 */
/* 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 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( 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
GL_EndBuildingLightmaps ( void )
{
LM_UploadBlock( false );
}