Fix mipmapping and add texture compression

This commit is contained in:
mid 2025-05-10 18:15:39 +03:00
parent deb6387908
commit 43fcf81381
2 changed files with 106 additions and 13 deletions

110
src/k3.c
View File

@ -26,6 +26,13 @@ bool k3IsCore = 0;
static struct k3GLSLP *basicBlitProgram;
static struct k3GLSLP *basicCubemapProgram;
typedef void*(*TextureOfflineCompressorFunc)(const void *pixels, uint16_t width, uint16_t height, GLenum externalFmt, GLenum intype, size_t *compressedSize);
static bool TextureCompressionEnabled;
static GLenum TextureCompressionRGBA;
static GLenum TextureCompressionSRGBA;
static TextureOfflineCompressorFunc TextureOfflineCompressor;
void k3StorageRef(struct k3Storage *s) {
s->ref++;
}
@ -438,6 +445,7 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
GLint internalFmt, externalFmt, intype;
int linearFilter, mipmap;
int compressed = 0;
switch(type) {
case k3_RAWCOLOR:
@ -448,7 +456,8 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
mipmap = 1;
break;
case k3_NORMAL:
internalFmt = GL_RGBA;
compressed = TextureCompressionEnabled;
internalFmt = compressed ? TextureCompressionRGBA : GL_RGBA;
externalFmt = GL_RGBA;
intype = GL_UNSIGNED_BYTE;
linearFilter = 1;
@ -456,8 +465,9 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
break;
case k3_DIFFUSE:
case k3_EMISSION:
internalFmt = GLAD_GL_EXT_texture_compression_s3tc
? (GLAD_GL_EXT_texture_sRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
compressed = TextureCompressionEnabled;
internalFmt = compressed
? (GLAD_GL_EXT_texture_sRGB ? TextureCompressionSRGBA : TextureCompressionRGBA)
: (GLAD_GL_EXT_texture_sRGB ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8);
externalFmt = GL_RGBA;
intype = GL_UNSIGNED_BYTE;
@ -480,7 +490,7 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
mipmap = 1;
break;
case k3_DEPTH:
internalFmt = GL_DEPTH_COMPONENT24;
internalFmt = GL_DEPTH_COMPONENT32F;
externalFmt = GL_DEPTH_COMPONENT;
intype = GL_UNSIGNED_INT;
if(!k3IsCore) glTexParameteri(target, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
@ -502,12 +512,9 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
if(!k3IsCore && !mipmap) {
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
} else {
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if(!k3IsCore && mipmap) {
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
}
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if(type == k3_DEPTH) {
@ -515,13 +522,18 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
}
if(!tex->cubemap && mipmap) {
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, linearFilter ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, linearFilter ? GL_LINEAR : GL_NEAREST);
} else {
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, linearFilter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, linearFilter ? GL_LINEAR : GL_NEAREST);
}
} else {
glBindTexture(target, tex->tex);
}
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, linearFilter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, linearFilter ? GL_LINEAR : GL_NEAREST);
if(k3IsCore && type == k3_ALPHA) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
@ -535,7 +547,16 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
k3Log(k3_WARN, "Non-zero index passed for non-cubemap texture");
}
glTexImage2D(target, 0, internalFmt, width, height, 0, externalFmt, intype, data);
if(compressed && TextureOfflineCompressor) {
size_t len;
data = TextureOfflineCompressor(data, width, height, externalFmt, intype, &len);
glCompressedTexImage2D(target, 0, internalFmt, width, height, 0, len, data);
free(data);
} else {
glTexImage2D(target, 0, internalFmt, width, height, 0, externalFmt, intype, data);
}
if(!tex->cubemap && k3IsCore && mipmap) {
glGenerateMipmap(target);
@ -544,6 +565,8 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
tex->szX = width;
tex->szY = height;
tex->szZ = 0;
tex->glInternalFormat = internalFmt;
}
uint32_t k3TexSzX(struct k3Tex *this) {
return this->szX;
@ -2201,6 +2224,50 @@ void GlCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei
}
}
#include"compr/bc7enc.h"
static void *compress_rgba_bc7(const void *pixels, uint16_t width, uint16_t height, GLenum externalFmt, GLenum intype, size_t *compressedSize) {
static bool called = false;
if(!called) {
bc7enc_compress_block_init();
called = true;
}
assert(externalFmt == GL_RGBA);
assert(intype == GL_UNSIGNED_BYTE);
uint16_t blockWidth = (width + 3) / 4;
uint16_t blockHeight = (height + 3) / 4;
size_t blocks = blockWidth * blockHeight;
*compressedSize = blocks * 16;
uint8_t *output = calloc(blocks, 16);
#pragma omp parallel
{
bc7enc_compress_block_params p;
bc7enc_compress_block_params_init(&p);
#pragma omp for
for(size_t blk = 0; blk < blocks; blk++) {
uint8_t blockPixels[64];
uint16_t blkX = blk % blockWidth;
uint16_t blkY = blk / blockWidth;
memcpy(blockPixels + 0, pixels + 4 * (((blkY * 4) + 0) * width + (blkX * 4)), 16);
memcpy(blockPixels +16, pixels + 4 * (((blkY * 4) + 1) * width + (blkX * 4)), 16);
memcpy(blockPixels +32, pixels + 4 * (((blkY * 4) + 2) * width + (blkX * 4)), 16);
memcpy(blockPixels +48, pixels + 4 * (((blkY * 4) + 3) * width + (blkX * 4)), 16);
bc7enc_compress_block(output + blk * 16, blockPixels, &p);
}
}
return output;
}
void k3Init() {
if(GLAD_GL_ARB_debug_output) {
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
@ -2259,6 +2326,23 @@ void k3Init() {
"}\n"
, NULL), NULL);
}
/*if(GLAD_GL_KHR_texture_compression_astc_ldr) {
TextureCompressionEnabled = true;
} else */ if(GLAD_GL_ARB_texture_compression_bptc || GLAD_GL_VERSION_4_2) {
TextureCompressionEnabled = true;
TextureCompressionSRGBA = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
TextureCompressionRGBA = GL_COMPRESSED_RGBA_BPTC_UNORM;
TextureOfflineCompressor = compress_rgba_bc7;
} else if(GL_EXT_texture_compression_s3tc) {
TextureCompressionEnabled = true;
TextureCompressionSRGBA = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
TextureCompressionRGBA = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
}
static size_t preprocess(char *src, const char*(*ldr)(const char *fn), const char ***strs, GLuint **sizes) {

View File

@ -20,6 +20,15 @@ struct k3Tex {
uint32_t szX;
uint32_t szY;
uint32_t szZ;
GLuint glInternalFormat;
GLuint glExternalFormat;
GLuint glInType;
bool mipmap;
// Asynchronous decoding
uint8_t deferredRemaining;
uint8_t *deferredData[6];
struct k3Tex *deferredNext;
};
struct k3Storage {