Fix mipmapping and add texture compression
This commit is contained in:
parent
deb6387908
commit
43fcf81381
108
src/k3.c
108
src/k3.c
@ -26,6 +26,13 @@ bool k3IsCore = 0;
|
|||||||
static struct k3GLSLP *basicBlitProgram;
|
static struct k3GLSLP *basicBlitProgram;
|
||||||
static struct k3GLSLP *basicCubemapProgram;
|
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) {
|
void k3StorageRef(struct k3Storage *s) {
|
||||||
s->ref++;
|
s->ref++;
|
||||||
}
|
}
|
||||||
@ -438,6 +445,7 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
|
|||||||
|
|
||||||
GLint internalFmt, externalFmt, intype;
|
GLint internalFmt, externalFmt, intype;
|
||||||
int linearFilter, mipmap;
|
int linearFilter, mipmap;
|
||||||
|
int compressed = 0;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case k3_RAWCOLOR:
|
case k3_RAWCOLOR:
|
||||||
@ -448,7 +456,8 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
|
|||||||
mipmap = 1;
|
mipmap = 1;
|
||||||
break;
|
break;
|
||||||
case k3_NORMAL:
|
case k3_NORMAL:
|
||||||
internalFmt = GL_RGBA;
|
compressed = TextureCompressionEnabled;
|
||||||
|
internalFmt = compressed ? TextureCompressionRGBA : GL_RGBA;
|
||||||
externalFmt = GL_RGBA;
|
externalFmt = GL_RGBA;
|
||||||
intype = GL_UNSIGNED_BYTE;
|
intype = GL_UNSIGNED_BYTE;
|
||||||
linearFilter = 1;
|
linearFilter = 1;
|
||||||
@ -456,8 +465,9 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
|
|||||||
break;
|
break;
|
||||||
case k3_DIFFUSE:
|
case k3_DIFFUSE:
|
||||||
case k3_EMISSION:
|
case k3_EMISSION:
|
||||||
internalFmt = GLAD_GL_EXT_texture_compression_s3tc
|
compressed = TextureCompressionEnabled;
|
||||||
? (GLAD_GL_EXT_texture_sRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
|
internalFmt = compressed
|
||||||
|
? (GLAD_GL_EXT_texture_sRGB ? TextureCompressionSRGBA : TextureCompressionRGBA)
|
||||||
: (GLAD_GL_EXT_texture_sRGB ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8);
|
: (GLAD_GL_EXT_texture_sRGB ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8);
|
||||||
externalFmt = GL_RGBA;
|
externalFmt = GL_RGBA;
|
||||||
intype = GL_UNSIGNED_BYTE;
|
intype = GL_UNSIGNED_BYTE;
|
||||||
@ -480,7 +490,7 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
|
|||||||
mipmap = 1;
|
mipmap = 1;
|
||||||
break;
|
break;
|
||||||
case k3_DEPTH:
|
case k3_DEPTH:
|
||||||
internalFmt = GL_DEPTH_COMPONENT24;
|
internalFmt = GL_DEPTH_COMPONENT32F;
|
||||||
externalFmt = GL_DEPTH_COMPONENT;
|
externalFmt = GL_DEPTH_COMPONENT;
|
||||||
intype = GL_UNSIGNED_INT;
|
intype = GL_UNSIGNED_INT;
|
||||||
if(!k3IsCore) glTexParameteri(target, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
|
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_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
} else {
|
} else {
|
||||||
if(!k3IsCore && !mipmap) {
|
if(!k3IsCore && mipmap) {
|
||||||
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);
|
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||||
} else {
|
|
||||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
}
|
}
|
||||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == k3_DEPTH) {
|
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_S, GL_CLAMP_TO_BORDER);
|
||||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, 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 {
|
} else {
|
||||||
glBindTexture(target, tex->tex);
|
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) {
|
if(k3IsCore && type == k3_ALPHA) {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, 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");
|
k3Log(k3_WARN, "Non-zero index passed for non-cubemap texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
glTexImage2D(target, 0, internalFmt, width, height, 0, externalFmt, intype, data);
|
||||||
|
}
|
||||||
|
|
||||||
if(!tex->cubemap && k3IsCore && mipmap) {
|
if(!tex->cubemap && k3IsCore && mipmap) {
|
||||||
glGenerateMipmap(target);
|
glGenerateMipmap(target);
|
||||||
@ -544,6 +565,8 @@ void k3TexUpdate(struct k3Tex *tex, enum k3TexType type, int index, uint16_t wid
|
|||||||
tex->szX = width;
|
tex->szX = width;
|
||||||
tex->szY = height;
|
tex->szY = height;
|
||||||
tex->szZ = 0;
|
tex->szZ = 0;
|
||||||
|
|
||||||
|
tex->glInternalFormat = internalFmt;
|
||||||
}
|
}
|
||||||
uint32_t k3TexSzX(struct k3Tex *this) {
|
uint32_t k3TexSzX(struct k3Tex *this) {
|
||||||
return this->szX;
|
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() {
|
void k3Init() {
|
||||||
if(GLAD_GL_ARB_debug_output) {
|
if(GLAD_GL_ARB_debug_output) {
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||||
@ -2259,6 +2326,23 @@ void k3Init() {
|
|||||||
"}\n"
|
"}\n"
|
||||||
, NULL), NULL);
|
, 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) {
|
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 szX;
|
||||||
uint32_t szY;
|
uint32_t szY;
|
||||||
uint32_t szZ;
|
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 {
|
struct k3Storage {
|
||||||
|
Loading…
Reference in New Issue
Block a user