diff options
author | SmileTheory <SmileTheory@gmail.com> | 2015-12-15 03:23:55 -0800 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2016-04-07 11:13:36 +0100 |
commit | f77b9694e3d2870f62b27589c70c2cf254248db3 (patch) | |
tree | 21a9690615b67de2bf62032f048c254d044d4fcf /src/renderergl2/tr_image.c | |
parent | 9cdedf11eff894db8f9f572ab52eae37fdacf473 (diff) |
OpenGL2: Switch to RGTC from LATC for normal maps. Also added a RGTC compressor as a workaround on Intel graphics.
Diffstat (limited to 'src/renderergl2/tr_image.c')
-rw-r--r-- | src/renderergl2/tr_image.c | 248 |
1 files changed, 147 insertions, 101 deletions
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<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; @@ -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 { |