summaryrefslogtreecommitdiffstats
path: root/src/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/world.cpp')
-rw-r--r--src/world.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/world.cpp b/src/world.cpp
index aaee058..1228c7a 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -557,6 +557,58 @@ bool load_png_rgba(const char *path, std::vector<unsigned char> &pixels,
557 } 557 }
558 } 558 }
559 559
560 // The material system rejects textures whose dimensions are not multiples of
561 // 4 ("Image dimensions must be multiple of 4!" / "LoadTextureFromVTF: VTF
562 // dimensions do not match texture"). Scale to the next power of two; that is
563 // also what the old skybox code expects.
564 {
565 int tw = 1, th = 1;
566 while (tw < (int)w)
567 tw <<= 1;
568 while (th < (int)h)
569 th <<= 1;
570 if (tw > 4096) tw = 4096;
571 if (th > 4096) th = 4096;
572 if (tw != (int)w || th != (int)h) {
573 std::vector<unsigned char> scaled((size_t)tw * (size_t)th * 4);
574 for (int y = 0; y < th; y++) {
575 float sy = ((float)y + 0.5f) * (float)h / (float)th - 0.5f;
576 int y0 = (int)sy;
577 float fy = sy - (float)y0;
578 if (y0 < 0) { y0 = 0; fy = 0.0f; }
579 int y1 = y0 + 1 < (int)h ? y0 + 1 : y0;
580 for (int x = 0; x < tw; x++) {
581 float sx = ((float)x + 0.5f) * (float)w / (float)tw - 0.5f;
582 int x0 = (int)sx;
583 float fx = sx - (float)x0;
584 if (x0 < 0) { x0 = 0; fx = 0.0f; }
585 int x1 = x0 + 1 < (int)w ? x0 + 1 : x0;
586 const unsigned char *p00 = pixels.data() +
587 ((size_t)y0 * (size_t)w + (size_t)x0) * 4;
588 const unsigned char *p10 = pixels.data() +
589 ((size_t)y0 * (size_t)w + (size_t)x1) * 4;
590 const unsigned char *p01 = pixels.data() +
591 ((size_t)y1 * (size_t)w + (size_t)x0) * 4;
592 const unsigned char *p11 = pixels.data() +
593 ((size_t)y1 * (size_t)w + (size_t)x1) * 4;
594 unsigned char *o = scaled.data() +
595 ((size_t)y * (size_t)tw + (size_t)x) * 4;
596 for (int c = 0; c < 4; c++) {
597 float v = (1.0f - fy) *
598 ((1.0f - fx) * p00[c] + fx * p10[c]) +
599 fy * ((1.0f - fx) * p01[c] + fx * p11[c]);
600 o[c] = (unsigned char)(v + 0.5f);
601 }
602 }
603 }
604 logf("skybox: resized %dx%d -> %dx%d for the material system",
605 (int)w, (int)h, tw, th);
606 pixels.swap(scaled);
607 w = (uint32_t)tw;
608 h = (uint32_t)th;
609 }
610 }
611
560 out_w = (int)w; 612 out_w = (int)w;
561 out_h = (int)h; 613 out_h = (int)h;
562 return true; 614 return true;
@@ -574,6 +626,12 @@ public:
574 virtual void RegenerateTextureBits(void *texture, void *vtf, void *rect) { 626 virtual void RegenerateTextureBits(void *texture, void *vtf, void *rect) {
575 (void)texture; 627 (void)texture;
576 (void)rect; 628 (void)rect;
629 static bool entered = false;
630 if (!entered) {
631 entered = true;
632 logf("skybox: regenerator entered (vtf=%p, %zu pixels)", vtf,
633 g_sky_pixels.size());
634 }
577 if (!vtf || g_sky_pixels.empty()) 635 if (!vtf || g_sky_pixels.empty())
578 return; 636 return;
579 using IntFn = int (*)(void *); 637 using IntFn = int (*)(void *);