5#define STB_IMAGE_IMPLEMENTATION 1
7#define STBI_NO_LINEAR 1
17#define STBI_NO_THREAD_LOCALS 1
25#define DDSD_CAPS 0x00000001
26#define DDSD_HEIGHT 0x00000002
27#define DDSD_WIDTH 0x00000004
28#define DDSD_PITCH 0x00000008
29#define DDSD_PIXELFORMAT 0x00001000
30#define DDSD_MIPMAPCOUNT 0x00020000
31#define DDSD_LINEARSIZE 0x00080000
32#define DDSD_DEPTH 0x00800000
35#define DDPF_ALPHAPIXELS 0x00000001
36#define DDPF_FOURCC 0x00000004
37#define DDPF_RGB 0x00000040
38#define DDPF_PALETTEINDEXED8 0x00000020
42#define DDSCAPS_COMPLEX 0x00000008
43#define DDSCAPS_TEXTURE 0x00001000
44#define DDSCAPS_MIPMAP 0x00400000
48#define DDSCAPS2_CUBEMAP 0x00000200
49#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
50#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
51#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
52#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
53#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
54#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
55#define DDSCAPS2_VOLUME 0x00200000
57#define SOIL_GL_SRGB 0x8C40
58#define SOIL_GL_SRGB_ALPHA 0x8C42
59#define SOIL_RGB_S3TC_DXT1 0x83F0
60#define SOIL_RGBA_S3TC_DXT1 0x83F1
61#define SOIL_RGBA_S3TC_DXT3 0x83F2
62#define SOIL_RGBA_S3TC_DXT5 0x83F3
64#define SOIL_TEXTURE_WRAP_R 0x8072
65#define SOIL_CLAMP_TO_EDGE 0x812F
66#define SOIL_REFLECTION_MAP 0x8512
77 unsigned int dwReserved1[11];
111 uint32_t palette_index = buffer_index;
114 if(
header->dwMagic != ((
'D' << 0) | (
'D' << 8) | (
'S' << 16) | (
' ' << 24))) {
117 if(
header->dwSize != 124) {
122 if((
header->dwFlags & flag) != flag) {
129 if(
header->sPixelFormat.dwSize != 32) {
140 !((
header->sPixelFormat.dwFourCC == ((
'D' << 0) | (
'X' << 8) | (
'T' << 16) | (
'1' << 24)))
141 || (
header->sPixelFormat.dwFourCC == ((
'D' << 0) | (
'X' << 8) | (
'T' << 16) | (
'3' << 24)))
142 || (
header->sPixelFormat.dwFourCC == ((
'D' << 0) | (
'X' << 8) | (
'T' << 16) | (
'5' << 24))))) {
153 height =
header->dwHeight;
155 GLint s3tc_format = 0;
156 GLint s3tc_format_layout = 0;
157 GLint s3tc_type = GL_UNSIGNED_BYTE;
163 if(
header->sPixelFormat.dwRGBBitCount == 16) {
172 palette_index = buffer_index;
173 buffer_index += 4 * 256;
176 dds_main_size = width * height * block_size;
180 switch((
header->sPixelFormat.dwFourCC >> 24) -
'0') {
194 dds_main_size = ((width + 3) >> 2) * ((height + 3) >> 2) * block_size;
197 uint32_t dds_full_size = dds_main_size;
200 mipmaps =
header->dwMipMapCount - 1;
201 for(
uint32_t i = 1; i <= mipmaps; ++i) {
202 uint32_t w = std::max<uint32_t>(width >> i, 1);
203 uint32_t h = std::max<uint32_t>(height >> i, 1);
206 dds_full_size += w * h * block_size;
209 dds_full_size += ((w + 3) / 4) * ((h + 3) / 4) * block_size;
214 if(buffer_index + dds_full_size <=
uint32_t(buffer_length)) {
217 glGenTextures(1, &texid);
219 glBindTexture(GL_TEXTURE_2D, texid);
225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
230 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
239 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
245 bool keep_rgba =
true;
247 std::unique_ptr<uint8_t[]> dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[dds_full_size]);
252 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
253 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
254 uint8_t pidx = buffer[buffer_index + i];
255 dds_dest_data[i * 4 + 0] = buffer[palette_index + pidx * 4 + 0];
256 dds_dest_data[i * 4 + 1] = buffer[palette_index + pidx * 4 + 1];
257 dds_dest_data[i * 4 + 2] = buffer[palette_index + pidx * 4 + 2];
258 dds_dest_data[i * 4 + 3] = is_alpha ? buffer[palette_index + pidx * 4 + 3] : 0xff;
260 s3tc_format = s3tc_format_layout = GL_RGBA;
262 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
263 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
264 uint8_t pidx = buffer[buffer_index + i];
265 dds_dest_data[i * 3 + 0] = buffer[palette_index + pidx * 4 + 0];
266 dds_dest_data[i * 3 + 1] = buffer[palette_index + pidx * 4 + 1];
267 dds_dest_data[i * 3 + 2] = buffer[palette_index + pidx * 4 + 2];
269 s3tc_format = s3tc_format_layout = GL_RGB;
275 uint16_t mr1 = uint16_t(
header->sPixelFormat.dwRBitMask >> std::countr_zero(
header->sPixelFormat.dwRBitMask));
276 float mr2 = mr1 == 0 ? 0.f : 255.f / float(mr1);
277 uint16_t mg1 = uint16_t(
header->sPixelFormat.dwGBitMask >> std::countr_zero(
header->sPixelFormat.dwGBitMask));
278 float mg2 = mg1 == 0 ? 0.f : 255.f / float(mg1);
279 uint16_t mb1 = uint16_t(
header->sPixelFormat.dwBBitMask >> std::countr_zero(
header->sPixelFormat.dwBBitMask));
280 float mb2 = mb1 == 0 ? 0.f : 255.f / float(mb1);
281 uint16_t ma1 = uint16_t(
header->sPixelFormat.dwAlphaBitMask >> std::countr_zero(
header->sPixelFormat.dwAlphaBitMask));
282 float ma2 = ma1 == 0 ? 0.f : 255.f / float(ma1);
283 uint16_t rmask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwRBitMask));
284 uint16_t gmask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwGBitMask));
285 uint16_t bmask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwBBitMask));
286 uint16_t amask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwAlphaBitMask));
288 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
289 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
290 uint16_t
data = *
reinterpret_cast<uint16_t const*
>(buffer + buffer_index + i * block_size);
291 uint16_t r = (
data &
header->sPixelFormat.dwRBitMask) >> rmask_zeros;
292 uint16_t g = (
data &
header->sPixelFormat.dwGBitMask) >> gmask_zeros;
293 uint16_t b = (
data &
header->sPixelFormat.dwBBitMask) >> bmask_zeros;
294 uint16_t a = (
data &
header->sPixelFormat.dwAlphaBitMask) >> amask_zeros;
295 dds_dest_data[i * 4 + 0] =
uint8_t(
float(r) * mr2);
296 dds_dest_data[i * 4 + 1] =
uint8_t(
float(g) * mg2);
297 dds_dest_data[i * 4 + 2] =
uint8_t(
float(b) * mb2);
298 dds_dest_data[i * 4 + 3] = is_alpha ?
uint8_t(
float(a) * ma2) : 0xff;
300 s3tc_format = s3tc_format_layout = GL_RGBA;
302 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
303 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
304 uint16_t
data = *
reinterpret_cast<uint16_t const*
>(buffer + buffer_index + i * block_size);
305 uint16_t r = (
data &
header->sPixelFormat.dwRBitMask) >> rmask_zeros;
306 uint16_t g = (
data &
header->sPixelFormat.dwGBitMask) >> gmask_zeros;
307 uint16_t b = (
data &
header->sPixelFormat.dwBBitMask) >> bmask_zeros;
308 uint16_t a = (
data &
header->sPixelFormat.dwAlphaBitMask) >> amask_zeros;
309 dds_dest_data[i * 3 + 0] =
uint8_t(
float(r) * mr2);
310 dds_dest_data[i * 3 + 1] =
uint8_t(
float(g) * mg2);
311 dds_dest_data[i * 3 + 2] =
uint8_t(
float(b) * mb2);
313 s3tc_format = s3tc_format_layout = GL_RGB;
324 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
325 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
326 auto ptr = buffer + buffer_index + i * block_size;
332 dds_dest_data[i * 4 + 0] =
static_cast<uint8_t>(r);
333 dds_dest_data[i * 4 + 1] =
static_cast<uint8_t>(g);
334 dds_dest_data[i * 4 + 2] =
static_cast<uint8_t>(b);
335 dds_dest_data[i * 4 + 3] = is_alpha ?
static_cast<uint8_t>(a) : 0xff;
337 s3tc_format = s3tc_format_layout = GL_RGBA;
339 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
340 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
341 auto ptr = buffer + buffer_index + i * block_size;
347 dds_dest_data[i * 3 + 0] =
static_cast<uint8_t>(r);
348 dds_dest_data[i * 3 + 1] =
static_cast<uint8_t>(g);
349 dds_dest_data[i * 3 + 2] =
static_cast<uint8_t>(b);
351 s3tc_format = s3tc_format_layout = GL_RGB;
362 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
363 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
369 dds_dest_data[i * 4 + 0] =
static_cast<uint8_t>(r);
370 dds_dest_data[i * 4 + 1] =
static_cast<uint8_t>(g);
371 dds_dest_data[i * 4 + 2] =
static_cast<uint8_t>(b);
372 dds_dest_data[i * 4 + 3] = is_alpha ?
static_cast<uint8_t>(a) : 0xff;
374 s3tc_format = s3tc_format_layout = GL_RGBA;
376 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
377 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
383 dds_dest_data[i * 3 + 0] =
static_cast<uint8_t>(r);
384 dds_dest_data[i * 3 + 1] =
static_cast<uint8_t>(g);
385 dds_dest_data[i * 3 + 2] =
static_cast<uint8_t>(b);
387 s3tc_format = s3tc_format_layout = GL_RGB;
393 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
397 glTexImage2D(GL_TEXTURE_2D, 0, s3tc_format, width, height, 0, s3tc_format_layout, s3tc_type, dds_dest_data.get());
398 uint32_t dest_buffer_index = (dds_main_size / block_size) * (keep_rgba ? 4 : 3);
400 for(
uint32_t i = 1; i <= mipmaps; ++i) {
401 uint32_t w = std::max<uint32_t>(width >> i, 1);
402 uint32_t h = std::max<uint32_t>(height >> i, 1);
404 uint32_t mip_size = w * h * (keep_rgba ? 4 : 3);
405 glTexImage2D(GL_TEXTURE_2D, i, s3tc_format, w, h, 0, s3tc_format_layout, s3tc_type, dds_dest_data.get() + dest_buffer_index);
407 dest_buffer_index += mip_size;
410 glCompressedTexImage2D(GL_TEXTURE_2D, 0, s3tc_format, width, height, 0, dds_main_size, buffer + buffer_index);
411 buffer_index += dds_main_size;
413 for(
uint32_t i = 1; i <= mipmaps; ++i) {
414 uint32_t w = std::max<uint32_t>(width >> i, 1);
415 uint32_t h = std::max<uint32_t>(height >> i, 1);
417 uint32_t mip_size = ((w + 3) / 4) * ((h + 3) / 4) * block_size;
418 glCompressedTexImage2D(GL_TEXTURE_2D, i, s3tc_format, w, h, 0, mip_size, buffer + buffer_index);
420 buffer_index += mip_size;
438 uint32_t palette_index = buffer_index;
441 if(
header->dwMagic != ((
'D' << 0) | (
'D' << 8) | (
'S' << 16) | (
' ' << 24))) {
444 if(
header->dwSize != 124) {
449 if((
header->dwFlags & flag) != flag) {
456 if(
header->sPixelFormat.dwSize != 32) {
467 !((
header->sPixelFormat.dwFourCC == ((
'D' << 0) | (
'X' << 8) | (
'T' << 16) | (
'1' << 24)))
468 || (
header->sPixelFormat.dwFourCC == ((
'D' << 0) | (
'X' << 8) | (
'T' << 16) | (
'3' << 24)))
469 || (
header->sPixelFormat.dwFourCC == ((
'D' << 0) | (
'X' << 8) | (
'T' << 16) | (
'5' << 24))))) {
480 height =
header->dwHeight;
482 GLint s3tc_format = 0;
483 GLint s3tc_format_layout = 0;
484 GLint s3tc_type = GL_UNSIGNED_BYTE;
490 if(
header->sPixelFormat.dwRGBBitCount == 16) {
499 palette_index = buffer_index;
500 buffer_index += 4 * 256;
503 dds_main_size = width * height * block_size;
507 switch((
header->sPixelFormat.dwFourCC >> 24) -
'0') {
521 dds_main_size = ((width + 3) >> 2) * ((height + 3) >> 2) * block_size;
524 uint32_t dds_full_size = dds_main_size;
527 mipmaps =
header->dwMipMapCount - 1;
528 for(
uint32_t i = 1; i <= mipmaps; ++i) {
529 uint32_t w = std::max<uint32_t>(width >> i, 1);
530 uint32_t h = std::max<uint32_t>(height >> i, 1);
533 dds_full_size += w * h * block_size;
536 dds_full_size += ((w + 3) / 4) * ((h + 3) / 4) * block_size;
541 if(buffer_index + dds_full_size <=
uint32_t(buffer_length)) {
544 glGenTextures(1, &texid);
546 glBindTexture(GL_TEXTURE_2D_ARRAY, texid);
552 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
553 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
556 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
557 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
561 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
562 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
565 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
566 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
569 glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
570 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, height);
574 bool keep_rgba =
true;
576 std::unique_ptr<uint8_t[]> dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[dds_full_size]);
581 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
582 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
583 uint8_t pidx = buffer[buffer_index + i];
584 dds_dest_data[i * 4 + 0] = buffer[palette_index + pidx * 4 + 0];
585 dds_dest_data[i * 4 + 1] = buffer[palette_index + pidx * 4 + 1];
586 dds_dest_data[i * 4 + 2] = buffer[palette_index + pidx * 4 + 2];
587 dds_dest_data[i * 4 + 3] = is_alpha ? buffer[palette_index + pidx * 4 + 3] : 0xff;
589 s3tc_format = s3tc_format_layout = GL_RGBA;
591 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
592 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
593 uint8_t pidx = buffer[buffer_index + i];
594 dds_dest_data[i * 3 + 0] = buffer[palette_index + pidx * 4 + 0];
595 dds_dest_data[i * 3 + 1] = buffer[palette_index + pidx * 4 + 1];
596 dds_dest_data[i * 3 + 2] = buffer[palette_index + pidx * 4 + 2];
598 s3tc_format = s3tc_format_layout = GL_RGB;
604 uint16_t mr1 = uint16_t(
header->sPixelFormat.dwRBitMask >> std::countr_zero(
header->sPixelFormat.dwRBitMask));
605 float mr2 = mr1 == 0 ? 0.f : 255.f / float(mr1);
606 uint16_t mg1 = uint16_t(
header->sPixelFormat.dwGBitMask >> std::countr_zero(
header->sPixelFormat.dwGBitMask));
607 float mg2 = mg1 == 0 ? 0.f : 255.f / float(mg1);
608 uint16_t mb1 = uint16_t(
header->sPixelFormat.dwBBitMask >> std::countr_zero(
header->sPixelFormat.dwBBitMask));
609 float mb2 = mb1 == 0 ? 0.f : 255.f / float(mb1);
610 uint16_t ma1 = uint16_t(
header->sPixelFormat.dwAlphaBitMask >> std::countr_zero(
header->sPixelFormat.dwAlphaBitMask));
611 float ma2 = ma1 == 0 ? 0.f : 255.f / float(ma1);
612 uint16_t rmask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwRBitMask));
613 uint16_t gmask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwGBitMask));
614 uint16_t bmask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwBBitMask));
615 uint16_t amask_zeros = uint16_t(std::countr_zero(
header->sPixelFormat.dwAlphaBitMask));
617 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
618 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
619 uint16_t
data = *
reinterpret_cast<uint16_t const*
>(buffer + buffer_index + i * block_size);
620 uint16_t r = (
data &
header->sPixelFormat.dwRBitMask) >> rmask_zeros;
621 uint16_t g = (
data &
header->sPixelFormat.dwGBitMask) >> gmask_zeros;
622 uint16_t b = (
data &
header->sPixelFormat.dwBBitMask) >> bmask_zeros;
623 uint16_t a = (
data &
header->sPixelFormat.dwAlphaBitMask) >> amask_zeros;
624 dds_dest_data[i * 4 + 0] =
uint8_t(
float(r) * mr2);
625 dds_dest_data[i * 4 + 1] =
uint8_t(
float(g) * mg2);
626 dds_dest_data[i * 4 + 2] =
uint8_t(
float(b) * mb2);
627 dds_dest_data[i * 4 + 3] = is_alpha ?
uint8_t(
float(a) * ma2) : 0xff;
629 s3tc_format = s3tc_format_layout = GL_RGBA;
631 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
632 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
633 uint16_t
data = *
reinterpret_cast<uint16_t const*
>(buffer + buffer_index + i * block_size);
634 uint16_t r = (
data &
header->sPixelFormat.dwRBitMask) >> rmask_zeros;
635 uint16_t g = (
data &
header->sPixelFormat.dwGBitMask) >> gmask_zeros;
636 uint16_t b = (
data &
header->sPixelFormat.dwBBitMask) >> bmask_zeros;
637 uint16_t a = (
data &
header->sPixelFormat.dwAlphaBitMask) >> amask_zeros;
638 dds_dest_data[i * 3 + 0] =
uint8_t(
float(r) * mr2);
639 dds_dest_data[i * 3 + 1] =
uint8_t(
float(g) * mg2);
640 dds_dest_data[i * 3 + 2] =
uint8_t(
float(b) * mb2);
642 s3tc_format = s3tc_format_layout = GL_RGB;
653 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
654 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
655 auto ptr = buffer + buffer_index + i * block_size;
661 dds_dest_data[i * 4 + 0] =
static_cast<uint8_t>(r);
662 dds_dest_data[i * 4 + 1] =
static_cast<uint8_t>(g);
663 dds_dest_data[i * 4 + 2] =
static_cast<uint8_t>(b);
664 dds_dest_data[i * 4 + 3] = is_alpha ?
static_cast<uint8_t>(a) : 0xff;
666 s3tc_format = s3tc_format_layout = GL_RGBA;
668 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
669 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
670 auto ptr = buffer + buffer_index + i * block_size;
676 dds_dest_data[i * 3 + 0] =
static_cast<uint8_t>(r);
677 dds_dest_data[i * 3 + 1] =
static_cast<uint8_t>(g);
678 dds_dest_data[i * 3 + 2] =
static_cast<uint8_t>(b);
680 s3tc_format = s3tc_format_layout = GL_RGB;
691 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
692 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
698 dds_dest_data[i * 4 + 0] =
static_cast<uint8_t>(r);
699 dds_dest_data[i * 4 + 1] =
static_cast<uint8_t>(g);
700 dds_dest_data[i * 4 + 2] =
static_cast<uint8_t>(b);
701 dds_dest_data[i * 4 + 3] = is_alpha ?
static_cast<uint8_t>(a) : 0xff;
703 s3tc_format = s3tc_format_layout = GL_RGBA;
705 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 3]);
706 for(
uint32_t i = 0; i < dds_full_size / block_size; i++) {
712 dds_dest_data[i * 3 + 0] =
static_cast<uint8_t>(r);
713 dds_dest_data[i * 3 + 1] =
static_cast<uint8_t>(g);
714 dds_dest_data[i * 3 + 2] =
static_cast<uint8_t>(b);
716 s3tc_format = s3tc_format_layout = GL_RGB;
722 dds_dest_data = std::unique_ptr<uint8_t[]>(
new uint8_t[(dds_full_size / block_size) * 4]);
726 size_t p_dx = width / tiles_x;
727 size_t p_dy = height / tiles_y;
728 for(
uint32_t x = 0; x < tiles_x; x++) {
729 for(
uint32_t y = 0; y < tiles_y; y++) {
730 uint32_t offset =
uint32_t(x * p_dy * width + y * p_dx * (keep_rgba ? 4 : 3));
731 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, GLint(x * tiles_x + y), GLsizei(p_dx), GLsizei(p_dy), 1, s3tc_format, s3tc_type, dds_dest_data.get() + offset);
749 size_t p_dx = width / tiles_x;
750 size_t p_dy = height / tiles_y;
751 glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, s3tc_format, GLsizei(p_dx), GLsizei(p_dy), GLsizei(tiles_x * tiles_y), 0, GLsizei(dds_main_size), buffer);
753 buffer_index += dds_main_size;
765 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
766 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
778 channels = other.channels;
779 loaded = other.loaded;
780 size_x = other.size_x;
781 size_y = other.size_y;
783 texture_handle = other.texture_handle;
785 other.data =
nullptr;
788 channels = other.channels;
789 loaded = other.loaded;
790 size_x = other.size_x;
791 size_y = other.size_y;
793 texture_handle = other.texture_handle;
795 other.data =
nullptr;
801 return texture_handle;
805 auto name_length = native_name.length();
807 auto root = get_root(fs);
808 if(name_length > 4) {
809 auto dds_name = native_name;
810 if(
auto pos = dds_name.find_last_of(
'.'); pos != native_string::npos) {
811 dds_name[pos + 1] =
NATIVE(
'd');
812 dds_name[pos + 2] =
NATIVE(
'd');
813 dds_name[pos + 3] =
NATIVE(
's');
814 dds_name.resize(pos + 4);
816 auto file = open_file(root, dds_name);
824 if(asset_texture.texture_handle) {
826 asset_texture.
size_x = int32_t(w);
827 asset_texture.
size_y = int32_t(h);
828 asset_texture.
loaded =
true;
831 asset_texture.
data =
static_cast<uint8_t*
>(STBI_MALLOC(4 * w * h));
832 glGetTextureImage(asset_texture.texture_handle, 0, GL_RGBA, GL_UNSIGNED_BYTE,
static_cast<int32_t
>(4 * w * h),
835 return asset_texture.texture_handle;
840 auto file = open_file(root, native_name);
841 if(!file && name_length > 4) {
842 auto png_name = native_name;
843 if(
auto pos = png_name.find_last_of(
'.'); pos != native_string::npos) {
844 png_name[pos + 1] =
NATIVE(
'p');
845 png_name[pos + 2] =
NATIVE(
'n');
846 png_name[pos + 3] =
NATIVE(
'g');
847 png_name.resize(pos + 4);
849 file = open_file(root, png_name);
854 int32_t file_channels = 4;
856 asset_texture.
data = stbi_load_from_memory(
reinterpret_cast<uint8_t const*
>(content.data), int32_t(content.file_size),
857 &(asset_texture.
size_x), &(asset_texture.
size_y), &file_channels, 4);
860 asset_texture.
loaded =
true;
862 glGenTextures(1, &asset_texture.texture_handle);
863 if(asset_texture.texture_handle) {
864 glBindTexture(GL_TEXTURE_2D, asset_texture.texture_handle);
866 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, asset_texture.
size_x, asset_texture.
size_y);
867 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, asset_texture.
size_x, asset_texture.
size_y, GL_RGBA, GL_UNSIGNED_BYTE,
870 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
871 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
872 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
873 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
875 glBindTexture(GL_TEXTURE_2D, 0);
879 STBI_FREE(asset_texture.
data);
880 asset_texture.
data =
nullptr;
883 return asset_texture.texture_handle;
885 asset_texture.
loaded =
true;
895 return NATIVE(
"_communist");
897 return NATIVE(
"_fascist");
899 return NATIVE(
"_monarchy");
901 return NATIVE(
"_republic");
904 return NATIVE(
"_theocracy");
906 return NATIVE(
"_special");
910 return NATIVE(
"_populist");
916 return NATIVE(
"_monarchy2");
918 return NATIVE(
"_monarchy3");
920 return NATIVE(
"_republic2");
922 return NATIVE(
"_republic3");
924 return NATIVE(
"_communist2");
926 return NATIVE(
"_communist3");
928 return NATIVE(
"_fascist2");
930 return NATIVE(
"_fascist3");
932 return NATIVE(
"_theocracy2");
934 return NATIVE(
"_theocracy3");
936 return NATIVE(
"_cosmetic_1");
938 return NATIVE(
"_cosmetic_2");
940 return NATIVE(
"_colonial");
942 return NATIVE(
"_nationalist");
944 return NATIVE(
"_sectarian");
946 return NATIVE(
"_socialist");
948 return NATIVE(
"_dominion");
950 return NATIVE(
"_agrarism");
952 return NATIVE(
"_national_syndicalist");
954 return NATIVE(
"_theocratic");
964 return NATIVE(
"_anarcho_liberal");
968 return NATIVE(
"_traditionalist");
970 return NATIVE(
"_ultranationalist");
978 auto masq_nat_id = state.world.nation_get_masquerade_identity(state.world.national_identity_get_nation_from_identity_holder(nat_id));
980 masq_nat_id = nat_id;
984 dcon::texture_id
id = dcon::texture_id{ dcon::texture_id::value_base_t(state.ui_defs.textures.size() + (1 + masq_nat_id.id.index()) * state.flag_types.size() + offset) };
985 if(state.open_gl.asset_textures[
id].loaded) {
986 return state.open_gl.asset_textures[id].texture_handle;
989 file_str +=
NATIVE(
"gfx");
991 file_str +=
NATIVE(
"flags");
1011 dcon::rebel_type_fat_id rtype = state.world.rebel_faction_get_type(faction);
1012 dcon::ideology_fat_id ideology = rtype.get_ideology();
1018 GLuint o_tex = state.ui_state.rebel_flags[ideology.id.index()];
1022 dcon::texture_id new_id{ dcon::texture_id::value_base_t(state.open_gl.asset_textures.size()) };
1023 state.open_gl.asset_textures.emplace_back();
1024 dcon::texture_id
id = new_id;
1027 file_str +=
NATIVE(
"assets");
1029 file_str +=
NATIVE(
"flags");
1031 file_str +=
NATIVE(
"REB");
1034 std::string_view name = state.to_string_view(state.world.ideology_get_name(ideology));
1041 state.ui_state.rebel_flags[ideology.id.index()] = p_tex;
1042 return state.ui_state.rebel_flags[ideology.id.index()];
1044 state.ui_state.rebel_flags[ideology.id.index()] = p_tex;
1045 return state.ui_state.rebel_flags[ideology.id.index()];
1050 if(
id && state.open_gl.asset_textures[
id].loaded) {
1051 return state.open_gl.asset_textures[id].texture_handle;
1053 if(
auto it = state.open_gl.late_loaded_map.find(std::string(asset_name)); it != state.open_gl.late_loaded_map.end()) {
1055 return state.open_gl.asset_textures[id].texture_handle;
1057 dcon::texture_id new_id{ dcon::texture_id::value_base_t(state.open_gl.asset_textures.size()) };
1058 state.open_gl.asset_textures.emplace_back();
1060 state.open_gl.late_loaded_map.insert_or_assign(std::string(asset_name), new_id);
1067 if(state.open_gl.asset_textures[
id].loaded) {
1068 return state.open_gl.asset_textures[id].texture_handle;
1070 auto fname = state.ui_defs.textures[id];
1071 auto fname_view = state.to_string_view(fname);
1083 glGenTextures(1, &texture_handle);
1084 glBindTexture(GL_TEXTURE_2D, texture_handle);
1087 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB8,
size, 1);
1089 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8,
size, 1);
1091 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG8,
size, 1);
1093 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8,
size, 1);
1095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1096 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1097 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1098 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1100 glBindTexture(GL_TEXTURE_2D, 0);
1110 glBindTexture(GL_TEXTURE_2D, texture_handle);
1112 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
size, 1, GL_RGB, GL_UNSIGNED_BYTE,
data);
1114 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
size, 1, GL_RGBA, GL_UNSIGNED_BYTE,
data);
1116 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
size, 1, GL_RG, GL_UNSIGNED_BYTE,
data);
1118 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
size, 1, GL_RED, GL_UNSIGNED_BYTE,
data);
1121 glBindTexture(GL_TEXTURE_2D, 0);
1123 return texture_handle;
1129 channels = other.channels;
1130 texture_handle = other.texture_handle;
1132 other.data =
nullptr;
1138 channels = other.channels;
1139 texture_handle = other.texture_handle;
1141 other.data =
nullptr;
1149 int32_t file_channels = 4;
1152 uint8_t*
data = stbi_load_from_memory(
reinterpret_cast<uint8_t const*
>(content.data), int32_t(content.file_size), &(size_x), &(size_y), &file_channels, 4);
1155 glGenTextures(1, &ftexid);
1156 if(
data && ftexid) {
1157 glBindTexture(GL_TEXTURE_2D, ftexid);
1159 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, size_x, size_y);
1160 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size_x, size_y, GL_RGBA, GL_UNSIGNED_BYTE,
data);
1162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
data_texture & operator=(data_texture const &)=delete
data_texture(int32_t sz, int32_t ch)
texture & operator=(texture const &)=delete
GLuint get_texture_handle() const
#define assert(condition)
uint32_t get_remapped_flag_type(sys::state const &state, flag_type type)
std::string int_to_tag(uint32_t v)
GLuint get_late_load_texture_handle(sys::state &state, dcon::texture_id &id, std::string_view asset_name)
GLuint get_rebel_flag_handle(sys::state &state, dcon::rebel_faction_id faction)
GLuint SOIL_direct_load_DDS_array_from_memory(unsigned char const *const buffer, uint32_t buffer_length, uint32_t &width, uint32_t &height, int soil_flags, uint32_t tiles_x, uint32_t tiles_y)
GLuint load_file_and_return_handle(native_string const &native_name, simple_fs::file_system const &fs, texture &asset_texture, bool keep_data)
GLuint SOIL_direct_load_DDS_from_memory(unsigned char const *const buffer, uint32_t buffer_length, uint32_t &width, uint32_t &height, int soil_flags)
@ SOIL_FLAG_TEXTURE_REPEATS
GLuint get_texture_handle(sys::state &state, dcon::texture_id id, bool keep_data)
native_string flag_type_to_name(sys::state &state, culture::flag_type type)
font_texture_result make_font_texture(simple_fs::file &f)
GLuint get_flag_handle(sys::state &state, dcon::national_identity_id nat_id, culture::flag_type type)
native_string win1250_to_native(std::string_view data_in)
native_string utf8_to_native(std::string_view data_in)
file_contents view_contents(file const &f)
std::string native_string
#define NATIVE_DIR_SEPARATOR
Holds important data about the game world, state, and other data regarding windowing,...
#define SOIL_TEXTURE_WRAP_R
#define SOIL_RGBA_S3TC_DXT3
#define SOIL_RGBA_S3TC_DXT1
#define DDPF_PALETTEINDEXED8
#define SOIL_RGBA_S3TC_DXT5