From 0c8b36e12129dc4a3a905d178492a2a31f0807a1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 29 Oct 2018 13:18:48 +0100 Subject: [PATCH] - moved the texture resizer to hwrenderer. This is pure math and will be shareable with Vulkan. --- src/gl/textures/gl_hwtexture.cpp | 99 ------------------------- src/gl/textures/gl_hwtexture.h | 1 - src/hwrenderer/textures/hw_ihwtexture.h | 2 + src/hwrenderer/textures/hw_material.cpp | 97 ++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 100 deletions(-) diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index 3651c016c..363ef87fc 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -71,105 +71,6 @@ int TexFormat[]={ //=========================================================================== unsigned int FHardwareTexture::lastbound[FHardwareTexture::MAX_TEXTURES]; -//=========================================================================== -// -// Quick'n dirty image rescaling. -// -// This will only be used when the source texture is larger than -// what the hardware can manage (extremely rare in Doom) -// -// Code taken from wxWidgets -// -//=========================================================================== - -struct BoxPrecalc -{ - int boxStart; - int boxEnd; -}; - -static void ResampleBoxPrecalc(TArray& boxes, int oldDim) -{ - int newDim = boxes.Size(); - const double scale_factor_1 = double(oldDim) / newDim; - const int scale_factor_2 = (int)(scale_factor_1 / 2); - - for (int dst = 0; dst < newDim; ++dst) - { - // Source pixel in the Y direction - const int src_p = int(dst * scale_factor_1); - - BoxPrecalc& precalc = boxes[dst]; - precalc.boxStart = clamp(int(src_p - scale_factor_1 / 2.0 + 1), 0, oldDim - 1); - precalc.boxEnd = clamp(MAX(precalc.boxStart + 1, int(src_p + scale_factor_2)), 0, oldDim - 1); - } -} - -void FHardwareTexture::Resize(int swidth, int sheight, int width, int height, unsigned char *src_data, unsigned char *dst_data) -{ - - // This function implements a simple pre-blur/box averaging method for - // downsampling that gives reasonably smooth results To scale the image - // down we will need to gather a grid of pixels of the size of the scale - // factor in each direction and then do an averaging of the pixels. - - TArray vPrecalcs(height, true); - TArray hPrecalcs(width, true); - - ResampleBoxPrecalc(vPrecalcs, sheight); - ResampleBoxPrecalc(hPrecalcs, swidth); - - int averaged_pixels, averaged_alpha, src_pixel_index; - double sum_r, sum_g, sum_b, sum_a; - - for (int y = 0; y < height; y++) // Destination image - Y direction - { - // Source pixel in the Y direction - const BoxPrecalc& vPrecalc = vPrecalcs[y]; - - for (int x = 0; x < width; x++) // Destination image - X direction - { - // Source pixel in the X direction - const BoxPrecalc& hPrecalc = hPrecalcs[x]; - - // Box of pixels to average - averaged_pixels = 0; - averaged_alpha = 0; - sum_r = sum_g = sum_b = sum_a = 0.0; - - for (int j = vPrecalc.boxStart; j <= vPrecalc.boxEnd; ++j) - { - for (int i = hPrecalc.boxStart; i <= hPrecalc.boxEnd; ++i) - { - // Calculate the actual index in our source pixels - src_pixel_index = j * swidth + i; - - int a = src_data[src_pixel_index * 4 + 3]; - if (a > 0) // do not use color from fully transparent pixels - { - sum_r += src_data[src_pixel_index * 4 + 0]; - sum_g += src_data[src_pixel_index * 4 + 1]; - sum_b += src_data[src_pixel_index * 4 + 2]; - sum_a += a; - averaged_pixels++; - } - averaged_alpha++; - - } - } - - // Calculate the average from the sum and number of averaged pixels - dst_data[0] = (unsigned char)xs_CRoundToInt(sum_r / averaged_pixels); - dst_data[1] = (unsigned char)xs_CRoundToInt(sum_g / averaged_pixels); - dst_data[2] = (unsigned char)xs_CRoundToInt(sum_b / averaged_pixels); - dst_data[3] = (unsigned char)xs_CRoundToInt(sum_a / averaged_alpha); - dst_data += 4; - } - } -} - - - //=========================================================================== // // Loads the texture image into the hardware diff --git a/src/gl/textures/gl_hwtexture.h b/src/gl/textures/gl_hwtexture.h index ae9a22783..a1e9f8740 100644 --- a/src/gl/textures/gl_hwtexture.h +++ b/src/gl/textures/gl_hwtexture.h @@ -66,7 +66,6 @@ private: TranslatedTexture * GetTexID(int translation); int GetDepthBuffer(int w, int h); - void Resize(int swidth, int sheight, int width, int height, unsigned char *src_data, unsigned char *dst_data); public: FHardwareTexture(bool nocompress); diff --git a/src/hwrenderer/textures/hw_ihwtexture.h b/src/hwrenderer/textures/hw_ihwtexture.h index b91291806..10447e5b1 100644 --- a/src/hwrenderer/textures/hw_ihwtexture.h +++ b/src/hwrenderer/textures/hw_ihwtexture.h @@ -27,5 +27,7 @@ public: virtual void Clean(bool all) = 0; virtual void CleanUnused(SpriteHits &usedtranslations) = 0; + + void Resize(int swidth, int sheight, int width, int height, unsigned char *src_data, unsigned char *dst_data); }; diff --git a/src/hwrenderer/textures/hw_material.cpp b/src/hwrenderer/textures/hw_material.cpp index 905860204..6bd514ccb 100644 --- a/src/hwrenderer/textures/hw_material.cpp +++ b/src/hwrenderer/textures/hw_material.cpp @@ -33,6 +33,103 @@ EXTERN_CVAR(Bool, gl_texture_usehires) extern TArray usershaders; +//=========================================================================== +// +// Quick'n dirty image rescaling. +// +// This will only be used when the source texture is larger than +// what the hardware can manage (extremely rare in Doom) +// +// Code taken from wxWidgets +// +//=========================================================================== + +struct BoxPrecalc +{ + int boxStart; + int boxEnd; +}; + +static void ResampleBoxPrecalc(TArray& boxes, int oldDim) +{ + int newDim = boxes.Size(); + const double scale_factor_1 = double(oldDim) / newDim; + const int scale_factor_2 = (int)(scale_factor_1 / 2); + + for (int dst = 0; dst < newDim; ++dst) + { + // Source pixel in the Y direction + const int src_p = int(dst * scale_factor_1); + + BoxPrecalc& precalc = boxes[dst]; + precalc.boxStart = clamp(int(src_p - scale_factor_1 / 2.0 + 1), 0, oldDim - 1); + precalc.boxEnd = clamp(MAX(precalc.boxStart + 1, int(src_p + scale_factor_2)), 0, oldDim - 1); + } +} + +void IHardwareTexture::Resize(int swidth, int sheight, int width, int height, unsigned char *src_data, unsigned char *dst_data) +{ + + // This function implements a simple pre-blur/box averaging method for + // downsampling that gives reasonably smooth results To scale the image + // down we will need to gather a grid of pixels of the size of the scale + // factor in each direction and then do an averaging of the pixels. + + TArray vPrecalcs(height, true); + TArray hPrecalcs(width, true); + + ResampleBoxPrecalc(vPrecalcs, sheight); + ResampleBoxPrecalc(hPrecalcs, swidth); + + int averaged_pixels, averaged_alpha, src_pixel_index; + double sum_r, sum_g, sum_b, sum_a; + + for (int y = 0; y < height; y++) // Destination image - Y direction + { + // Source pixel in the Y direction + const BoxPrecalc& vPrecalc = vPrecalcs[y]; + + for (int x = 0; x < width; x++) // Destination image - X direction + { + // Source pixel in the X direction + const BoxPrecalc& hPrecalc = hPrecalcs[x]; + + // Box of pixels to average + averaged_pixels = 0; + averaged_alpha = 0; + sum_r = sum_g = sum_b = sum_a = 0.0; + + for (int j = vPrecalc.boxStart; j <= vPrecalc.boxEnd; ++j) + { + for (int i = hPrecalc.boxStart; i <= hPrecalc.boxEnd; ++i) + { + // Calculate the actual index in our source pixels + src_pixel_index = j * swidth + i; + + int a = src_data[src_pixel_index * 4 + 3]; + if (a > 0) // do not use color from fully transparent pixels + { + sum_r += src_data[src_pixel_index * 4 + 0]; + sum_g += src_data[src_pixel_index * 4 + 1]; + sum_b += src_data[src_pixel_index * 4 + 2]; + sum_a += a; + averaged_pixels++; + } + averaged_alpha++; + + } + } + + // Calculate the average from the sum and number of averaged pixels + dst_data[0] = (unsigned char)xs_CRoundToInt(sum_r / averaged_pixels); + dst_data[1] = (unsigned char)xs_CRoundToInt(sum_g / averaged_pixels); + dst_data[2] = (unsigned char)xs_CRoundToInt(sum_b / averaged_pixels); + dst_data[3] = (unsigned char)xs_CRoundToInt(sum_a / averaged_alpha); + dst_data += 4; + } + } +} + //=========================================================================== // //