summaryrefslogtreecommitdiffstats
path: root/src/studio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/studio.cpp')
-rw-r--r--src/studio.cpp46
1 files changed, 13 insertions, 33 deletions
diff --git a/src/studio.cpp b/src/studio.cpp
index 086d213..cf145d1 100644
--- a/src/studio.cpp
+++ b/src/studio.cpp
@@ -199,20 +199,21 @@ ModelExecFn g_orig_model_exec = nullptr;
199ForceOverrideFn g_force_override = nullptr; 199ForceOverrideFn g_force_override = nullptr;
200void *g_style_mats[7] = {}; 200void *g_style_mats[7] = {};
201 201
202void *viewmodel_material();
203
204const char *chams_material_name(int idx) { 202const char *chams_material_name(int idx) {
205 switch (idx) { 203 switch (idx) {
206 case 1: return "debug/debugwireframe"; 204 case 1: return "debug/debugwireframe";
207 case 2: 205 case 2:
206 case 5: return "debug/debugtranslucentmodelhulls";
208 case 3: 207 case 3:
209 case 4: 208 case 4:
210 case 5:
211 case 6: 209 case 6:
212 default: return "debug/debugtranslucentsinglecolor"; 210 default: return "debug/debugtranslucentsinglecolor";
213 } 211 }
214} 212}
215 213
214// Never call FindMaterial here: this runs inside DrawModelExecute, where
215// loading a material can crash the material system. chams_preload fills the
216// cache from outer_draw instead.
216void *style_material(int idx) { 217void *style_material(int idx) {
217 if (idx < 0) idx = 0; 218 if (idx < 0) idx = 0;
218 if (idx > 6) idx = 6; 219 if (idx > 6) idx = 6;
@@ -220,17 +221,7 @@ void *style_material(int idx) {
220 return g_style_mats[idx]; 221 return g_style_mats[idx];
221 if (g_style_mats[3]) 222 if (g_style_mats[3])
222 return g_style_mats[3]; 223 return g_style_mats[3];
223 return viewmodel_material(); 224 return nullptr;
224}
225
226// Viewmodels need a model shader; vgui materials do not draw skinned models.
227void *viewmodel_material() {
228 if (g_style_mats[3])
229 return g_style_mats[3];
230 static void *mat = nullptr;
231 if (!mat)
232 mat = world_find_material("debug/debugtranslucentsinglecolor");
233 return mat;
234} 225}
235 226
236void chams_color(void *mat, float r, float g, float b) { 227void chams_color(void *mat, float r, float g, float b) {
@@ -260,6 +251,7 @@ void chams_alpha(void *mat, float a) {
260void chams_apply(void *mat, bool ignorez, int style, bool force_white, 251void chams_apply(void *mat, bool ignorez, int style, bool force_white,
261 const int *rgb, bool znearer) { 252 const int *rgb, bool znearer) {
262 using FlagFn = void (*)(void *, int, bool); 253 using FlagFn = void (*)(void *, int, bool);
254 bool additive = style == 2 || style == 5;
263 float r = force_white ? 1.0f : (float)rgb[0] / 255.0f; 255 float r = force_white ? 1.0f : (float)rgb[0] / 255.0f;
264 float g = force_white ? 1.0f : (float)rgb[1] / 255.0f; 256 float g = force_white ? 1.0f : (float)rgb[1] / 255.0f;
265 float b = force_white ? 1.0f : (float)rgb[2] / 255.0f; 257 float b = force_white ? 1.0f : (float)rgb[2] / 255.0f;
@@ -268,12 +260,12 @@ void chams_apply(void *mat, bool ignorez, int style, bool force_white,
268 // 0 Flat, 1 Wireframe, 2 Additive, 3 Solid, 4 White, 5 Fullbright 260 // 0 Flat, 1 Wireframe, 2 Additive, 3 Solid, 4 White, 5 Fullbright
269 // (additive white glow), 6 Glow outline (solid base; the wireframe overlay 261 // (additive white glow), 6 Glow outline (solid base; the wireframe overlay
270 // is a second draw with ZNEARER so its contour is not hidden by the base). 262 // is a second draw with ZNEARER so its contour is not hidden by the base).
263 // Styles 2/5 use debug/debugtranslucentmodelhulls, whose VMT already has
264 // $additive; ADDITIVE on debugtranslucentsinglecolor did nothing.
271 vfunc<FlagFn>(mat, 29)(mat, 1 << 15 /* IGNOREZ */, ignorez); 265 vfunc<FlagFn>(mat, 29)(mat, 1 << 15 /* IGNOREZ */, ignorez);
272 vfunc<FlagFn>(mat, 29)(mat, 1 << 21 /* TRANSLUCENT */, rgb[3] < 255);
273 vfunc<FlagFn>(mat, 29)(mat, 1 << 10 /* ZNEARER */, znearer); 266 vfunc<FlagFn>(mat, 29)(mat, 1 << 10 /* ZNEARER */, znearer);
274 vfunc<FlagFn>(mat, 29)(mat, 1 << 28 /* WIREFRAME */, style == 1); 267 vfunc<FlagFn>(mat, 29)(mat, 1 << 28 /* WIREFRAME */, style == 1);
275 vfunc<FlagFn>(mat, 29)(mat, 1 << 7 /* ADDITIVE */, 268 vfunc<FlagFn>(mat, 29)(mat, 1 << 7 /* ADDITIVE */, additive);
276 style == 2 || style == 5);
277 vfunc<FlagFn>(mat, 29)(mat, 1 << 12 /* FLAT */, style == 0); 269 vfunc<FlagFn>(mat, 29)(mat, 1 << 12 /* FLAT */, style == 0);
278 vfunc<FlagFn>(mat, 29)(mat, 1 << 6 /* SELFILLUM */, style == 5); 270 vfunc<FlagFn>(mat, 29)(mat, 1 << 6 /* SELFILLUM */, style == 5);
279} 271}
@@ -281,7 +273,6 @@ void chams_apply(void *mat, bool ignorez, int style, bool force_white,
281void chams_reset(void *mat) { 273void chams_reset(void *mat) {
282 using FlagFn = void (*)(void *, int, bool); 274 using FlagFn = void (*)(void *, int, bool);
283 vfunc<FlagFn>(mat, 29)(mat, 1 << 15, false); 275 vfunc<FlagFn>(mat, 29)(mat, 1 << 15, false);
284 vfunc<FlagFn>(mat, 29)(mat, 1 << 21, false);
285 vfunc<FlagFn>(mat, 29)(mat, 1 << 10, false); 276 vfunc<FlagFn>(mat, 29)(mat, 1 << 10, false);
286 vfunc<FlagFn>(mat, 29)(mat, 1 << 28, false); 277 vfunc<FlagFn>(mat, 29)(mat, 1 << 28, false);
287 vfunc<FlagFn>(mat, 29)(mat, 1 << 7, false); 278 vfunc<FlagFn>(mat, 29)(mat, 1 << 7, false);
@@ -317,21 +308,6 @@ void hkdModelExecute(void *self, const void *state, const void *info,
317 return false; 308 return false;
318 bool white = style == 4 || style == 5; 309 bool white = style == 4 || style == 5;
319 const int *use_rgb = rgb; 310 const int *use_rgb = rgb;
320 // Additive blending vanishes against bright backgrounds (sky,
321 // white walls, strong fog), which made the viewmodel disappear in
322 // some places. Lay down a faint translucent base so the first-person
323 // model keeps a silhouette on bright backgrounds without turning
324 // into an opaque blob; the additive pass still provides the glow.
325 if (is_vm && (style == 2 || style == 5) && rgb[3] > 0) {
326 int ba = rgb[3] / 8;
327 if (ba < 16)
328 ba = 16;
329 int drgb[4] = {rgb[0], rgb[1], rgb[2], ba};
330 chams_apply(mat, ignorez, 3, false, drgb, false);
331 g_force_override(self, mat, 0 /* OVERRIDE_NORMAL */);
332 g_orig_model_exec(self, state, info, bone);
333 chams_reset(mat);
334 }
335 chams_apply(mat, ignorez, style, white, use_rgb, false); 311 chams_apply(mat, ignorez, style, white, use_rgb, false);
336 g_force_override(self, mat, 0 /* OVERRIDE_NORMAL */); 312 g_force_override(self, mat, 0 /* OVERRIDE_NORMAL */);
337 g_orig_model_exec(self, state, info, bone); 313 g_orig_model_exec(self, state, info, bone);
@@ -391,6 +367,10 @@ void chams_preload() {
391 continue; 367 continue;
392 void *m = world_find_material(chams_material_name(i)); 368 void *m = world_find_material(chams_material_name(i));
393 if (m) { 369 if (m) {
370 // FindMaterial can hand back an unreferenced material; the engine warns
371 // ("bad reference count 0") and may reset its vars when it is bound.
372 using RefFn = void (*)(void *);
373 vfunc<RefFn>(m, 12)(m); // IMaterial::IncrementReferenceCount
394 g_style_mats[i] = m; 374 g_style_mats[i] = m;
395 logf("chams: preloaded style %d %s = %p", i, chams_material_name(i), m); 375 logf("chams: preloaded style %d %s = %p", i, chams_material_name(i), m);
396 } 376 }