summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-04 18:43:28 +0100
committersalmonik <salmonik@tuta.io>2026-11-04 18:43:28 +0100
commitd7201a987ba6cc56fda3d3ea69275307385f7c3e (patch)
tree54d5247ac75adc3b9241c323dbc0ca5db5d35c96
parentChams: style flags on the resident debug material (diff)
downloadhl2h-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.h1
-rw-r--r--src/menu.cpp1
-rw-r--r--src/studio.cpp65
-rw-r--r--src/world.cpp15
4 files changed, 53 insertions, 29 deletions
diff --git a/src/hl2h.h b/src/hl2h.h
index 1be1bb1..0f7e1f2 100644
--- a/src/hl2h.h
+++ b/src/hl2h.h
@@ -339,6 +339,7 @@ bool esp_is_npc_index(int idx);
339bool esp_is_viewmodel_index(int idx); 339bool esp_is_viewmodel_index(int idx);
340void *world_find_material(const char *name); 340void *world_find_material(const char *name);
341void chams_init(); 341void chams_init();
342void chams_preload();
342int engine_get_local_player(); 343int engine_get_local_player();
343void draw_text_col(int x, int y, const char *s, int r, int g, int b); 344void draw_text_col(int x, int y, const char *s, int r, int g, int b);
344void draw_text_small_col(int x, int y, const char *s, int r, int g, int b); 345void 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
23namespace { 24namespace {
24 25
@@ -196,34 +197,37 @@ using ForceOverrideFn = void (*)(void *, void *, int);
196void *g_modelrender = nullptr; 197void *g_modelrender = nullptr;
197ModelExecFn g_orig_model_exec = nullptr; 198ModelExecFn g_orig_model_exec = nullptr;
198ForceOverrideFn g_force_override = nullptr; 199ForceOverrideFn g_force_override = nullptr;
199void *g_chams_mat = nullptr; 200void *g_style_mats[6] = {};
200int g_chams_mat_idx = -1; 201
202void *viewmodel_material();
201 203
202const char *chams_material_name(int idx) { 204const 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
210void *chams_material() { 215void *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.
226void *viewmodel_material() { 228void *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
314static 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.
322void 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
310void chams_init() { 345void 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}