diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-04 14:15:49 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-04 14:15:49 +0100 |
| commit | 35bbdf5ee97961ecca7cda2c3ad98aed558ace60 (patch) | |
| tree | 3d79113dcf19e5f2b8c353aebe72e03920df1d32 | |
| parent | Add HDR tonemap brightness slider (diff) | |
| download | hl2h-35bbdf5ee97961ecca7cda2c3ad98aed558ace60.tar.gz hl2h-35bbdf5ee97961ecca7cda2c3ad98aed558ace60.zip | |
Remove gamma slider; keep HDR brightness
Wayland/XWayland discards window gamma ramps, so mat_monitorgamma could not
work on the development setup. Drop the slider, config key and readback.
Keep the in-engine HDR tonemap brightness and document that Fullbright turns
tonemapping off.
| -rw-r--r-- | CONTEXT.md | 22 | ||||
| -rw-r--r-- | src/gui.cpp | 25 | ||||
| -rw-r--r-- | src/hl2h.cpp | 32 | ||||
| -rw-r--r-- | src/hl2h.h | 1 | ||||
| -rw-r--r-- | src/menu.cpp | 11 |
5 files changed, 19 insertions, 72 deletions
| @@ -21,7 +21,7 @@ covers ESP, aimbot, triggerbot and silent aim. | |||
| 21 | - `HL2H_NO_SERVER=1` — disable server-side health reads. | 21 | - `HL2H_NO_SERVER=1` — disable server-side health reads. |
| 22 | - Config: `$XDG_CONFIG_HOME/hl2hake/config`, falling back to | 22 | - Config: `$XDG_CONFIG_HOME/hl2hake/config`, falling back to |
| 23 | `~/.config/hl2hake/config`. Plain INI, saved on every change. New sections: | 23 | `~/.config/hl2hake/config`. Plain INI, saved on every change. New sections: |
| 24 | `[view]` (camera FOV, viewmodel FOV, gamma x10) and `[movement]` | 24 | `[view]` (camera FOV, viewmodel FOV, HDR brightness) and `[movement]` |
| 25 | (crouch-jump, edge jump). | 25 | (crouch-jump, edge jump). |
| 26 | 26 | ||
| 27 | ## Runtime architecture | 27 | ## Runtime architecture |
| @@ -237,19 +237,17 @@ vocabulary / decisions. | |||
| 237 | client netvar every tick. The camera slider is 40..140 (stock 75) and the | 237 | client netvar every tick. The camera slider is 40..140 (stock 75) and the |
| 238 | viewmodel slider 20..120 (stock 54); 0 is not allowed (old configs with 0 | 238 | viewmodel slider 20..120 (stock 54); 0 is not allowed (old configs with 0 |
| 239 | migrate to the stock value). | 239 | migrate to the stock value). |
| 240 | - `viewmodel_fov` and `mat_monitorgamma` are client cvars; applied through | 240 | - `viewmodel_fov` is a client cvar, applied through `ClientCmd` when its |
| 241 | `ClientCmd` when their slider changes. Gamma is stored as x10 | 241 | slider changes. |
| 242 | (`[view] gamma=22` = 2.2) and the slider stops at 26 because the engine | ||
| 243 | clamps `mat_monitorgamma` at 2.6. The value is read back through | ||
| 244 | `ICvar::FindVar` on the next tick (ClientCmd is queued) and logged. The | ||
| 245 | engine does apply the ramp (`SDL_SetWindowGammaRamp` was called with | ||
| 246 | changing midpoints), but a Wayland/XWayland compositor discards it, so on | ||
| 247 | this setup the slider has no visible effect. | ||
| 248 | - `HDR brightness` (`[view] tonemap`, x10, 0 = automatic) sets | 242 | - `HDR brightness` (`[view] tonemap`, x10, 0 = automatic) sets |
| 249 | `mat_force_tonemap_scale`. This is in-engine tonemapping for HDR maps and | 243 | `mat_force_tonemap_scale`. This is in-engine tonemapping for HDR maps and |
| 250 | does not depend on the window system applying a gamma ramp; 10 = 1.0. | 244 | does not depend on the window system; 10 = 1.0. It has no visible effect |
| 251 | Both live in the always-on `Camera / display` card | 245 | while Fullbright is on (fullbright bypasses tonemapping). |
| 252 | (`[view] fov/vmfov/gamma/tonemap`). | 246 | - `mat_monitorgamma` was tried and removed: the engine applies the ramp (SDL |
| 247 | receives changing midpoints), but Wayland/XWayland compositors discard | ||
| 248 | window gamma ramps, so the slider did nothing on the development setup. | ||
| 249 | - Both controls live in the always-on `Camera / display` card | ||
| 250 | (`[view] fov/vmfov/tonemap`). | ||
| 253 | 251 | ||
| 254 | ## Map transitions | 252 | ## Map transitions |
| 255 | 253 | ||
diff --git a/src/gui.cpp b/src/gui.cpp index 83dc0a5..59c4364 100644 --- a/src/gui.cpp +++ b/src/gui.cpp | |||
| @@ -411,20 +411,17 @@ static void build_cards() { | |||
| 411 | g_ctrls[g_nctrl - 1].zero_unlimited = true; | 411 | g_ctrls[g_nctrl - 1].zero_unlimited = true; |
| 412 | 412 | ||
| 413 | int view = add_card(2, nullptr, "Camera / display", | 413 | int view = add_card(2, nullptr, "Camera / display", |
| 414 | "Camera FOV, viewmodel FOV and monitor gamma.", true); | 414 | "Camera FOV, viewmodel FOV and HDR brightness.", true); |
| 415 | add_slider(view, "Camera FOV", | 415 | add_slider(view, "Camera FOV", |
| 416 | "World camera field of view (40-140; stock 75).", 40, 140, | 416 | "World camera field of view (40-140; stock 75).", 40, 140, |
| 417 | &g_fov_camera); | 417 | &g_fov_camera); |
| 418 | add_slider(view, "Viewmodel FOV", | 418 | add_slider(view, "Viewmodel FOV", |
| 419 | "Weapon model field of view (20-120; stock 54).", 20, 120, | 419 | "Weapon model field of view (20-120; stock 54).", 20, 120, |
| 420 | &g_fov_viewmodel); | 420 | &g_fov_viewmodel); |
| 421 | add_slider(view, "Gamma x10", | ||
| 422 | "mat_monitorgamma x10: 16 = 1.6, 26 = 2.6 (engine max), stock " | ||
| 423 | "is 22. Uses the OS gamma ramp; some compositors ignore it.", | ||
| 424 | 16, 26, &g_gamma); | ||
| 425 | add_slider(view, "HDR brightness", | 421 | add_slider(view, "HDR brightness", |
| 426 | "mat_force_tonemap_scale x10 (0 = automatic). In-engine " | 422 | "mat_force_tonemap_scale x10 (0 = automatic). In-engine " |
| 427 | "brightness for HDR maps; 10 = 1.0.", | 423 | "brightness for HDR maps; 10 = 1.0. No effect while Fullbright " |
| 424 | "is on.", | ||
| 428 | 0, 30, &g_tonemap); | 425 | 0, 30, &g_tonemap); |
| 429 | 426 | ||
| 430 | add_card(2, &g_fullbright, "Fullbright", | 427 | add_card(2, &g_fullbright, "Fullbright", |
| @@ -2245,22 +2242,6 @@ SDL_WarpMouseGlobal(int x, int y) { | |||
| 2245 | real_warp_global(x, y); | 2242 | real_warp_global(x, y); |
| 2246 | } | 2243 | } |
| 2247 | 2244 | ||
| 2248 | // Diagnostic: tell whether mat_monitorgamma reaches the SDL gamma ramp at all. | ||
| 2249 | static int (*real_set_gamma_ramp)(void *, const unsigned short *, | ||
| 2250 | const unsigned short *, | ||
| 2251 | const unsigned short *) = nullptr; | ||
| 2252 | |||
| 2253 | extern "C" __attribute__((visibility("default"))) int | ||
| 2254 | SDL_SetWindowGammaRamp(void *window, const unsigned short *r, | ||
| 2255 | const unsigned short *g, const unsigned short *b) { | ||
| 2256 | if (!real_set_gamma_ramp) | ||
| 2257 | real_set_gamma_ramp = (int (*)(void *, const unsigned short *, | ||
| 2258 | const unsigned short *, | ||
| 2259 | const unsigned short *))dlsym( | ||
| 2260 | RTLD_NEXT, "SDL_SetWindowGammaRamp"); | ||
| 2261 | return real_set_gamma_ramp ? real_set_gamma_ramp(window, r, g, b) : -1; | ||
| 2262 | } | ||
| 2263 | |||
| 2264 | static unsigned int (*real_get_rel_mouse)(int *, int *) = nullptr; | 2245 | static unsigned int (*real_get_rel_mouse)(int *, int *) = nullptr; |
| 2265 | static int (*real_poll_event)(void *) = nullptr; | 2246 | static int (*real_poll_event)(void *) = nullptr; |
| 2266 | 2247 | ||
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index a037bac..ca7ee85 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -655,13 +655,13 @@ static void install_uniform_random_hook() { | |||
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | // --------------------------------------------------------------------------- | 657 | // --------------------------------------------------------------------------- |
| 658 | // camera / viewmodel FOV and gamma | 658 | // camera / viewmodel FOV and HDR brightness |
| 659 | // --------------------------------------------------------------------------- | 659 | // --------------------------------------------------------------------------- |
| 660 | // | 660 | // |
| 661 | // The rendered camera FOV is derived from C_BasePlayer::m_iDefaultFOV every | 661 | // The rendered camera FOV is derived from C_BasePlayer::m_iDefaultFOV every |
| 662 | // frame (CViewRender::OnRenderStart copies it into default_fov), so writing | 662 | // frame (CViewRender::OnRenderStart copies it into default_fov), so writing |
| 663 | // the client netvar is enough and needs no server command. The viewmodel FOV | 663 | // the client netvar is enough and needs no server command. The viewmodel FOV |
| 664 | // and monitor gamma are plain client cvars. | 664 | // is a plain client cvar. |
| 665 | 665 | ||
| 666 | static void view_settings_apply(void *ent) { | 666 | static void view_settings_apply(void *ent) { |
| 667 | if (g_net.default_fov >= 0 && ent) | 667 | if (g_net.default_fov >= 0 && ent) |
| @@ -673,33 +673,9 @@ static void view_settings_apply(void *ent) { | |||
| 673 | console_cmd(cmd); | 673 | console_cmd(cmd); |
| 674 | last_vm = g_fov_viewmodel; | 674 | last_vm = g_fov_viewmodel; |
| 675 | } | 675 | } |
| 676 | static int last_gamma = 22; | ||
| 677 | static int pending_gamma = -1; | ||
| 678 | if (g_gamma != last_gamma) { | ||
| 679 | char cmd[48]; | ||
| 680 | snprintf(cmd, sizeof(cmd), "mat_monitorgamma %d.%d", g_gamma / 10, | ||
| 681 | g_gamma % 10); | ||
| 682 | console_cmd(cmd); | ||
| 683 | pending_gamma = g_gamma; | ||
| 684 | last_gamma = g_gamma; | ||
| 685 | } | ||
| 686 | if (pending_gamma >= 0) { | ||
| 687 | // ClientCmd is queued, so read the cvar on the next tick to see the value | ||
| 688 | // the engine actually accepted (it clamps mat_monitorgamma at 2.6). | ||
| 689 | float got = -1.0f; | ||
| 690 | if (g_iface.cvar) { | ||
| 691 | using FindFn = void *(*)(void *, const char *); | ||
| 692 | void *v = vfunc<FindFn>(g_iface.cvar, 12)(g_iface.cvar, | ||
| 693 | "mat_monitorgamma"); | ||
| 694 | if (v) | ||
| 695 | got = *(float *)((uintptr_t)v + 0x2c); // ConVar m_Value.f | ||
| 696 | } | ||
| 697 | logf("view: gamma request %d.%d, cvar reports %.2f", pending_gamma / 10, | ||
| 698 | pending_gamma % 10, got); | ||
| 699 | pending_gamma = -1; | ||
| 700 | } | ||
| 701 | // In-engine brightness for HDR maps. Unlike mat_monitorgamma this does not | 676 | // In-engine brightness for HDR maps. Unlike mat_monitorgamma this does not |
| 702 | // depend on the window system applying a gamma ramp. | 677 | // depend on the window system applying a gamma ramp. Fullbright bypasses |
| 678 | // tonemapping, so the slider only has a visible effect while it is off. | ||
| 703 | static int last_tonemap = 0; | 679 | static int last_tonemap = 0; |
| 704 | static int pending_tonemap = -1; | 680 | static int pending_tonemap = -1; |
| 705 | if (g_tonemap != last_tonemap) { | 681 | if (g_tonemap != last_tonemap) { |
| @@ -248,7 +248,6 @@ extern bool g_auto_crouchjump; | |||
| 248 | extern bool g_edge_jump; | 248 | extern bool g_edge_jump; |
| 249 | extern int g_fov_camera; | 249 | extern int g_fov_camera; |
| 250 | extern int g_fov_viewmodel; | 250 | extern int g_fov_viewmodel; |
| 251 | extern int g_gamma; | ||
| 252 | extern int g_tonemap; | 251 | extern int g_tonemap; |
| 253 | extern int g_esp_col_hostile[3]; | 252 | extern int g_esp_col_hostile[3]; |
| 254 | extern int g_esp_col_neutral[3]; | 253 | extern int g_esp_col_neutral[3]; |
diff --git a/src/menu.cpp b/src/menu.cpp index 033c0f9..020d2c5 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -81,7 +81,6 @@ bool g_auto_crouchjump = false; | |||
| 81 | bool g_edge_jump = false; | 81 | bool g_edge_jump = false; |
| 82 | int g_fov_camera = 75; // HL2's stock camera FOV | 82 | int g_fov_camera = 75; // HL2's stock camera FOV |
| 83 | int g_fov_viewmodel = 54; // HL2's stock viewmodel FOV | 83 | int g_fov_viewmodel = 54; // HL2's stock viewmodel FOV |
| 84 | int g_gamma = 22; // mat_monitorgamma x10, stock 2.2 | ||
| 85 | int g_tonemap = 0; // mat_force_tonemap_scale x10, 0 = automatic | 84 | int g_tonemap = 0; // mat_force_tonemap_scale x10, 0 = automatic |
| 86 | int g_esp_col_hostile[3] = {255, 60, 60}; | 85 | int g_esp_col_hostile[3] = {255, 60, 60}; |
| 87 | int g_esp_col_neutral[3] = {220, 220, 220}; | 86 | int g_esp_col_neutral[3] = {220, 220, 220}; |
| @@ -249,8 +248,8 @@ void config_save() { | |||
| 249 | g_esp_col_neutral[0], g_esp_col_neutral[1], g_esp_col_neutral[2], | 248 | g_esp_col_neutral[0], g_esp_col_neutral[1], g_esp_col_neutral[2], |
| 250 | g_esp_col_friendly[0], g_esp_col_friendly[1], | 249 | g_esp_col_friendly[0], g_esp_col_friendly[1], |
| 251 | g_esp_col_friendly[2]); | 250 | g_esp_col_friendly[2]); |
| 252 | fprintf(f, "[view]\nfov=%d\nvmfov=%d\ngamma=%d\ntonemap=%d\n", | 251 | fprintf(f, "[view]\nfov=%d\nvmfov=%d\ntonemap=%d\n", g_fov_camera, |
| 253 | g_fov_camera, g_fov_viewmodel, g_gamma, g_tonemap); | 252 | g_fov_viewmodel, g_tonemap); |
| 254 | fprintf(f, "[movement]\ncrouchjump=%d\nedgejump=%d\n", | 253 | fprintf(f, "[movement]\ncrouchjump=%d\nedgejump=%d\n", |
| 255 | (int)g_auto_crouchjump, (int)g_edge_jump); | 254 | (int)g_auto_crouchjump, (int)g_edge_jump); |
| 256 | gui_config_write(f); | 255 | gui_config_write(f); |
| @@ -405,11 +404,6 @@ static bool config_load() { | |||
| 405 | lo = 20; | 404 | lo = 20; |
| 406 | hi = 120; | 405 | hi = 120; |
| 407 | stock = 54; | 406 | stock = 54; |
| 408 | } else if (strcmp(key, "gamma") == 0) { | ||
| 409 | dst = &g_gamma; | ||
| 410 | lo = 16; | ||
| 411 | hi = 26; // the engine clamps mat_monitorgamma at 2.6 | ||
| 412 | stock = 22; | ||
| 413 | } else if (strcmp(key, "tonemap") == 0) { | 407 | } else if (strcmp(key, "tonemap") == 0) { |
| 414 | dst = &g_tonemap; | 408 | dst = &g_tonemap; |
| 415 | lo = 0; | 409 | lo = 0; |
| @@ -610,7 +604,6 @@ void config_reset_defaults() { | |||
| 610 | g_edge_jump = false; | 604 | g_edge_jump = false; |
| 611 | g_fov_camera = 75; | 605 | g_fov_camera = 75; |
| 612 | g_fov_viewmodel = 54; | 606 | g_fov_viewmodel = 54; |
| 613 | g_gamma = 22; | ||
| 614 | g_tonemap = 0; | 607 | g_tonemap = 0; |
| 615 | g_esp_col_hostile[0] = 255; | 608 | g_esp_col_hostile[0] = 255; |
| 616 | g_esp_col_hostile[1] = 60; | 609 | g_esp_col_hostile[1] = 60; |
