Minor image code cleanup.

Added support for LATC(normalmaps) and BPTC(everything else) image compression
This commit is contained in:
James Canete 2012-04-06 01:44:08 +00:00
parent 9f6328817a
commit f9551a6179
6 changed files with 320 additions and 176 deletions

View file

@ -330,6 +330,22 @@ extern void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLs
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
#endif #endif
#ifndef GL_EXT_texture_compression_latc
#define GL_EXT_texture_compression_latc
#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
#endif
#ifndef GL_ARB_texture_compression_bptc
#define GL_ARB_texture_compression_bptc
#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
#endif
#if defined(WIN32) #if defined(WIN32)
// WGL_ARB_create_context // WGL_ARB_create_context
#ifndef WGL_ARB_create_context #ifndef WGL_ARB_create_context

View file

@ -290,11 +290,11 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
{ {
for (i = 0; i < tr.numLightmaps; i++) for (i = 0; i < tr.numLightmaps; i++)
{ {
tr.lightmaps[i] = R_CreateImage2(va("_fatlightmap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat ); tr.lightmaps[i] = R_CreateImage(va("_fatlightmap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat );
if (tr.worldDeluxeMapping) if (tr.worldDeluxeMapping)
{ {
tr.deluxemaps[i] = R_CreateImage2(va("_fatdeluxemap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGFLAG_NORMALIZED | IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 ); tr.deluxemaps[i] = R_CreateImage(va("_fatdeluxemap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGTYPE_DELUXE, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 );
} }
} }
} }
@ -464,7 +464,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
if (r_mergeLightmaps->integer) if (r_mergeLightmaps->integer)
R_UpdateSubImage(tr.lightmaps[lightmapnum], image, xoff, yoff, tr.lightmapSize, tr.lightmapSize); R_UpdateSubImage(tr.lightmaps[lightmapnum], image, xoff, yoff, tr.lightmapSize, tr.lightmapSize);
else else
tr.lightmaps[i] = R_CreateImage2(va("*lightmap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat ); tr.lightmaps[i] = R_CreateImage(va("*lightmap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat );
if (hdrLightmap) if (hdrLightmap)
ri.FS_FreeFile(hdrLightmap); ri.FS_FreeFile(hdrLightmap);
@ -496,7 +496,7 @@ static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
} }
else else
{ {
tr.deluxemaps[i] = R_CreateImage2(va("*deluxemap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGFLAG_NORMALIZED | IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 ); tr.deluxemaps[i] = R_CreateImage(va("*deluxemap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGTYPE_DELUXE, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 );
} }
} }
} }

View file

@ -439,7 +439,7 @@ void GLimp_InitExtraExtensions()
} }
// GL_ARB_half_float_pixel // GL_ARB_half_float_pixel
extension = "GL_ARB_texture_float"; extension = "GL_ARB_half_float_pixel";
glRefConfig.halfFloatPixel = qfalse; glRefConfig.halfFloatPixel = qfalse;
if( GLimp_HaveExtension( extension ) ) if( GLimp_HaveExtension( extension ) )
{ {
@ -580,4 +580,34 @@ void GLimp_InitExtraExtensions()
{ {
ri.Printf(PRINT_ALL, result[2], extension); ri.Printf(PRINT_ALL, result[2], extension);
} }
glRefConfig.textureCompression = TCR_NONE;
// GL_EXT_texture_compression_latc
extension = "GL_EXT_texture_compression_latc";
if (GLimp_HaveExtension(extension))
{
if (r_ext_compressed_textures->integer)
glRefConfig.textureCompression |= TCR_LATC;
ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
// GL_ARB_texture_compression_bptc
extension = "GL_ARB_texture_compression_bptc";
if (GLimp_HaveExtension(extension))
{
if (r_ext_compressed_textures->integer >= 2)
glRefConfig.textureCompression |= TCR_BPTC;
ri.Printf(PRINT_ALL, result[(r_ext_compressed_textures->integer >= 2) ? 1 : 0], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
} }

View file

@ -182,31 +182,63 @@ void R_ImageList_f( void ) {
ri.Printf( PRINT_ALL, "RGB8" ); ri.Printf( PRINT_ALL, "RGB8" );
break; break;
case GL_RGB4_S3TC: case GL_RGB4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
ri.Printf( PRINT_ALL, "S3TC " ); ri.Printf( PRINT_ALL, "S3TC " );
break; break;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
ri.Printf( PRINT_ALL, "DXT1 " );
break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
ri.Printf( PRINT_ALL, "DXT5 " );
break;
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
ri.Printf( PRINT_ALL, "LATC " );
break;
case GL_RGBA4: case GL_RGBA4:
ri.Printf( PRINT_ALL, "RGBA4" ); ri.Printf( PRINT_ALL, "RGBA4" );
break; break;
case GL_RGB5: case GL_RGB5:
ri.Printf( PRINT_ALL, "RGB5 " ); ri.Printf( PRINT_ALL, "RGB5 " );
break; break;
case GL_SRGB_EXT:
ri.Printf( PRINT_ALL, "sRGB " );
break;
case GL_SRGB8_EXT:
ri.Printf( PRINT_ALL, "sRGB8" );
break;
case GL_SRGB_ALPHA_EXT:
case GL_SRGB8_ALPHA8_EXT:
ri.Printf( PRINT_ALL, "sRGBA" );
break;
/*
case GL_SLUMINANCE_EXT:
break;
case GL_SLUMINANCE8_EXT:
break;
case GL_SLUMINANCE_ALPHA_EXT:
break;
case GL_SLUMINANCE8_ALPHA8_EXT:
break;
*/
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
ri.Printf( PRINT_ALL, "sDXT1" );
break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
ri.Printf( PRINT_ALL, "sDXT5" );
break;
case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
ri.Printf( PRINT_ALL, "BPTC " );
break;
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
ri.Printf( PRINT_ALL, "sBPTC" );
break;
default: default:
ri.Printf( PRINT_ALL, "???? " ); ri.Printf( PRINT_ALL, "???? " );
} }
switch ( image->wrapClampMode ) { if (image->flags & IMGFLAG_CLAMPTOEDGE)
case GL_REPEAT:
ri.Printf( PRINT_ALL, "rept " );
break;
case GL_CLAMP_TO_EDGE:
ri.Printf( PRINT_ALL, "clmp " ); ri.Printf( PRINT_ALL, "clmp " );
break; else
default: ri.Printf( PRINT_ALL, "rept " );
ri.Printf( PRINT_ALL, "%4i ", image->wrapClampMode );
break;
}
ri.Printf( PRINT_ALL, " %s\n", image->imgName ); ri.Printf( PRINT_ALL, " %s\n", image->imgName );
} }
@ -1349,9 +1381,44 @@ static void R_MipMap (byte *in, int width, int height) {
} }
static void R_MipMapNormalHeight (byte *in, int width, int height, qboolean swizzle) { static void R_MipMapLuminanceAlpha (const byte *in, byte *out, int width, int height)
{
int i, j, row;
if ( width == 1 && height == 1 ) {
return;
}
row = width * 4;
width >>= 1;
height >>= 1;
if ( width == 0 || height == 0 ) {
width += height; // get largest
for (i=0 ; i<width ; i++, out+=4, in+=8 ) {
out[0] =
out[1] =
out[2] = (in[0] + in[4]) >> 1;
out[3] = (in[3] + in[7]) >> 1;
}
return;
}
for (i=0 ; i<height ; i++, in+=row) {
for (j=0 ; j<width ; j++, out+=4, in+=8) {
out[0] =
out[1] =
out[2] = (in[0] + in[4] + in[row ] + in[row+4]) >> 2;
out[3] = (in[3] + in[7] + in[row+3] + in[row+7]) >> 2;
}
}
}
static void R_MipMapNormalHeight (const byte *in, byte *out, int width, int height, qboolean swizzle)
{
int i, j; int i, j;
byte *out;
int row; int row;
int sx = swizzle ? 3 : 0; int sx = swizzle ? 3 : 0;
int sa = swizzle ? 0 : 3; int sa = swizzle ? 0 : 3;
@ -1361,38 +1428,9 @@ static void R_MipMapNormalHeight (byte *in, int width, int height, qboolean swiz
} }
row = width * 4; row = width * 4;
out = in;
width >>= 1; width >>= 1;
height >>= 1; height >>= 1;
if ( width == 0 || height == 0 ) {
width += height; // get largest
for (i=0 ; i<width ; i++, out+=4, in+=8 ) {
vec3_t v;
v[0] = OffsetByteToFloat(in[sx ]);
v[1] = OffsetByteToFloat(in[1 ]);
v[2] = OffsetByteToFloat(in[2 ]);
v[0] += OffsetByteToFloat(in[sx+4]);
v[1] += OffsetByteToFloat(in[ 5]);
v[2] += OffsetByteToFloat(in[ 6]);
VectorNormalizeFast(v);
//v[0] *= 0.5f;
//v[1] *= 0.5f;
//v[2] = 1.0f - v[0] * v[0] - v[1] * v[1];
//v[2] = sqrt(MAX(v[2], 0.0f));
out[sx] = FloatToOffsetByte(v[0]);
out[1 ] = FloatToOffsetByte(v[1]);
out[2 ] = FloatToOffsetByte(v[2]);
out[sa] = MAX(in[sa], in[sa+4]);
}
return;
}
for (i=0 ; i<height ; i++, in+=row) { for (i=0 ; i<height ; i++, in+=row) {
for (j=0 ; j<width ; j++, out+=4, in+=8) { for (j=0 ; j<width ; j++, out+=4, in+=8) {
vec3_t v; vec3_t v;
@ -1493,7 +1531,7 @@ RawImage_ScaleToPower2
=============== ===============
*/ */
static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_height, int *inout_scaled_width, int *inout_scaled_height, imgFlags_t flags, byte **resampledBuffer) static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_height, int *inout_scaled_width, int *inout_scaled_height, imgType_t type, imgFlags_t flags, byte **resampledBuffer)
{ {
int width = *inout_width; int width = *inout_width;
int height = *inout_height; int height = *inout_height;
@ -1565,7 +1603,7 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he
} }
} }
if (!(flags & IMGFLAG_NORMALIZED)) if (type == IMGTYPE_COLORALPHA)
RGBAtoYCoCgA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); RGBAtoYCoCgA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
while (scaled_width < finalwidth || scaled_height < finalheight) while (scaled_width < finalwidth || scaled_height < finalheight)
@ -1573,14 +1611,14 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he
scaled_width <<= 1; scaled_width <<= 1;
scaled_height <<= 1; scaled_height <<= 1;
FCBIByBlock(*resampledBuffer, scaled_width, scaled_height, clampToEdge, flags & IMGFLAG_NORMALIZED); FCBIByBlock(*resampledBuffer, scaled_width, scaled_height, clampToEdge, (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT));
} }
if (!(flags & IMGFLAG_NORMALIZED)) if (type == IMGTYPE_COLORALPHA)
{ {
YCoCgAtoRGBA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); YCoCgAtoRGBA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
} }
else else if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
{ {
FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
} }
@ -1659,14 +1697,40 @@ static qboolean RawImage_HasAlpha(const byte *scan, int numPixels)
return qfalse; return qfalse;
} }
static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgFlags_t flags) static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgType_t type, imgFlags_t flags)
{ {
int samples = 3; int samples = 3;
GLenum internalFormat = GL_RGB; GLenum internalFormat = GL_RGB;
qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION); qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION);
qboolean normalmap4 = (flags & IMGFLAG_SWIZZLE) && (flags & IMGFLAG_NORMALIZED); qboolean normalmap = (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT);
if(lightMap) if(normalmap)
{
if ((!RawImage_HasAlpha(data, numPixels) || (type == IMGTYPE_NORMAL)) && !forceNoCompression && (glRefConfig.textureCompression & TCR_LATC))
{
internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
}
else
{
if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB )
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
else if ( r_texturebits->integer == 16 )
{
internalFormat = GL_RGBA4;
}
else if ( r_texturebits->integer == 32 )
{
internalFormat = GL_RGBA8;
}
else
{
internalFormat = GL_RGBA;
}
}
}
else if(lightMap)
{ {
samples = 4; samples = 4;
if(r_greyscale->integer) if(r_greyscale->integer)
@ -1676,7 +1740,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light
} }
else else
{ {
if (normalmap4 || RawImage_HasAlpha(data, numPixels)) if (RawImage_HasAlpha(data, numPixels))
{ {
samples = 4; samples = 4;
} }
@ -1695,7 +1759,11 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light
} }
else else
{ {
if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB ) if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) )
{
internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
}
else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB )
{ {
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
} }
@ -1730,7 +1798,11 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light
} }
else else
{ {
if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB ) if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) )
{
internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
}
else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB )
{ {
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
} }
@ -1797,6 +1869,10 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
break; break;
case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
break;
} }
} }
} }
@ -1805,7 +1881,7 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light
} }
static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgFlags_t flags, qboolean subtexture ) static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
{ {
int dataFormat, dataType; int dataFormat, dataType;
@ -1842,9 +1918,16 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei
{ {
if (data) if (data)
{ {
if (flags & IMGFLAG_NORMALIZED) if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
{ {
R_MipMapNormalHeight( data, width, height, flags & IMGFLAG_SWIZZLE ); if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
{
R_MipMapLuminanceAlpha( data, data, width, height );
}
else
{
R_MipMapNormalHeight( data, data, width, height, qtrue);
}
} }
else if (flags & IMGFLAG_SRGB) else if (flags & IMGFLAG_SRGB)
{ {
@ -1889,17 +1972,16 @@ Upload32
=============== ===============
*/ */
extern qboolean charSet; extern qboolean charSet;
static void Upload32( byte *data, int width, int height, imgFlags_t flags, static void Upload32( byte *data, int width, int height, imgType_t type, imgFlags_t flags,
qboolean lightMap, int *format, int *pUploadWidth, int *pUploadHeight) qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight)
{ {
byte *scaledBuffer = NULL; byte *scaledBuffer = NULL;
byte *resampledBuffer = NULL; byte *resampledBuffer = NULL;
int scaled_width, scaled_height; int scaled_width, scaled_height;
int i, c; int i, c;
byte *scan; byte *scan;
GLenum internalFormat = *format;
RawImage_ScaleToPower2(&data, &width, &height, &scaled_width, &scaled_height, flags, &resampledBuffer); RawImage_ScaleToPower2(&data, &width, &height, &scaled_width, &scaled_height, type, flags, &resampledBuffer);
scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
@ -1931,24 +2013,34 @@ static void Upload32( byte *data, int width, int height, imgFlags_t flags,
} }
} }
if (!internalFormat) // normals are always swizzled
internalFormat = RawImage_GetFormat(scan, c, lightMap, flags); if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
if (flags & IMGFLAG_SWIZZLE)
{ {
RawImage_SwizzleRA(data, width, height); RawImage_SwizzleRA(data, width, height);
} }
// LATC2 is only used for normals
if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
{
byte *in = data;
int c = width * height;
while (c--)
{
in[0] = in[1];
in[2] = in[1];
in += 4;
}
}
// copy or resample data as appropriate for first MIP level // copy or resample data as appropriate for first MIP level
if ( ( scaled_width == width ) && if ( ( scaled_width == width ) &&
( scaled_height == height ) ) { ( scaled_height == height ) ) {
if (!(flags & IMGFLAG_MIPMAP)) if (!(flags & IMGFLAG_MIPMAP))
{ {
RawImage_UploadTexture( data, 0, 0, scaled_width, scaled_height, internalFormat, flags, qfalse ); RawImage_UploadTexture( data, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse );
//qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); //qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
*pUploadWidth = scaled_width; *pUploadWidth = scaled_width;
*pUploadHeight = scaled_height; *pUploadHeight = scaled_height;
*format = internalFormat;
goto done; goto done;
} }
@ -1985,9 +2077,8 @@ static void Upload32( byte *data, int width, int height, imgFlags_t flags,
*pUploadWidth = scaled_width; *pUploadWidth = scaled_width;
*pUploadHeight = scaled_height; *pUploadHeight = scaled_height;
*format = internalFormat;
RawImage_UploadTexture(scaledBuffer, 0, 0, scaled_width, scaled_height, internalFormat, flags, qfalse); RawImage_UploadTexture(scaledBuffer, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse);
done: done:
@ -2018,22 +2109,17 @@ done:
} }
static void EmptyTexture( int width, int height, imgFlags_t flags, static void EmptyTexture( int width, int height, imgType_t type, imgFlags_t flags,
qboolean lightMap, int *format, int *pUploadWidth, int *pUploadHeight ) qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight )
{ {
int scaled_width, scaled_height; int scaled_width, scaled_height;
GLenum internalFormat = *format;
RawImage_ScaleToPower2(NULL, &width, &height, &scaled_width, &scaled_height, flags, NULL); RawImage_ScaleToPower2(NULL, &width, &height, &scaled_width, &scaled_height, type, flags, NULL);
if (!internalFormat)
internalFormat = RawImage_GetFormat(NULL, 0, lightMap, flags);
*pUploadWidth = scaled_width; *pUploadWidth = scaled_width;
*pUploadHeight = scaled_height; *pUploadHeight = scaled_height;
*format = internalFormat;
RawImage_UploadTexture(NULL, 0, 0, scaled_width, scaled_height, internalFormat, flags, qfalse); RawImage_UploadTexture(NULL, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse);
if (flags & IMGFLAG_MIPMAP) if (flags & IMGFLAG_MIPMAP)
{ {
@ -2064,7 +2150,7 @@ R_CreateImage
This is the only way any image_t are created This is the only way any image_t are created
================ ================
*/ */
image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, imgFlags_t flags, int internalFormat ) { image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) {
image_t *image; image_t *image;
qboolean isLightmap = qfalse; qboolean isLightmap = qfalse;
long hash; long hash;
@ -2085,6 +2171,7 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, img
image->texnum = 1024 + tr.numImages; image->texnum = 1024 + tr.numImages;
tr.numImages++; tr.numImages++;
image->type = type;
image->flags = flags; image->flags = flags;
strcpy (image->imgName, name); strcpy (image->imgName, name);
@ -2095,8 +2182,17 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, img
glWrapClampMode = GL_CLAMP_TO_EDGE; glWrapClampMode = GL_CLAMP_TO_EDGE;
else else
glWrapClampMode = GL_REPEAT; glWrapClampMode = GL_REPEAT;
image->wrapClampMode = glWrapClampMode;
if (!internalFormat)
{
if (image->flags & IMGFLAG_CUBEMAP)
internalFormat = GL_RGBA8;
else
internalFormat = RawImage_GetFormat(pic, width * height, isLightmap, image->type, image->flags);
}
image->internalFormat = internalFormat; image->internalFormat = internalFormat;
// lightmaps are always allocated on TMU 1 // lightmaps are always allocated on TMU 1
if ( qglActiveTextureARB && isLightmap ) { if ( qglActiveTextureARB && isLightmap ) {
@ -2125,9 +2221,6 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, img
qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
if (!internalFormat)
image->internalFormat = GL_RGBA8;
image->uploadWidth = width; image->uploadWidth = width;
image->uploadHeight = height; image->uploadHeight = height;
} }
@ -2137,14 +2230,14 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, img
if (pic) if (pic)
{ {
Upload32( pic, image->width, image->height, image->flags, Upload32( pic, image->width, image->height, image->type, image->flags,
isLightmap, &image->internalFormat, &image->uploadWidth, isLightmap, image->internalFormat, &image->uploadWidth,
&image->uploadHeight ); &image->uploadHeight );
} }
else else
{ {
EmptyTexture(image->width, image->height, image->flags, EmptyTexture(image->width, image->height, image->type, image->flags,
isLightmap, &image->internalFormat, &image->uploadWidth, isLightmap, image->internalFormat, &image->uploadWidth,
&image->uploadHeight ); &image->uploadHeight );
} }
@ -2161,40 +2254,6 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, img
return image; return image;
} }
image_t *R_CreateImage( const char *name, byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode )
{
imgFlags_t flags = IMGFLAG_NONE;
if (mipmap)
flags |= IMGFLAG_MIPMAP;
if (allowPicmip)
flags |= IMGFLAG_PICMIP;
if (glWrapClampMode == GL_CLAMP_TO_EDGE)
flags |= IMGFLAG_CLAMPTOEDGE;
return R_CreateImage2( name, pic, width, height, flags, 0 );
}
image_t *R_CreateCubeImage( const char *name, byte *pic, int width, int height,
qboolean mipmap, qboolean allowPicmip, int glWrapClampMode )
{
imgFlags_t flags = IMGFLAG_CUBEMAP;
if (mipmap)
flags |= IMGFLAG_MIPMAP;
if (allowPicmip)
flags |= IMGFLAG_PICMIP;
if (glWrapClampMode == GL_CLAMP_TO_EDGE)
flags |= IMGFLAG_CLAMPTOEDGE;
return R_CreateImage2( name, pic, width, height, flags, 0 );
}
void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ) void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height )
{ {
byte *scaledBuffer = NULL; byte *scaledBuffer = NULL;
@ -2202,12 +2261,27 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h
int scaled_width, scaled_height, scaled_x, scaled_y; int scaled_width, scaled_height, scaled_x, scaled_y;
byte *data = pic; byte *data = pic;
if (image->flags & IMGFLAG_SWIZZLE) // normals are always swizzled
if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT)
{ {
RawImage_SwizzleRA(pic, width, height); RawImage_SwizzleRA(pic, width, height);
} }
RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->flags, &resampledBuffer); // LATC2 is only used for normals
if (image->internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
{
byte *in = data;
int c = width * height;
while (c--)
{
in[0] = in[1];
in[2] = in[1];
in += 4;
}
}
RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->type, image->flags, &resampledBuffer);
scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
@ -2224,7 +2298,7 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h
{ {
scaled_x = x * scaled_width / width; scaled_x = x * scaled_width / width;
scaled_y = y * scaled_height / height; scaled_y = y * scaled_height / height;
RawImage_UploadTexture( data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->flags, qtrue ); RawImage_UploadTexture( data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue );
//qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, data ); //qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, data );
GL_CheckErrors(); GL_CheckErrors();
@ -2265,7 +2339,7 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h
scaled_x = x * scaled_width / width; scaled_x = x * scaled_width / width;
scaled_y = y * scaled_height / height; scaled_y = y * scaled_height / height;
RawImage_UploadTexture( (byte *)data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->flags, qtrue ); RawImage_UploadTexture( (byte *)data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue );
done: done:
@ -2392,7 +2466,7 @@ Finds or loads the given image.
Returns NULL if it fails, not a default image. Returns NULL if it fails, not a default image.
============== ==============
*/ */
image_t *R_FindImageFile( const char *name, imgFlags_t flags ) image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
{ {
image_t *image; image_t *image;
int width, height; int width, height;
@ -2428,20 +2502,20 @@ image_t *R_FindImageFile( const char *name, imgFlags_t flags )
return NULL; return NULL;
} }
if (r_normalMapping->integer && !(flags & IMGFLAG_NORMALIZED) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP)) if (r_normalMapping->integer && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP))
{ {
char normalName[MAX_QPATH]; char normalName[MAX_QPATH];
image_t *normalImage; image_t *normalImage;
int normalWidth, normalHeight; int normalWidth, normalHeight;
imgFlags_t normalFlags; imgFlags_t normalFlags;
normalFlags = (flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_SWIZZLE | IMGFLAG_NORMALIZED | IMGFLAG_NOLIGHTSCALE; normalFlags = (flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE;
COM_StripExtension(name, normalName, MAX_QPATH); COM_StripExtension(name, normalName, MAX_QPATH);
Q_strcat(normalName, MAX_QPATH, "_n"); Q_strcat(normalName, MAX_QPATH, "_n");
// find normalmap in case it's there // find normalmap in case it's there
normalImage = R_FindImageFile(normalName, normalFlags); normalImage = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
// if not, generate it // if not, generate it
if (normalImage == NULL) if (normalImage == NULL)
@ -2470,12 +2544,12 @@ image_t *R_FindImageFile( const char *name, imgFlags_t flags )
} }
YCoCgAtoRGBA(pic, pic, width, height); YCoCgAtoRGBA(pic, pic, width, height);
R_CreateImage2( normalName, normalPic, normalWidth, normalHeight, normalFlags, 0 ); R_CreateImage( normalName, normalPic, normalWidth, normalHeight, IMGTYPE_NORMAL, normalFlags, 0 );
ri.Free( normalPic ); ri.Free( normalPic );
} }
} }
image = R_CreateImage2( ( char * ) name, pic, width, height, flags, 0 ); image = R_CreateImage( ( char * ) name, pic, width, height, type, flags, 0 );
ri.Free( pic ); ri.Free( pic );
return image; return image;
} }
@ -2511,7 +2585,7 @@ static void R_CreateDlightImage( void ) {
data[y][x][3] = 255; data[y][x][3] = 255;
} }
} }
tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE ); tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 );
} }
@ -2598,7 +2672,7 @@ static void R_CreateFogImage( void ) {
// standard openGL clamping doesn't really do what we want -- it includes // standard openGL clamping doesn't really do what we want -- it includes
// the border color at the edges. OpenGL 1.2 has clamp-to-edge, which does // the border color at the edges. OpenGL 1.2 has clamp-to-edge, which does
// what we want. // what we want.
tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, qfalse, qfalse, GL_CLAMP_TO_EDGE ); tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 );
ri.Hunk_FreeTempMemory( data ); ri.Hunk_FreeTempMemory( data );
borderColor[0] = 1.0; borderColor[0] = 1.0;
@ -2642,7 +2716,7 @@ static void R_CreateDefaultImage( void ) {
data[x][DEFAULT_SIZE-1][2] = data[x][DEFAULT_SIZE-1][2] =
data[x][DEFAULT_SIZE-1][3] = 255; data[x][DEFAULT_SIZE-1][3] = 255;
} }
tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qtrue, qfalse, GL_REPEAT ); tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_MIPMAP, 0);
} }
/* /*
@ -2658,13 +2732,13 @@ void R_CreateBuiltinImages( void ) {
// we use a solid white image instead of disabling texturing // we use a solid white image instead of disabling texturing
Com_Memset( data, 255, sizeof( data ) ); Com_Memset( data, 255, sizeof( data ) );
tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT ); tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, IMGTYPE_COLORALPHA, IMGFLAG_NONE, 0);
if (r_dlightMode->integer >= 2) if (r_dlightMode->integer >= 2)
{ {
for( x = 0; x < MAX_DLIGHTS; x++) for( x = 0; x < MAX_DLIGHTS; x++)
{ {
tr.shadowCubemaps[x] = R_CreateCubeImage(va("*shadowcubemap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE ); tr.shadowCubemaps[x] = R_CreateImage(va("*shadowcubemap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE | IMGFLAG_CUBEMAP, 0);
} }
} }
@ -2679,12 +2753,12 @@ void R_CreateBuiltinImages( void ) {
} }
} }
tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT ); tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, IMGTYPE_COLORALPHA, IMGFLAG_NONE, 0);
for(x=0;x<32;x++) { for(x=0;x<32;x++) {
// scratchimage is usually used for cinematic drawing // scratchimage is usually used for cinematic drawing
tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qtrue, GL_CLAMP_TO_EDGE ); tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_PICMIP | IMGFLAG_CLAMPTOEDGE, 0);
} }
R_CreateDlightImage(); R_CreateDlightImage();
@ -2708,9 +2782,9 @@ void R_CreateBuiltinImages( void ) {
if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat) if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
hdrFormat = GL_RGB16F_ARB; hdrFormat = GL_RGB16F_ARB;
tr.renderImage = R_CreateImage2("_render", NULL, width, height, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); tr.renderImage = R_CreateImage("_render", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
#ifdef REACTION #ifdef REACTION
tr.godRaysImage = R_CreateImage2("*godRays", NULL, width, height, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); tr.godRaysImage = R_CreateImage("*godRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
#endif #endif
{ {
@ -2721,13 +2795,13 @@ void R_CreateBuiltinImages( void ) {
else else
format = GL_RGBA8; format = GL_RGBA8;
tr.screenScratchImage = R_CreateImage2("*screenScratch", NULL, width, height, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, format); tr.screenScratchImage = R_CreateImage("*screenScratch", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, format);
} }
if (glRefConfig.framebufferObject) if (glRefConfig.framebufferObject)
{ {
tr.renderDepthImage = R_CreateImage2("*renderdepth", NULL, width, height, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); tr.renderDepthImage = R_CreateImage("*renderdepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
tr.textureDepthImage = R_CreateImage2("*texturedepth", NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); tr.textureDepthImage = R_CreateImage("*texturedepth", NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
} }
{ {
@ -2751,23 +2825,23 @@ void R_CreateBuiltinImages( void ) {
p = data; p = data;
} }
tr.calcLevelsImage = R_CreateImage2("*calcLevels", p, 1, 1,IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); tr.calcLevelsImage = R_CreateImage("*calcLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
tr.fixedLevelsImage = R_CreateImage2("*fixedLevels", p, 1, 1, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); tr.fixedLevelsImage = R_CreateImage("*fixedLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
} }
for (x = 0; x < 2; x++) for (x = 0; x < 2; x++)
{ {
tr.textureScratchImage[x] = R_CreateImage2(va("*textureScratch%d", x), NULL, 256, 256, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); tr.textureScratchImage[x] = R_CreateImage(va("*textureScratch%d", x), NULL, 256, 256, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
} }
for (x = 0; x < 2; x++) for (x = 0; x < 2; x++)
{ {
tr.quarterImage[x] = R_CreateImage2(va("*quarter%d", x), NULL, 512, 512, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); tr.quarterImage[x] = R_CreateImage(va("*quarter%d", x), NULL, 512, 512, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
} }
} }
for( x = 0; x < MAX_DRAWN_PSHADOWS; x++) for( x = 0; x < MAX_DRAWN_PSHADOWS; x++)
{ {
tr.pshadowMaps[x] = R_CreateImage2(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
} }
} }

View file

@ -106,19 +106,25 @@ typedef struct {
float transformMatrix[16]; float transformMatrix[16];
} orientationr_t; } orientationr_t;
typedef enum
{
IMGTYPE_COLORALPHA, // for color, lightmap, diffuse, and specular
IMGTYPE_NORMAL,
IMGTYPE_NORMALHEIGHT,
IMGTYPE_DELUXE, // normals are swizzled, deluxe are not
} imgType_t;
typedef enum typedef enum
{ {
IMGFLAG_NONE = 0x0000, IMGFLAG_NONE = 0x0000,
IMGFLAG_MIPMAP = 0x0001, IMGFLAG_MIPMAP = 0x0001,
IMGFLAG_PICMIP = 0x0002, IMGFLAG_PICMIP = 0x0002,
IMGFLAG_CUBEMAP = 0x0004, IMGFLAG_CUBEMAP = 0x0004,
IMGFLAG_SWIZZLE = 0x0008,
IMGFLAG_NO_COMPRESSION = 0x0010, IMGFLAG_NO_COMPRESSION = 0x0010,
IMGFLAG_NORMALIZED = 0x0020, IMGFLAG_NOLIGHTSCALE = 0x0020,
IMGFLAG_NOLIGHTSCALE = 0x0040, IMGFLAG_CLAMPTOEDGE = 0x0040,
IMGFLAG_CLAMPTOEDGE = 0x0080, IMGFLAG_SRGB = 0x0080,
IMGFLAG_SRGB = 0x0100, IMGFLAG_GENNORMALMAP = 0x0100,
IMGFLAG_GENNORMALMAP = 0x0200,
} imgFlags_t; } imgFlags_t;
typedef struct image_s { typedef struct image_s {
@ -132,8 +138,8 @@ typedef struct image_s {
int internalFormat; int internalFormat;
int TMU; // only needed for voodoo2 int TMU; // only needed for voodoo2
imgType_t type;
imgFlags_t flags; imgFlags_t flags;
int wrapClampMode; // GL_CLAMP_TO_EDGE or GL_REPEAT
struct image_s* next; struct image_s* next;
} image_t; } image_t;
@ -1587,6 +1593,12 @@ typedef enum {
MI_ATI MI_ATI
} memInfo_t; } memInfo_t;
typedef enum {
TCR_NONE = 0x0000,
TCR_LATC = 0x0001,
TCR_BPTC = 0x0002,
} textureCompressionRef_t;
// We can't change glConfig_t without breaking DLL/vms compatibility, so // We can't change glConfig_t without breaking DLL/vms compatibility, so
// store extensions we have here. // store extensions we have here.
typedef struct { typedef struct {
@ -1603,6 +1615,7 @@ typedef struct {
qboolean textureFloat; qboolean textureFloat;
qboolean halfFloatPixel; qboolean halfFloatPixel;
qboolean packedDepthStencil; qboolean packedDepthStencil;
textureCompressionRef_t textureCompression;
qboolean framebufferMultisample; qboolean framebufferMultisample;
qboolean framebufferBlit; qboolean framebufferBlit;
@ -2120,10 +2133,8 @@ qboolean R_GetEntityToken( char *buffer, int size );
model_t *R_AllocModel( void ); model_t *R_AllocModel( void );
void R_Init( void ); void R_Init( void );
image_t *R_FindImageFile( const char *name, imgFlags_t flags ); image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags );
image_t *R_CreateImage( const char *name, byte *pic, int width, int height, qboolean mipmap image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat );
, qboolean allowPicmip, int wrapClampMode );
image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, imgFlags_t flags, int internalFormat );
void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ); void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height );
qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ); qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode );

View file

@ -652,6 +652,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
} }
else else
{ {
imgType_t type = IMGTYPE_COLORALPHA;
imgFlags_t flags = IMGFLAG_NONE; imgFlags_t flags = IMGFLAG_NONE;
if (!shader.noMipMaps) if (!shader.noMipMaps)
@ -662,7 +663,11 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP) if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP)
{ {
flags |= IMGFLAG_SWIZZLE | IMGFLAG_NORMALIZED | IMGFLAG_NOLIGHTSCALE; type = IMGTYPE_NORMAL;
flags |= IMGFLAG_NOLIGHTSCALE;
if (stage->type == ST_NORMALPARALLAXMAP)
type = IMGTYPE_NORMALHEIGHT;
} }
else else
{ {
@ -673,7 +678,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
flags |= IMGFLAG_SRGB; flags |= IMGFLAG_SRGB;
} }
stage->bundle[0].image[0] = R_FindImageFile( token, flags ); stage->bundle[0].image[0] = R_FindImageFile( token, type, flags );
if ( !stage->bundle[0].image[0] ) if ( !stage->bundle[0].image[0] )
{ {
@ -687,6 +692,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
// //
else if ( !Q_stricmp( token, "clampmap" ) ) else if ( !Q_stricmp( token, "clampmap" ) )
{ {
imgType_t type = IMGTYPE_COLORALPHA;
imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_SRGB; imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_SRGB;
token = COM_ParseExt( text, qfalse ); token = COM_ParseExt( text, qfalse );
@ -704,7 +710,11 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP) if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP)
{ {
flags |= IMGFLAG_SWIZZLE | IMGFLAG_NORMALIZED | IMGFLAG_NOLIGHTSCALE; type = IMGTYPE_NORMAL;
flags |= IMGFLAG_NOLIGHTSCALE;
if (stage->type == ST_NORMALPARALLAXMAP)
type = IMGTYPE_NORMALHEIGHT;
} }
else else
{ {
@ -716,7 +726,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
} }
stage->bundle[0].image[0] = R_FindImageFile( token, flags ); stage->bundle[0].image[0] = R_FindImageFile( token, type, flags );
if ( !stage->bundle[0].image[0] ) if ( !stage->bundle[0].image[0] )
{ {
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
@ -754,7 +764,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
if (!shader.noPicMip) if (!shader.noPicMip)
flags |= IMGFLAG_PICMIP; flags |= IMGFLAG_PICMIP;
stage->bundle[0].image[num] = R_FindImageFile( token, flags ); stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags );
if ( !stage->bundle[0].image[num] ) if ( !stage->bundle[0].image[num] )
{ {
ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
@ -889,7 +899,10 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
} }
else if(!Q_stricmp(token, "normalParallaxMap") || !Q_stricmp(token, "bumpParallaxMap")) else if(!Q_stricmp(token, "normalParallaxMap") || !Q_stricmp(token, "bumpParallaxMap"))
{ {
stage->type = ST_NORMALPARALLAXMAP; if (r_parallaxMapping->integer)
stage->type = ST_NORMALPARALLAXMAP;
else
stage->type = ST_NORMALMAP;
} }
else if(!Q_stricmp(token, "specularMap")) else if(!Q_stricmp(token, "specularMap"))
{ {
@ -1373,7 +1386,7 @@ static void ParseSkyParms( char **text ) {
for (i=0 ; i<6 ; i++) { for (i=0 ; i<6 ; i++) {
Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga" Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
, token, suf[i] ); , token, suf[i] );
shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP | IMGFLAG_CLAMPTOEDGE ); shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP | IMGFLAG_CLAMPTOEDGE );
if ( !shader.sky.outerbox[i] ) { if ( !shader.sky.outerbox[i] ) {
shader.sky.outerbox[i] = tr.defaultImage; shader.sky.outerbox[i] = tr.defaultImage;
@ -1404,7 +1417,7 @@ static void ParseSkyParms( char **text ) {
for (i=0 ; i<6 ; i++) { for (i=0 ; i<6 ; i++) {
Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga" Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
, token, suf[i] ); , token, suf[i] );
shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP ); shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP );
if ( !shader.sky.innerbox[i] ) { if ( !shader.sky.innerbox[i] ) {
shader.sky.innerbox[i] = tr.defaultImage; shader.sky.innerbox[i] = tr.defaultImage;
} }
@ -2149,12 +2162,12 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
{ {
char normalName[MAX_QPATH]; char normalName[MAX_QPATH];
image_t *normalImg; image_t *normalImg;
imgFlags_t normalFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_SWIZZLE | IMGFLAG_NORMALIZED | IMGFLAG_NOLIGHTSCALE; imgFlags_t normalFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE;
COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH); COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH);
Q_strcat(normalName, MAX_QPATH, "_n"); Q_strcat(normalName, MAX_QPATH, "_n");
normalImg = R_FindImageFile(normalName, normalFlags); normalImg = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
if (normalImg) if (normalImg)
{ {
@ -3107,7 +3120,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag
flags |= IMGFLAG_CLAMPTOEDGE; flags |= IMGFLAG_CLAMPTOEDGE;
} }
image = R_FindImageFile( name, flags ); image = R_FindImageFile( name, IMGTYPE_COLORALPHA, flags );
if ( !image ) { if ( !image ) {
ri.Printf( PRINT_DEVELOPER, "Couldn't find image file for shader %s\n", name ); ri.Printf( PRINT_DEVELOPER, "Couldn't find image file for shader %s\n", name );
shader.defaultShader = qtrue; shader.defaultShader = qtrue;