From f77b9694e3d2870f62b27589c70c2cf254248db3 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 15 Dec 2015 03:23:55 -0800 Subject: OpenGL2: Switch to RGTC from LATC for normal maps. Also added a RGTC compressor as a workaround on Intel graphics. --- src/renderergl2/tr_extensions.c | 26 ++++- src/renderergl2/tr_glsl.c | 2 +- src/renderergl2/tr_image.c | 248 ++++++++++++++++++++++++---------------- src/renderergl2/tr_local.h | 4 +- 4 files changed, 173 insertions(+), 107 deletions(-) (limited to 'src/renderergl2') diff --git a/src/renderergl2/tr_extensions.c b/src/renderergl2/tr_extensions.c index 811b8377..2c1407b2 100644 --- a/src/renderergl2/tr_extensions.c +++ b/src/renderergl2/tr_extensions.c @@ -585,6 +585,22 @@ void GLimp_InitExtraExtensions() ri.Printf(PRINT_ALL, result[2], extension); } + // GL_ARB_texture_compression + extension = "GL_ARB_texture_compression"; + glRefConfig.arbTextureCompression = qfalse; + if (GLimp_HaveExtension(extension)) + { + qglCompressedTexImage3DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage3DARB"); + qglCompressedTexImage2DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage2DARB"); + qglCompressedTexImage1DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage1DARB"); + qglCompressedTexSubImage3DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage3DARB"); + qglCompressedTexSubImage2DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage2DARB"); + qglCompressedTexSubImage1DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage1DARB"); + qglGetCompressedTexImageARB = (void *)SDL_GL_GetProcAddress("glGetCompressedTexImageARB"); + glRefConfig.arbTextureCompression = qtrue; + ri.Printf(PRINT_ALL, result[glRefConfig.arbTextureCompression], extension); + } + // GL_EXT_framebuffer_multisample extension = "GL_EXT_framebuffer_multisample"; glRefConfig.framebufferMultisample = qfalse; @@ -601,12 +617,12 @@ void GLimp_InitExtraExtensions() glRefConfig.textureCompression = TCR_NONE; - // GL_EXT_texture_compression_latc - extension = "GL_EXT_texture_compression_latc"; + // GL_ARB_texture_compression_rgtc + extension = "GL_ARB_texture_compression_rgtc"; if (GLimp_HaveExtension(extension)) { - if (r_ext_compressed_textures->integer) - glRefConfig.textureCompression |= TCR_LATC; + if (r_ext_compressed_textures->integer && glRefConfig.arbTextureCompression) + glRefConfig.textureCompression |= TCR_RGTC; ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension); } @@ -615,6 +631,8 @@ void GLimp_InitExtraExtensions() ri.Printf(PRINT_ALL, result[2], extension); } + glRefConfig.swizzleNormalmap = r_ext_compressed_textures->integer && !(glRefConfig.textureCompression & TCR_RGTC); + // GL_ARB_texture_compression_bptc extension = "GL_ARB_texture_compression_bptc"; if (GLimp_HaveExtension(extension)) diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index 8ce3a4e7..14e20105 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -1031,7 +1031,7 @@ void GLSL_InitGPUShaders(void) if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); - if (1) + if (glRefConfig.swizzleNormalmap) Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); if (r_hdr->integer && !glRefConfig.floatLightmap) diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 541b1a38..93ee28e9 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -177,15 +177,20 @@ void R_ImageList_f( void ) { format = "sBPTC"; // 128 bits per 16 pixels, so 1 byte per pixel break; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - format = "LATC "; + case GL_COMPRESSED_RG_RGTC2: + format = "RGTC2"; // 128 bits per 16 pixels, so 1 byte per pixel break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: format = "DXT1 "; // 64 bits per 16 pixels, so 4 bits per pixel estSize /= 2; break; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + format = "DXT1a"; + // 64 bits per 16 pixels, so 4 bits per pixel + estSize /= 2; + break; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: format = "DXT5 "; // 128 bits per 16 pixels, so 1 byte per pixel @@ -1332,41 +1337,6 @@ static void R_MipMapsRGB( byte *in, int inWidth, int inHeight) } -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> 1; - out[3] = (in[3] + in[7]) >> 1; - } - return; - } - - for (i=0 ; i> 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; @@ -1657,13 +1627,13 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light if(normalmap) { - if ((!RawImage_HasAlpha(data, numPixels) || (type == IMGTYPE_NORMAL)) && !forceNoCompression && (glRefConfig.textureCompression & TCR_LATC)) - { - internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; - } - else + if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels)) { - 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; } @@ -1680,6 +1650,33 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light internalFormat = GL_RGBA; } } + else + { + if (!forceNoCompression && glRefConfig.textureCompression & TCR_RGTC) + { + internalFormat = GL_COMPRESSED_RG_RGTC2; + } + else 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; + } + else if (r_texturebits->integer == 16) + { + internalFormat = GL_RGB5; + } + else if (r_texturebits->integer == 32) + { + internalFormat = GL_RGB8; + } + else + { + internalFormat = GL_RGB; + } + } } else if(lightMap) { @@ -1775,10 +1772,101 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light return internalFormat; } +static void CompressMonoBlock(byte outdata[8], const byte indata[16]) +{ + int hi, lo, diff, bias, outbyte, shift, i; + byte *p = outdata; + + hi = lo = indata[0]; + for (i = 1; i < 16; i++) + { + hi = MAX(indata[i], hi); + lo = MIN(indata[i], lo); + } + + *p++ = hi; + *p++ = lo; + + diff = hi - lo; + + if (diff == 0) + { + outbyte = (hi == 255) ? 255 : 0; + + for (i = 0; i < 6; i++) + *p++ = outbyte; + + return; + } + + bias = diff / 2 - lo * 7; + outbyte = shift = 0; + for (i = 0; i < 16; i++) + { + const byte fixIndex[8] = { 1, 7, 6, 5, 4, 3, 2, 0 }; + byte index = fixIndex[(indata[i] * 7 + bias) / diff]; + + outbyte |= index << shift; + shift += 3; + if (shift >= 8) + { + *p++ = outbyte & 0xff; + shift -= 8; + outbyte >>= 8; + } + } +} + +static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int mip) +{ + int wBlocks, hBlocks, y, x, size; + byte *compressedData, *p; + + wBlocks = (width + 3) / 4; + hBlocks = (height + 3) / 4; + size = wBlocks * hBlocks * 16; + + p = compressedData = ri.Hunk_AllocateTempMemory(size); + for (y = 0; y < height; y += 4) + { + int oh = MIN(4, height - y); + + for (x = 0; x < width; x += 4) + { + byte workingData[16]; + int component; + + int ow = MIN(4, width - x); + + for (component = 0; component < 2; component++) + { + int ox, oy; + + for (oy = 0; oy < oh; oy++) + for (ox = 0; ox < ow; ox++) + workingData[oy * 4 + ox] = data[((y + oy) * width + x + ox) * 4 + component]; + + // dupe data to fill + for (oy = 0; oy < 4; oy++) + for (ox = (oy < oh) ? ow : 0; ox < 4; ox++) + workingData[oy * 4 + ox] = workingData[(oy % oh) * 4 + ox % ow]; + + CompressMonoBlock(p, workingData); + p += 8; + } + } + } + + qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData); + + ri.Hunk_FreeTempMemory(compressedData); +} + 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; + qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); switch(internalFormat) { @@ -1802,7 +1890,12 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei if ( subtexture ) qglTexSubImage2D( GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data ); else - qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data ); + { + if (rgtc) + RawImage_UploadToRgtc2Texture(data, width, height, 0); + else + qglTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data); + } if (flags & IMGFLAG_MIPMAP) { @@ -1815,14 +1908,7 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei { if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) { - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } + R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); } else { @@ -1849,7 +1935,10 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei } else { - qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data ); + if (rgtc) + RawImage_UploadToRgtc2Texture(data, width, height, miplevel); + else + qglTexImage2D(GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); } } } @@ -1903,25 +1992,11 @@ static void Upload32( byte *data, int width, int height, imgType_t type, imgFlag } } - // normals are always swizzled - if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) + if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)) { 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 if ( ( scaled_width == width ) && ( scaled_height == height ) ) { @@ -1943,14 +2018,7 @@ static void Upload32( byte *data, int width, int height, imgType_t type, imgFlag if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) { - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } + R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); } else { @@ -2186,26 +2254,11 @@ 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; byte *data = pic; - // normals are always swizzled - if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT) + if (glRefConfig.swizzleNormalmap && (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT)) { RawImage_SwizzleRA(pic, width, height); } - // 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 ); @@ -2238,14 +2291,7 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT) { - if (image->internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } + R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); } else { diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 73681f32..0a1dc5fe 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1381,7 +1381,7 @@ typedef enum { typedef enum { TCR_NONE = 0x0000, - TCR_LATC = 0x0001, + TCR_RGTC = 0x0001, TCR_BPTC = 0x0002, } textureCompressionRef_t; @@ -1405,7 +1405,9 @@ typedef struct { qboolean textureFloat; qboolean halfFloatPixel; qboolean packedDepthStencil; + qboolean arbTextureCompression; textureCompressionRef_t textureCompression; + qboolean swizzleNormalmap; qboolean framebufferMultisample; qboolean framebufferBlit; -- cgit