From 592b865ca5c98d1df2153ea5b77f67aa8a76db60 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 14:11:40 +0100 Subject: Add HDR tonemap brightness slider The engine applies mat_monitorgamma (SDL receives changing ramp midpoints), but Wayland/XWayland compositors discard the window gamma ramp, so the gamma slider has no visible effect there. Add an in-engine brightness control that does not depend on the window system: mat_force_tonemap_scale, exposed as "HDR brightness" (x10, 0 = automatic). Drop the temporary SDL gamma ramp diagnostic. --- CONTEXT.md | 17 +++++++++-------- src/gui.cpp | 12 +++++------- src/hl2h.cpp | 28 ++++++++++++++++++++++++++++ src/hl2h.h | 1 + src/menu.cpp | 11 +++++++++-- 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index fc73214..e0af84a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -241,14 +241,15 @@ vocabulary / decisions. `ClientCmd` when their slider changes. Gamma is stored as x10 (`[view] gamma=22` = 2.2) and the slider stops at 26 because the engine clamps `mat_monitorgamma` at 2.6. The value is read back through - `ICvar::FindVar` on the next tick (ClientCmd is queued) and logged - (`view: gamma request ..., cvar reports ...`) to distinguish a rejected - command from an OS gamma ramp the compositor ignores. `SDL_SetWindowGammaRamp` - is also interposed (first 12 calls log `gamma: SDL_SetWindowGammaRamp - mid=...`) to see whether the engine ever pushes a ramp after the slider - moves; if it does and the screen does not change, the compositor is - discarding it. Both live in the always-on - `Camera / display` card (`[view] fov/vmfov/gamma`). + `ICvar::FindVar` on the next tick (ClientCmd is queued) and logged. The + engine does apply the ramp (`SDL_SetWindowGammaRamp` was called with + changing midpoints), but a Wayland/XWayland compositor discards it, so on + this setup the slider has no visible effect. +- `HDR brightness` (`[view] tonemap`, x10, 0 = automatic) sets + `mat_force_tonemap_scale`. This is in-engine tonemapping for HDR maps and + does not depend on the window system applying a gamma ramp; 10 = 1.0. + Both live in the always-on `Camera / display` card + (`[view] fov/vmfov/gamma/tonemap`). ## Map transitions diff --git a/src/gui.cpp b/src/gui.cpp index e8bcac7..83dc0a5 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -420,8 +420,12 @@ static void build_cards() { &g_fov_viewmodel); add_slider(view, "Gamma x10", "mat_monitorgamma x10: 16 = 1.6, 26 = 2.6 (engine max), stock " - "is 22.", + "is 22. Uses the OS gamma ramp; some compositors ignore it.", 16, 26, &g_gamma); + add_slider(view, "HDR brightness", + "mat_force_tonemap_scale x10 (0 = automatic). In-engine " + "brightness for HDR maps; 10 = 1.0.", + 0, 30, &g_tonemap); add_card(2, &g_fullbright, "Fullbright", "Ignore world lighting so dark areas are visible.", true); @@ -2254,12 +2258,6 @@ SDL_SetWindowGammaRamp(void *window, const unsigned short *r, const unsigned short *, const unsigned short *))dlsym( RTLD_NEXT, "SDL_SetWindowGammaRamp"); - static int logs = 0; - if (logs < 12) { - logs++; - logf("gamma: SDL_SetWindowGammaRamp mid=%u/%u/%u", r ? r[128] : 0, - g ? g[128] : 0, b ? b[128] : 0); - } return real_set_gamma_ramp ? real_set_gamma_ramp(window, r, g, b) : -1; } diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 1fc7096..a037bac 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp @@ -698,6 +698,34 @@ static void view_settings_apply(void *ent) { pending_gamma % 10, got); pending_gamma = -1; } + // In-engine brightness for HDR maps. Unlike mat_monitorgamma this does not + // depend on the window system applying a gamma ramp. + static int last_tonemap = 0; + static int pending_tonemap = -1; + if (g_tonemap != last_tonemap) { + char cmd[64]; + if (g_tonemap == 0) + snprintf(cmd, sizeof(cmd), "mat_force_tonemap_scale 0"); + else + snprintf(cmd, sizeof(cmd), "mat_force_tonemap_scale %d.%d", + g_tonemap / 10, g_tonemap % 10); + console_cmd(cmd); + pending_tonemap = g_tonemap; + last_tonemap = g_tonemap; + } + if (pending_tonemap >= 0) { + float got = -1.0f; + if (g_iface.cvar) { + using FindFn = void *(*)(void *, const char *); + void *v = vfunc(g_iface.cvar, 12)(g_iface.cvar, + "mat_force_tonemap_scale"); + if (v) + got = *(float *)((uintptr_t)v + 0x2c); + } + logf("view: tonemap request %d.%d, cvar reports %.2f", + pending_tonemap / 10, pending_tonemap % 10, got); + pending_tonemap = -1; + } } // --------------------------------------------------------------------------- diff --git a/src/hl2h.h b/src/hl2h.h index 6b142c7..a050feb 100644 --- a/src/hl2h.h +++ b/src/hl2h.h @@ -249,6 +249,7 @@ extern bool g_edge_jump; extern int g_fov_camera; extern int g_fov_viewmodel; extern int g_gamma; +extern int g_tonemap; extern int g_esp_col_hostile[3]; extern int g_esp_col_neutral[3]; extern int g_esp_col_friendly[3]; diff --git a/src/menu.cpp b/src/menu.cpp index 248aa48..033c0f9 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -82,6 +82,7 @@ bool g_edge_jump = false; int g_fov_camera = 75; // HL2's stock camera FOV int g_fov_viewmodel = 54; // HL2's stock viewmodel FOV int g_gamma = 22; // mat_monitorgamma x10, stock 2.2 +int g_tonemap = 0; // mat_force_tonemap_scale x10, 0 = automatic int g_esp_col_hostile[3] = {255, 60, 60}; int g_esp_col_neutral[3] = {220, 220, 220}; int g_esp_col_friendly[3] = {60, 255, 60}; @@ -248,8 +249,8 @@ void config_save() { g_esp_col_neutral[0], g_esp_col_neutral[1], g_esp_col_neutral[2], g_esp_col_friendly[0], g_esp_col_friendly[1], g_esp_col_friendly[2]); - fprintf(f, "[view]\nfov=%d\nvmfov=%d\ngamma=%d\n", g_fov_camera, - g_fov_viewmodel, g_gamma); + fprintf(f, "[view]\nfov=%d\nvmfov=%d\ngamma=%d\ntonemap=%d\n", + g_fov_camera, g_fov_viewmodel, g_gamma, g_tonemap); fprintf(f, "[movement]\ncrouchjump=%d\nedgejump=%d\n", (int)g_auto_crouchjump, (int)g_edge_jump); gui_config_write(f); @@ -409,6 +410,11 @@ static bool config_load() { lo = 16; hi = 26; // the engine clamps mat_monitorgamma at 2.6 stock = 22; + } else if (strcmp(key, "tonemap") == 0) { + dst = &g_tonemap; + lo = 0; + hi = 30; + stock = 0; } if (dst) { int v = atoi(val); @@ -605,6 +611,7 @@ void config_reset_defaults() { g_fov_camera = 75; g_fov_viewmodel = 54; g_gamma = 22; + g_tonemap = 0; g_esp_col_hostile[0] = 255; g_esp_col_hostile[1] = 60; g_esp_col_hostile[2] = 60; -- cgit v1.2.3