1#include "RasterConversion.h"
5 #pragma warning(disable:4244)
8#define STB_DXT_IMPLEMENTATION
15#include "../ClipmapTerrainTypes.h"
17bool Cogs::isCompressible(TextureFormat format)
19 return format == TextureFormat::R8G8B8_UNORM ||
20 format == TextureFormat::R8G8B8A8_UNORM ||
21 format == TextureFormat::R8G8B8A8_UNORM_SRGB;
24Cogs::TextureFormat Cogs::getCompressedFormat(TextureFormat format)
28 case TextureFormat::R8G8B8_UNORM:
29 return TextureFormat::BC3_UNORM;
30 case TextureFormat::R8G8B8A8_UNORM:
31 return TextureFormat::BC3_UNORM;
32 case TextureFormat::R8G8B8A8_UNORM_SRGB:
33 return TextureFormat::BC3_UNORM_SRGB;
35 return TextureFormat::Unknown;
40bool Cogs::isConvertible(TextureFormat format)
42 return format == TextureFormat::B8G8R8 ||
43 format == TextureFormat::B8G8R8A8 ||
44 format == TextureFormat::R8G8B8_UNORM;
47Cogs::TextureFormat Cogs::compressTileData(std::vector<uint8_t> & destination,
48 const uint8_t * source,
49 TextureFormat sourceFormat,
53 const auto targetFormat = getCompressedFormat(sourceFormat);
55 const size_t numBlocksX = width / 4;
56 const size_t numBlocksY = height / 4;
58 const size_t bpp = Cogs::getBlockSize(sourceFormat);
59 const bool hasAlpha = bpp == 4;
61 const size_t rowStride = width * bpp;
63 assert(destination.size() >= (numBlocksX * numBlocksY * 16) &&
"Destination buffer too small.");
65 auto d = destination.data();
67 for (
size_t y = 0; y < numBlocksY; ++y) {
68 for (
size_t x = 0; x < numBlocksX; ++x) {
69 uint8_t pixels[4 * 4 * 4];
71 for (
int yy = 0; yy < 4; ++yy) {
72 for (
int xx = 0; xx < 4; ++xx) {
73 const size_t sourceIndex = (4 * y * rowStride) + (yy * rowStride) + (x * 4 * bpp) + xx * bpp;
75 pixels[yy * 16 + xx * 4 + 0] = source[sourceIndex + 0];
76 pixels[yy * 16 + xx * 4 + 1] = source[sourceIndex + 1];
77 pixels[yy * 16 + xx * 4 + 2] = source[sourceIndex + 2];
78 pixels[yy * 16 + xx * 4 + 3] = hasAlpha ? source[sourceIndex + 3] : 255;
82 stb_compress_dxt_block(d, pixels, hasAlpha ? 1 : 0, STB_DXT_NORMAL);
90Cogs::TextureFormat Cogs::convertBitmapData(
const uint8_t * data,
91 const TileData * tileData,
92 std::vector<uint8_t> & destination)
94 if (tileData->shouldConvert() && !Cogs::isConvertible(tileData->format)) {
95 return TextureFormat::Unknown;
98 const bool swizzle = tileData->shouldConvert() &&
99 (tileData->format == TextureFormat::B8G8R8 || tileData->format == TextureFormat::B8G8R8A8);
100 const int r = swizzle ? 2 : 0;
101 const int b = swizzle ? 0 : 2;
103 auto targetFormat = tileData->shouldConvert() ?
104 (tileData->isLinear() ? TextureFormat::R8G8B8A8_UNORM : TextureFormat::R8G8B8A8_UNORM_SRGB) :
107 const size_t width = tileData->width;
108 const size_t height = tileData->height;
109 const size_t stride = tileData->stride;
110 const bool flip = tileData->shouldFlip();
111 const size_t bpp = Cogs::getBlockSize(tileData->format);
113 destination.resize(getTextureSize(
static_cast<int>(width),
static_cast<int>(height), targetFormat));
115 for (
size_t y = 0; y < height; ++y) {
116 size_t targetLine = flip ? (height - 1 - y) * width : y * width;
118 for (
size_t x = 0; x < width; ++x) {
120 size_t j = 4 * (targetLine + x);
122 destination[j + 0] = data[i + r];
123 destination[j + 1] = data[i + 1];
124 destination[j + 2] = data[i + b];
125 destination[j + 3] = bpp == 4 ? data[i + 3] : 255;
128 data += stride ? stride : width * 4;