diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-04 00:21:55 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-04 00:21:55 +0100 |
| commit | b97ac5d495ce82e6f1cf051c3f3a29ff38c91982 (patch) | |
| tree | 7b16b311fb9fea94d4d160cc4cdd634f13033c25 /src/world.cpp | |
| parent | Skybox image: decode PNG ourselves to avoid symbol interposition (diff) | |
| download | hl2h-b97ac5d495ce82e6f1cf051c3f3a29ff38c91982.tar.gz hl2h-b97ac5d495ce82e6f1cf051c3f3a29ff38c91982.zip | |
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.
Diffstat (limited to '')
| -rw-r--r-- | src/world.cpp | 43 |
1 files changed, 35 insertions, 8 deletions
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: | |||
| 587 | return; | 587 | return; |
| 588 | int pitch = vfunc<PitchFn>(vtf, 19)(vtf, 0); // RowSizeInBytes(0) | 588 | int pitch = vfunc<PitchFn>(vtf, 19)(vtf, 0); // RowSizeInBytes(0) |
| 589 | unsigned char *dst = vfunc<DataFn>(vtf, 39)(vtf, 0, 0, 0); // ImageData | 589 | unsigned char *dst = vfunc<DataFn>(vtf, 39)(vtf, 0, 0, 0); // ImageData |
| 590 | static bool logged_regen = false; | ||
| 591 | if (!logged_regen) { | ||
| 592 | logged_regen = true; | ||
| 593 | logf("skybox: regenerator %dx%d pitch=%d dst=%p first=%02x%02x%02x%02x", | ||
| 594 | w, h, pitch, dst, g_sky_pixels[0], g_sky_pixels[1], | ||
| 595 | g_sky_pixels[2], g_sky_pixels[3]); | ||
| 596 | } | ||
| 590 | if (!dst || pitch <= 0) | 597 | if (!dst || pitch <= 0) |
| 591 | return; | 598 | return; |
| 592 | int rows = h < g_sky_px_h ? h : g_sky_px_h; | 599 | int rows = h < g_sky_px_h ? h : g_sky_px_h; |
| @@ -675,24 +682,44 @@ int apply_sky_texture() { | |||
| 675 | using SetTexFn = void (*)(void *, void *); | 682 | using SetTexFn = void (*)(void *, void *); |
| 676 | auto find_var = vfunc<FindVarFn>(mat, 11); // IMaterial::FindVar | 683 | auto find_var = vfunc<FindVarFn>(mat, 11); // IMaterial::FindVar |
| 677 | 684 | ||
| 678 | static const char *vars[] = {"$basetexture", "$hdrbasetexture", | 685 | using GetTexFn = void *(*)(void *); |
| 679 | "$hdrcompressedtexture", nullptr}; | 686 | using IsDefFn = bool (*)(void *); |
| 680 | for (int vi = 0; vars[vi]; vi++) { | 687 | using UndefFn = void (*)(void *); |
| 688 | static const char *tex_vars[] = {"$basetexture", "$hdrbasetexture", | ||
| 689 | nullptr}; | ||
| 690 | for (int vi = 0; tex_vars[vi]; vi++) { | ||
| 681 | bool found = false; | 691 | bool found = false; |
| 682 | void *var = find_var(mat, vars[vi], &found, false); | 692 | void *var = find_var(mat, tex_vars[vi], &found, false); |
| 683 | if (!found || !var) | 693 | if (!found || !var) |
| 684 | continue; | 694 | continue; |
| 685 | using GetTexFn = void *(*)(void *); | ||
| 686 | auto vget = vfunc<GetStrFn>(var, 6); // GetStringValue | 695 | auto vget = vfunc<GetStrFn>(var, 6); // GetStringValue |
| 687 | auto vgettex = vfunc<GetTexFn>(var, 0); // GetTextureValue | 696 | auto vgettex = vfunc<GetTexFn>(var, 0); // GetTextureValue |
| 688 | auto vset = vfunc<SetTexFn>(var, 14); // SetTextureValue | 697 | auto vset = vfunc<SetTexFn>(var, 14); // SetTextureValue |
| 689 | const char *orig = vget(var); | 698 | record_orig(name, tex_vars[vi], vget(var), vgettex(var)); |
| 690 | void *orig_tex = vgettex(var); | ||
| 691 | record_orig(name, vars[vi], orig, orig_tex); | ||
| 692 | vset(var, g_sky_tex); | 699 | vset(var, g_sky_tex); |
| 693 | if (vi == 0) | 700 | if (vi == 0) |
| 694 | hits++; | 701 | hits++; |
| 695 | } | 702 | } |
| 703 | // The HDR sky shader samples $hdrcompressedtexture (DXT5) when defined, | ||
| 704 | // which cannot hold our RGBA texture. Undefine it so the shader falls back | ||
| 705 | // to $hdrbasetexture, which now points at our image. | ||
| 706 | static const char *undef_vars[] = { | ||
| 707 | "$hdrcompressedtexture", "$hdrcompressedtexture0", | ||
| 708 | "$hdrcompressedtexture1", "$hdrcompressedtexture2", nullptr}; | ||
| 709 | for (int vi = 0; undef_vars[vi]; vi++) { | ||
| 710 | bool found = false; | ||
| 711 | void *var = find_var(mat, undef_vars[vi], &found, false); | ||
| 712 | if (!found || !var) | ||
| 713 | continue; | ||
| 714 | if (!vfunc<IsDefFn>(var, 17)(var)) | ||
| 715 | continue; | ||
| 716 | record_orig(name, undef_vars[vi], vfunc<GetStrFn>(var, 6)(var), | ||
| 717 | vfunc<GetTexFn>(var, 0)(var)); | ||
| 718 | vfunc<UndefFn>(var, 18)(var); // SetUndefined | ||
| 719 | } | ||
| 720 | // The sky shader binds its texture in SHADER_INIT, so changing the vars is | ||
| 721 | // not enough: rebuild the material's shader state. | ||
| 722 | vfunc<void (*)(void *)>(mat, 37)(mat); // IMaterial::Refresh | ||
| 696 | } | 723 | } |
| 697 | return hits; | 724 | return hits; |
| 698 | } | 725 | } |
