diff options
Diffstat (limited to 'src/studio.cpp')
| -rw-r--r-- | src/studio.cpp | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/studio.cpp b/src/studio.cpp index 69a2e07..8b0a710 100644 --- a/src/studio.cpp +++ b/src/studio.cpp | |||
| @@ -212,6 +212,20 @@ ModelExecFn g_orig_model_exec = nullptr; | |||
| 212 | ForceOverrideFn g_force_override = nullptr; | 212 | ForceOverrideFn g_force_override = nullptr; |
| 213 | void *g_style_mats[8] = {}; | 213 | void *g_style_mats[8] = {}; |
| 214 | 214 | ||
| 215 | // The engine forces a material for special passes (shadow depth, reflections) | ||
| 216 | // and clears it again. Without tracking that, the chams pass could not tell | ||
| 217 | // "no override" from "engine override in progress": it hijacked the shadow pass | ||
| 218 | // with chams materials and then cleared the engine's override for every model | ||
| 219 | // drawn afterwards. | ||
| 220 | static ForceOverrideFn g_real_force_override = nullptr; | ||
| 221 | static void *g_current_override = nullptr; | ||
| 222 | |||
| 223 | static void hkdForceOverride(void *self, void *mat, int type) { | ||
| 224 | g_current_override = mat; | ||
| 225 | if (g_real_force_override) | ||
| 226 | g_real_force_override(self, mat, type); | ||
| 227 | } | ||
| 228 | |||
| 215 | const char *chams_material_name(int idx) { | 229 | const char *chams_material_name(int idx) { |
| 216 | switch (idx) { | 230 | switch (idx) { |
| 217 | case 1: return "debug/debugwireframe"; | 231 | case 1: return "debug/debugwireframe"; |
| @@ -330,6 +344,12 @@ void hkdModelExecute(void *self, const void *state, const void *info, | |||
| 330 | g_orig_model_exec(self, state, info, bone); | 344 | g_orig_model_exec(self, state, info, bone); |
| 331 | return; | 345 | return; |
| 332 | } | 346 | } |
| 347 | // Shadow-depth/reflection passes arrive with a material already forced. Let | ||
| 348 | // them draw normally instead of substituting chams. | ||
| 349 | if (g_current_override) { | ||
| 350 | g_orig_model_exec(self, state, info, bone); | ||
| 351 | return; | ||
| 352 | } | ||
| 333 | if (feature_active(FEAT_CHAMS) && info && g_force_override) { | 353 | if (feature_active(FEAT_CHAMS) && info && g_force_override) { |
| 334 | // ModelRenderInfo_t::entity_index is at 0x30 on 32-bit. | 354 | // ModelRenderInfo_t::entity_index is at 0x30 on 32-bit. |
| 335 | int idx = *(const int *)((const char *)info + 0x30); | 355 | int idx = *(const int *)((const char *)info + 0x30); |
| @@ -568,7 +588,8 @@ void chams_init() { | |||
| 568 | logf("chams: model render has no vtable"); | 588 | logf("chams: model render has no vtable"); |
| 569 | return; | 589 | return; |
| 570 | } | 590 | } |
| 571 | g_force_override = (ForceOverrideFn)vt[1]; | 591 | g_real_force_override = (ForceOverrideFn)vt[1]; |
| 592 | g_force_override = g_real_force_override; | ||
| 572 | g_orig_model_exec = (ModelExecFn)vt[19]; | 593 | g_orig_model_exec = (ModelExecFn)vt[19]; |
| 573 | if (!mod_engine().contains((uintptr_t)g_force_override) || | 594 | if (!mod_engine().contains((uintptr_t)g_force_override) || |
| 574 | !mod_engine().contains((uintptr_t)g_orig_model_exec)) { | 595 | !mod_engine().contains((uintptr_t)g_orig_model_exec)) { |
| @@ -581,6 +602,7 @@ void chams_init() { | |||
| 581 | logf("chams: vtable clone failed"); | 602 | logf("chams: vtable clone failed"); |
| 582 | return; | 603 | return; |
| 583 | } | 604 | } |
| 605 | nvt[1] = (void *)&hkdForceOverride; // track engine-forced passes | ||
| 584 | nvt[19] = (void *)&hkdModelExecute; | 606 | nvt[19] = (void *)&hkdModelExecute; |
| 585 | g_modelrender = g_iface.modelrender; | 607 | g_modelrender = g_iface.modelrender; |
| 586 | *(void ***)g_modelrender = nvt; | 608 | *(void ***)g_modelrender = nvt; |
