diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-04 18:43:28 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-04 18:43:28 +0100 |
| commit | d7201a987ba6cc56fda3d3ea69275307385f7c3e (patch) | |
| tree | 54d5247ac75adc3b9241c323dbc0ca5db5d35c96 | |
| parent | Chams: style flags on the resident debug material (diff) | |
| download | hl2h-d7201a987ba6cc56fda3d3ea69275307385f7c3e.tar.gz hl2h-d7201a987ba6cc56fda3d3ea69275307385f7c3e.zip | |
Chams: preload style materials outside the model draw
FindMaterial inside DrawModelExecute did not load the style VMTs, so every
style fell back to the solid material. Preload the six style materials from
outer_draw (throttled) and have the render hook use the cached pointers only.
world_find_material now returns only the exact requested material; the caller
falls back to the solid style. Add a vgui/white probe and per-style preload
logs.
| -rw-r--r-- | src/hl2h.h | 1 | ||||
| -rw-r--r-- | src/menu.cpp | 1 | ||||
| -rw-r--r-- | src/studio.cpp | 65 | ||||
| -rw-r--r-- | src/world.cpp | 15 |
4 files changed, 53 insertions, 29 deletions
| @@ -339,6 +339,7 @@ bool esp_is_npc_index(int idx); | |||
| 339 | bool esp_is_viewmodel_index(int idx); | 339 | bool esp_is_viewmodel_index(int idx); |
| 340 | void *world_find_material(const char *name); | 340 | void *world_find_material(const char *name); |
| 341 | void chams_init(); | 341 | void chams_init(); |
| 342 | void chams_preload(); | ||
| 342 | int engine_get_local_player(); | 343 | int engine_get_local_player(); |
| 343 | void draw_text_col(int x, int y, const char *s, int r, int g, int b); | 344 | void draw_text_col(int x, int y, const char *s, int r, int g, int b); |
| 344 | void draw_text_small_col(int x, int y, const char *s, int r, int g, int b); | 345 | void draw_text_small_col(int x, int y, const char *s, int r, int g, int b); |
diff --git a/src/menu.cpp b/src/menu.cpp index 376a779..6a3c607 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -999,6 +999,7 @@ void outer_draw() { | |||
| 999 | world_tint_update(); | 999 | world_tint_update(); |
| 1000 | prop_tint_update(); | 1000 | prop_tint_update(); |
| 1001 | fog_update(); | 1001 | fog_update(); |
| 1002 | chams_preload(); | ||
| 1002 | gui_handle_input(); | 1003 | gui_handle_input(); |
| 1003 | // HL2H_DRAW_TEST=1 draws a probe rect without needing the GUI open | 1004 | // HL2H_DRAW_TEST=1 draws a probe rect without needing the GUI open |
| 1004 | static bool draw_test = getenv("HL2H_DRAW_TEST") != nullptr; | 1005 | static bool draw_test = getenv("HL2H_DRAW_TEST") != nullptr; |
diff --git a/src/studio.cpp b/src/studio.cpp index 1ca8ad7..44d1bb4 100644 --- a/src/studio.cpp +++ b/src/studio.cpp | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <cstdio> | 19 | #include <cstdio> |
| 20 | #include <cstring> | 20 | #include <cstring> |
| 21 | #include <dlfcn.h> | 21 | #include <dlfcn.h> |
| 22 | #include <time.h> | ||
| 22 | 23 | ||
| 23 | namespace { | 24 | namespace { |
| 24 | 25 | ||
| @@ -196,34 +197,37 @@ using ForceOverrideFn = void (*)(void *, void *, int); | |||
| 196 | void *g_modelrender = nullptr; | 197 | void *g_modelrender = nullptr; |
| 197 | ModelExecFn g_orig_model_exec = nullptr; | 198 | ModelExecFn g_orig_model_exec = nullptr; |
| 198 | ForceOverrideFn g_force_override = nullptr; | 199 | ForceOverrideFn g_force_override = nullptr; |
| 199 | void *g_chams_mat = nullptr; | 200 | void *g_style_mats[6] = {}; |
| 200 | int g_chams_mat_idx = -1; | 201 | |
| 202 | void *viewmodel_material(); | ||
| 201 | 203 | ||
| 202 | const char *chams_material_name(int idx) { | 204 | const char *chams_material_name(int idx) { |
| 203 | (void)idx; | 205 | switch (idx) { |
| 204 | // Only this debug material is reliably resident in the base game; the other | 206 | case 1: return "debug/debugwireframe"; |
| 205 | // debug VMTs are not loaded and FindMaterial does not make them available. | 207 | case 2: return "debug/additivevertexcolorvertexalpha"; |
| 206 | // Visual styles are applied as material flags instead. | 208 | case 3: return "debug/debugtranslucentsinglecolor"; |
| 207 | return "debug/debugtranslucentsinglecolor"; | 209 | case 4: return "debug/debugtranslucentvertexcolor"; |
| 210 | case 5: return "debug/debugmrmfullbright2"; | ||
| 211 | default: return "models/debug/debugwhite"; | ||
| 212 | } | ||
| 208 | } | 213 | } |
| 209 | 214 | ||
| 210 | void *chams_material() { | 215 | void *chams_material() { |
| 211 | int idx = g_chams_mat_index; | 216 | int idx = g_chams_mat_index; |
| 212 | if (idx < 0) idx = 0; | 217 | if (idx < 0) idx = 0; |
| 213 | if (idx > 5) idx = 5; | 218 | if (idx > 5) idx = 5; |
| 214 | if (g_chams_mat && g_chams_mat_idx == idx) | 219 | if (g_style_mats[idx]) |
| 215 | return g_chams_mat; | 220 | return g_style_mats[idx]; |
| 216 | g_chams_mat = world_find_material(chams_material_name(idx)); | 221 | if (g_style_mats[3]) |
| 217 | if (!g_chams_mat) | 222 | return g_style_mats[3]; |
| 218 | g_chams_mat = world_find_material("debug/debugtranslucentsinglecolor"); | 223 | return viewmodel_material(); |
| 219 | g_chams_mat_idx = idx; | ||
| 220 | logf("chams: style %d -> %p", idx, g_chams_mat); | ||
| 221 | return g_chams_mat; | ||
| 222 | } | 224 | } |
| 223 | 225 | ||
| 224 | // Viewmodels need a model shader; the VGUI white materials used by some | 226 | // Viewmodels need a model shader; the VGUI white materials used by some |
| 225 | // styles do not draw skinned models and make the hands/weapon disappear. | 227 | // styles do not draw skinned models and make the hands/weapon disappear. |
| 226 | void *viewmodel_material() { | 228 | void *viewmodel_material() { |
| 229 | if (g_style_mats[3]) | ||
| 230 | return g_style_mats[3]; | ||
| 227 | static void *mat = nullptr; | 231 | static void *mat = nullptr; |
| 228 | if (!mat) | 232 | if (!mat) |
| 229 | mat = world_find_material("debug/debugtranslucentsinglecolor"); | 233 | mat = world_find_material("debug/debugtranslucentsinglecolor"); |
| @@ -307,6 +311,37 @@ void hkdModelExecute(void *self, const void *state, const void *info, | |||
| 307 | 311 | ||
| 308 | } // namespace | 312 | } // namespace |
| 309 | 313 | ||
| 314 | static double chams_now() { | ||
| 315 | timespec ts; | ||
| 316 | clock_gettime(CLOCK_MONOTONIC, &ts); | ||
| 317 | return (double)ts.tv_sec + (double)ts.tv_nsec * 1e-9; | ||
| 318 | } | ||
| 319 | |||
| 320 | // Called from outer_draw (outside the model draw) so FindMaterial can load | ||
| 321 | // the style VMTs. The render hook only reads the cached pointers. | ||
| 322 | void chams_preload() { | ||
| 323 | static double last = 0.0; | ||
| 324 | static bool probed = false; | ||
| 325 | double now = chams_now(); | ||
| 326 | if (now - last < 1.5) | ||
| 327 | return; | ||
| 328 | last = now; | ||
| 329 | if (!probed) { | ||
| 330 | probed = true; | ||
| 331 | void *probe = world_find_material("vgui/white"); | ||
| 332 | logf("chams: probe vgui/white = %p", probe); | ||
| 333 | } | ||
| 334 | for (int i = 0; i < 6; i++) { | ||
| 335 | if (g_style_mats[i]) | ||
| 336 | continue; | ||
| 337 | void *m = world_find_material(chams_material_name(i)); | ||
| 338 | if (m) { | ||
| 339 | g_style_mats[i] = m; | ||
| 340 | logf("chams: preloaded style %d %s = %p", i, chams_material_name(i), m); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 310 | void chams_init() { | 345 | void chams_init() { |
| 311 | if (g_modelrender || !g_iface.modelrender) { | 346 | if (g_modelrender || !g_iface.modelrender) { |
| 312 | if (!g_iface.modelrender) | 347 | if (!g_iface.modelrender) |
diff --git a/src/world.cpp b/src/world.cpp index d071281..ea186b4 100644 --- a/src/world.cpp +++ b/src/world.cpp | |||
| @@ -1065,19 +1065,6 @@ void *world_find_material(const char *name) { | |||
| 1065 | logf("chams: material %s = %p", name, mat); | 1065 | logf("chams: material %s = %p", name, mat); |
| 1066 | return mat; | 1066 | return mat; |
| 1067 | } | 1067 | } |
| 1068 | static const char *fallbacks[] = {"debug/debugtranslucentsinglecolor", | 1068 | logd("chams: material %s not found", name); |
| 1069 | "models/debug/debugwhite", "vgui/white", | ||
| 1070 | nullptr}; | ||
| 1071 | for (int i = 0; fallbacks[i]; i++) { | ||
| 1072 | mat = walk(fallbacks[i]); | ||
| 1073 | if (!mat) | ||
| 1074 | mat = find(fallbacks[i]); | ||
| 1075 | if (mat) { | ||
| 1076 | logf("chams: material %s (fallback for %s) = %p", fallbacks[i], name, | ||
| 1077 | mat); | ||
| 1078 | return mat; | ||
| 1079 | } | ||
| 1080 | } | ||
| 1081 | logf("chams: material %s not found", name); | ||
| 1082 | return nullptr; | 1069 | return nullptr; |
| 1083 | } | 1070 | } |
