Fix mipmapping and add texture compression
This commit is contained in:
parent
deb6387908
commit
43fcf81381
110
src/k3.c
110
src/k3.c
@ -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) {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user