From b97ac5d495ce82e6f1cf051c3f3a29ff38c91982 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 00:21:55 +0100 Subject: Skybox image: fix HDR sky binding; clip checkbox/arrow drawing The HDR sky materials use the "sky" shader with $hdrcompressedtexture (DXT5). Assigning an RGBA8 procedural texture there sampled as compressed data and rendered black. Point $hdrbasetexture at the image, undefine $hdrcompressedtexture (and its 0/1/2 variants) so the shader falls back, and call IMaterial::Refresh (37) because the sky shader binds textures in SHADER_INIT, which is otherwise cached. GUI: draw_checkbox and the card expand chevron ignored the content clip, so cards scrolled out of view leaked header widgets outside the window. Log the first regenerator call (size/pitch/first pixel) for diagnosis. --- src/world.cpp | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'src/world.cpp') diff --git a/src/world.cpp b/src/world.cpp index 621e5f7..aaee058 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -587,6 +587,13 @@ public: return; int pitch = vfunc(vtf, 19)(vtf, 0); // RowSizeInBytes(0) unsigned char *dst = vfunc(vtf, 39)(vtf, 0, 0, 0); // ImageData + static bool logged_regen = false; + if (!logged_regen) { + logged_regen = true; + logf("skybox: regenerator %dx%d pitch=%d dst=%p first=%02x%02x%02x%02x", + w, h, pitch, dst, g_sky_pixels[0], g_sky_pixels[1], + g_sky_pixels[2], g_sky_pixels[3]); + } if (!dst || pitch <= 0) return; int rows = h < g_sky_px_h ? h : g_sky_px_h; @@ -675,24 +682,44 @@ int apply_sky_texture() { using SetTexFn = void (*)(void *, void *); auto find_var = vfunc(mat, 11); // IMaterial::FindVar - static const char *vars[] = {"$basetexture", "$hdrbasetexture", - "$hdrcompressedtexture", nullptr}; - for (int vi = 0; vars[vi]; vi++) { + using GetTexFn = void *(*)(void *); + using IsDefFn = bool (*)(void *); + using UndefFn = void (*)(void *); + static const char *tex_vars[] = {"$basetexture", "$hdrbasetexture", + nullptr}; + for (int vi = 0; tex_vars[vi]; vi++) { bool found = false; - void *var = find_var(mat, vars[vi], &found, false); + void *var = find_var(mat, tex_vars[vi], &found, false); if (!found || !var) continue; - using GetTexFn = void *(*)(void *); auto vget = vfunc(var, 6); // GetStringValue auto vgettex = vfunc(var, 0); // GetTextureValue auto vset = vfunc(var, 14); // SetTextureValue - const char *orig = vget(var); - void *orig_tex = vgettex(var); - record_orig(name, vars[vi], orig, orig_tex); + record_orig(name, tex_vars[vi], vget(var), vgettex(var)); vset(var, g_sky_tex); if (vi == 0) hits++; } + // The HDR sky shader samples $hdrcompressedtexture (DXT5) when defined, + // which cannot hold our RGBA texture. Undefine it so the shader falls back + // to $hdrbasetexture, which now points at our image. + static const char *undef_vars[] = { + "$hdrcompressedtexture", "$hdrcompressedtexture0", + "$hdrcompressedtexture1", "$hdrcompressedtexture2", nullptr}; + for (int vi = 0; undef_vars[vi]; vi++) { + bool found = false; + void *var = find_var(mat, undef_vars[vi], &found, false); + if (!found || !var) + continue; + if (!vfunc(var, 17)(var)) + continue; + record_orig(name, undef_vars[vi], vfunc(var, 6)(var), + vfunc(var, 0)(var)); + vfunc(var, 18)(var); // SetUndefined + } + // The sky shader binds its texture in SHADER_INIT, so changing the vars is + // not enough: rebuild the material's shader state. + vfunc(mat, 37)(mat); // IMaterial::Refresh } return hits; } -- cgit v1.2.3