diff --git a/src/refresh/header/local.h b/src/refresh/header/local.h index ad7b625c..2267d65f 100644 --- a/src/refresh/header/local.h +++ b/src/refresh/header/local.h @@ -178,6 +178,7 @@ extern cvar_t *gl_lightlevel; extern cvar_t *gl_vertex_arrays; extern cvar_t *gl_ext_swapinterval; +extern cvar_t *gl_ext_palettedtexture; extern cvar_t *gl_ext_multitexture; extern cvar_t *gl_ext_pointparameters; extern cvar_t *gl_ext_compiled_vertex_array; @@ -312,6 +313,8 @@ image_t *R_FindImage ( char *name, imagetype_t type ); void R_TextureMode ( char *string ); void R_ImageList_f ( void ); +void R_SetTexturePalette ( unsigned palette [ 256 ] ); + void R_InitImages ( void ); void R_ShutdownImages ( void ); diff --git a/src/refresh/r_image.c b/src/refresh/r_image.c index e88595d2..c1f6a39a 100644 --- a/src/refresh/r_image.c +++ b/src/refresh/r_image.c @@ -127,6 +127,30 @@ typedef struct int upload_width, upload_height; qboolean uploaded_paletted; +void +R_SetTexturePalette ( unsigned palette [ 256 ] ) +{ + int i; + unsigned char temptable [ 768 ]; + + if ( qglColorTableEXT && gl_ext_palettedtexture->value ) + { + for ( i = 0; i < 256; i++ ) + { + temptable [ i * 3 + 0 ] = ( palette [ i ] >> 0 ) & 0xff; + temptable [ i * 3 + 1 ] = ( palette [ i ] >> 8 ) & 0xff; + temptable [ i * 3 + 2 ] = ( palette [ i ] >> 16 ) & 0xff; + } + + qglColorTableEXT( GL_SHARED_TEXTURE_PALETTE_EXT, + GL_RGB, + 256, + GL_RGB, + GL_UNSIGNED_BYTE, + temptable ); + } +} + void R_EnableMultitexture ( qboolean enable ) { @@ -582,6 +606,7 @@ R_Upload32 ( unsigned *data, int width, int height, qboolean mipmap ) { int samples; unsigned scaled [ 256 * 256 ]; + unsigned char paletted_texture [ 256 * 256 ]; int scaled_width, scaled_height; int i, c; byte *scan; @@ -677,7 +702,25 @@ R_Upload32 ( unsigned *data, int width, int height, qboolean mipmap ) { if ( !mipmap ) { - qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); + if ( qglColorTableEXT && gl_ext_palettedtexture->value && ( samples == gl_solid_format ) ) + { + uploaded_paletted = true; + R_BuildPalettedTexture( paletted_texture, (unsigned char *) data, scaled_width, scaled_height ); + qglTexImage2D( GL_TEXTURE_2D, + 0, + GL_COLOR_INDEX8_EXT, + scaled_width, + scaled_height, + 0, + GL_COLOR_INDEX, + GL_UNSIGNED_BYTE, + paletted_texture ); + } + else + { + qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); + } + goto done; } @@ -689,7 +732,25 @@ R_Upload32 ( unsigned *data, int width, int height, qboolean mipmap ) } R_LightScaleTexture( scaled, scaled_width, scaled_height, !mipmap ); - qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled ); + + if ( qglColorTableEXT && gl_ext_palettedtexture->value && ( samples == gl_solid_format ) ) + { + uploaded_paletted = true; + R_BuildPalettedTexture( paletted_texture, (unsigned char *) scaled, scaled_width, scaled_height ); + qglTexImage2D( GL_TEXTURE_2D, + 0, + GL_COLOR_INDEX8_EXT, + scaled_width, + scaled_height, + 0, + GL_COLOR_INDEX, + GL_UNSIGNED_BYTE, + paletted_texture ); + } + else + { + qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled ); + } if ( mipmap ) { @@ -714,7 +775,25 @@ R_Upload32 ( unsigned *data, int width, int height, qboolean mipmap ) } miplevel++; - qglTexImage2D( GL_TEXTURE_2D, miplevel, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled ); + + if ( qglColorTableEXT && gl_ext_palettedtexture->value && ( samples == gl_solid_format ) ) + { + uploaded_paletted = true; + R_BuildPalettedTexture( paletted_texture, (unsigned char *) scaled, scaled_width, scaled_height ); + qglTexImage2D( GL_TEXTURE_2D, + miplevel, + GL_COLOR_INDEX8_EXT, + scaled_width, + scaled_height, + 0, + GL_COLOR_INDEX, + GL_UNSIGNED_BYTE, + paletted_texture ); + } + else + { + qglTexImage2D( GL_TEXTURE_2D, miplevel, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled ); + } } } @@ -751,44 +830,64 @@ R_Upload8 ( byte *data, int width, int height, qboolean mipmap, qboolean is_sky ri.Sys_Error( ERR_DROP, "R_Upload8: too large" ); } - for ( i = 0; i < s; i++ ) + if ( qglColorTableEXT && gl_ext_palettedtexture->value && is_sky ) { - p = data [ i ]; - trans [ i ] = d_8to24table [ p ]; + qglTexImage2D( GL_TEXTURE_2D, + 0, + GL_COLOR_INDEX8_EXT, + width, + height, + 0, + GL_COLOR_INDEX, + GL_UNSIGNED_BYTE, + data ); - /* transparent, so scan around for another color - * to avoid alpha fringes */ - if ( p == 255 ) - { - if ( ( i > width ) && ( data [ i - width ] != 255 ) ) - { - p = data [ i - width ]; - } - else if ( ( i < s - width ) && ( data [ i + width ] != 255 ) ) - { - p = data [ i + width ]; - } - else if ( ( i > 0 ) && ( data [ i - 1 ] != 255 ) ) - { - p = data [ i - 1 ]; - } - else if ( ( i < s - 1 ) && ( data [ i + 1 ] != 255 ) ) - { - p = data [ i + 1 ]; - } - else - { - p = 0; - } + qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max ); + qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max ); - /* copy rgb components */ - ( (byte *) &trans [ i ] ) [ 0 ] = ( (byte *) &d_8to24table [ p ] ) [ 0 ]; - ( (byte *) &trans [ i ] ) [ 1 ] = ( (byte *) &d_8to24table [ p ] ) [ 1 ]; - ( (byte *) &trans [ i ] ) [ 2 ] = ( (byte *) &d_8to24table [ p ] ) [ 2 ]; - } + return ( false ); /* SBF: FIXME - what is the correct return value? */ } + else + { + for ( i = 0; i < s; i++ ) + { + p = data [ i ]; + trans [ i ] = d_8to24table [ p ]; - return ( R_Upload32( trans, width, height, mipmap ) ); + /* transparent, so scan around for another color + * to avoid alpha fringes */ + if ( p == 255 ) + { + if ( ( i > width ) && ( data [ i - width ] != 255 ) ) + { + p = data [ i - width ]; + } + else if ( ( i < s - width ) && ( data [ i + width ] != 255 ) ) + { + p = data [ i + width ]; + } + else if ( ( i > 0 ) && ( data [ i - 1 ] != 255 ) ) + { + p = data [ i - 1 ]; + } + else if ( ( i < s - 1 ) && ( data [ i + 1 ] != 255 ) ) + { + p = data [ i + 1 ]; + } + else + { + p = 0; + } + + /* copy rgb components */ + ( (byte *) &trans [ i ] ) [ 0 ] = ( (byte *) &d_8to24table [ p ] ) [ 0 ]; + ( (byte *) &trans [ i ] ) [ 1 ] = ( (byte *) &d_8to24table [ p ] ) [ 1 ]; + ( (byte *) &trans [ i ] ) [ 2 ] = ( (byte *) &d_8to24table [ p ] ) [ 2 ]; + } + } + + return ( R_Upload32( trans, width, height, mipmap ) ); + } } /* diff --git a/src/refresh/r_main.c b/src/refresh/r_main.c index e551a5c0..c2b03c33 100644 --- a/src/refresh/r_main.c +++ b/src/refresh/r_main.c @@ -114,6 +114,7 @@ cvar_t *gl_particle_att_b; cvar_t *gl_particle_att_c; cvar_t *gl_ext_swapinterval; +cvar_t *gl_ext_palettedtexture; cvar_t *gl_ext_multitexture; cvar_t *gl_ext_pointparameters; cvar_t *gl_ext_compiled_vertex_array; @@ -980,6 +981,7 @@ R_Register ( void ) gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "0", CVAR_ARCHIVE ); gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE ); + gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE ); gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE ); gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE ); gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE ); @@ -1130,6 +1132,8 @@ R_Init ( void *hinstance, void *hWnd ) ri.Cvar_Set( "scr_drawall", "0" ); gl_config.allow_cds = true; + ri.Con_Printf( PRINT_ALL, "\nProbing for OpenGL extensions:\n"); + /* grab extensions */ if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) || strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) ) @@ -1161,6 +1165,27 @@ R_Init ( void *hinstance, void *hWnd ) ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" ); } + if ( !qglColorTableEXT && + strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) && + strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) ) + { + if ( gl_ext_palettedtexture->value ) + { + ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" ); + qglColorTableEXT = + ( void (APIENTRY *) ( GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid * ) )qwglGetProcAddress( + "glColorTableEXT" ); + } + else + { + ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" ); + } + } + else + { + ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" ); + } + if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) ) { if ( gl_ext_multitexture->value ) @@ -1364,6 +1389,8 @@ R_SetPalette ( const unsigned char *palette ) } } + R_SetTexturePalette( r_rawpalette ); + qglClearColor( 0, 0, 0, 0 ); qglClear( GL_COLOR_BUFFER_BIT ); qglClearColor( 1, 0, 0.5, 0.5 ); diff --git a/src/refresh/r_misc.c b/src/refresh/r_misc.c index e838c405..037cab11 100644 --- a/src/refresh/r_misc.c +++ b/src/refresh/r_misc.c @@ -22,7 +22,7 @@ * Misc refresher functions * * ======================================================================= - */ + */ #include "header/local.h" @@ -35,7 +35,7 @@ byte dottexture [ 8 ] [ 8 ] = { { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, -}; +}; typedef struct _TargaHeader { @@ -45,7 +45,6 @@ typedef struct _TargaHeader unsigned short x_origin, y_origin, width, height; unsigned char pixel_size, attributes; } TargaHeader; - void R_InitParticleTexture ( void ) @@ -204,6 +203,13 @@ R_SetDefaultState ( void ) qglPointParameterfvEXT( GL_DISTANCE_ATTENUATION_EXT, attenuations ); } + if ( qglColorTableEXT && gl_ext_palettedtexture->value ) + { + qglEnable( GL_SHARED_TEXTURE_PALETTE_EXT ); + + R_SetTexturePalette( d_8to24table ); + } + R_UpdateSwapInterval(); } diff --git a/src/refresh/r_warp.c b/src/refresh/r_warp.c index 0af4c91f..a864f7e2 100644 --- a/src/refresh/r_warp.c +++ b/src/refresh/r_warp.c @@ -22,14 +22,14 @@ * Warps. Used on water surfaces und for skybox rotation. * * ======================================================================= - */ + */ #include "header/local.h" #define TURBSCALE ( 256.0 / ( 2 * M_PI ) ) #define SUBDIVIDE_SIZE 64 #define ON_EPSILON 0.1 /* point on plane side epsilon */ -#define MAX_CLIP_VERTS 64 +#define MAX_CLIP_VERTS 64 extern model_t *loadmodel; char skyname [ MAX_QPATH ]; @@ -40,7 +40,7 @@ msurface_t *warpface; int skytexorder [ 6 ] = { 0, 2, 1, 3, 4, 5 }; /* 3dstudio environment map names */ -char *suf [ 6 ] = { "rt", "bk", "lf", "ft", "up", "dn" }; +char *suf [ 6 ] = { "rt", "bk", "lf", "ft", "up", "dn" }; float r_turbsin[] = { #include "constants/warpsin.h" @@ -80,7 +80,7 @@ int vec_to_st [ 6 ] [ 3 ] = { float skymins [ 2 ] [ 6 ], skymaxs [ 2 ] [ 6 ]; float sky_min, sky_max; - + void R_BoundPoly ( int numverts, float *verts, vec3_t mins, vec3_t maxs ) { @@ -458,7 +458,7 @@ R_ClipSkyPolygon ( int nump, vec3_t vecs, int stage ) } if ( stage == 6 ) - { + { /* fully clipped, so draw it */ R_DrawSkyPolygon( nump, vecs ); return; @@ -490,7 +490,7 @@ R_ClipSkyPolygon ( int nump, vec3_t vecs, int stage ) } if ( !front || !back ) - { + { /* not clipped */ R_ClipSkyPolygon( nump, vecs, stage + 1 ); return; @@ -656,7 +656,7 @@ R_DrawSkyBox ( void ) for ( i = 0; i < 6; i++ ) { if ( skyrotate ) - { + { skymins [ 0 ] [ i ] = -1; skymins [ 1 ] [ i ] = -1; skymaxs [ 0 ] [ i ] = 1; @@ -694,7 +694,14 @@ R_SetSky ( char *name, float rotate, vec3_t axis ) for ( i = 0; i < 6; i++ ) { - Com_sprintf( pathname, sizeof ( pathname ), "env/%s%s.tga", skyname, suf [ i ] ); + if ( qglColorTableEXT && gl_ext_palettedtexture->value ) + { + Com_sprintf( pathname, sizeof ( pathname ), "env/%s%s.pcx", skyname, suf [ i ] ); + } + else + { + Com_sprintf( pathname, sizeof ( pathname ), "env/%s%s.tga", skyname, suf [ i ] ); + } sky_images [ i ] = R_FindImage( pathname, it_sky );