summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-04 14:11:40 +0100
committersalmonik <salmonik@tuta.io>2026-11-04 14:11:40 +0100
commit592b865ca5c98d1df2153ea5b77f67aa8a76db60 (patch)
tree4fb957603dba3bc57d316168f074410bdef3e70f
parentGamma: clamp slider to the engine's 2.6 cap, defer readback (diff)
downloadhl2h-592b865ca5c98d1df2153ea5b77f67aa8a76db60.tar.gz
hl2h-592b865ca5c98d1df2153ea5b77f67aa8a76db60.zip
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.
-rw-r--r--CONTEXT.md17
-rw-r--r--src/gui.cpp12
-rw-r--r--src/hl2h.cpp28
-rw-r--r--src/hl2h.h1
-rw-r--r--src/menu.cpp11
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.
241 `ClientCmd` when their slider changes. Gamma is stored as x10 241 `ClientCmd` when their slider changes. Gamma is stored as x10
242 (`[view] gamma=22` = 2.2) and the slider stops at 26 because the engine 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 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 244 `ICvar::FindVar` on the next tick (ClientCmd is queued) and logged. The
245 (`view: gamma request ..., cvar reports ...`) to distinguish a rejected 245 engine does apply the ramp (`SDL_SetWindowGammaRamp` was called with
246 command from an OS gamma ramp the compositor ignores. `SDL_SetWindowGammaRamp` 246 changing midpoints), but a Wayland/XWayland compositor discards it, so on
247 is also interposed (first 12 calls log `gamma: SDL_SetWindowGammaRamp 247 this setup the slider has no visible effect.
248 mid=...`) to see whether the engine ever pushes a ramp after the slider 248- `HDR brightness` (`[view] tonemap`, x10, 0 = automatic) sets
249 moves; if it does and the screen does not change, the compositor is 249 `mat_force_tonemap_scale`. This is in-engine tonemapping for HDR maps and
250 discarding it. Both live in the always-on 250 does not depend on the window system applying a gamma ramp; 10 = 1.0.
251 `Camera / display` card (`[view] fov/vmfov/gamma`). 251 Both live in the always-on `Camera / display` card
252 (`[view] fov/vmfov/gamma/tonemap`).
252 253
253## Map transitions 254## Map transitions
254 255
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() {
420 &g_fov_viewmodel); 420 &g_fov_viewmodel);
421 add_slider(view, "Gamma x10", 421 add_slider(view, "Gamma x10",
422 "mat_monitorgamma x10: 16 = 1.6, 26 = 2.6 (engine max), stock " 422 "mat_monitorgamma x10: 16 = 1.6, 26 = 2.6 (engine max), stock "
423 "is 22.", 423 "is 22. Uses the OS gamma ramp; some compositors ignore it.",
424 16, 26, &g_gamma); 424 16, 26, &g_gamma);
425 add_slider(view, "HDR brightness",
426 "mat_force_tonemap_scale x10 (0 = automatic). In-engine "
427 "brightness for HDR maps; 10 = 1.0.",
428 0, 30, &g_tonemap);
425 429
426 add_card(2, &g_fullbright, "Fullbright", 430 add_card(2, &g_fullbright, "Fullbright",
427 "Ignore world lighting so dark areas are visible.", true); 431 "Ignore world lighting so dark areas are visible.", true);
@@ -2254,12 +2258,6 @@ SDL_SetWindowGammaRamp(void *window, const unsigned short *r,
2254 const unsigned short *, 2258 const unsigned short *,
2255 const unsigned short *))dlsym( 2259 const unsigned short *))dlsym(
2256 RTLD_NEXT, "SDL_SetWindowGammaRamp"); 2260 RTLD_NEXT, "SDL_SetWindowGammaRamp");
2257 static int logs = 0;
2258 if (logs < 12) {
2259 logs++;
2260 logf("gamma: SDL_SetWindowGammaRamp mid=%u/%u/%u", r ? r[128] : 0,
2261 g ? g[128] : 0, b ? b[128] : 0);
2262 }
2263 return real_set_gamma_ramp ? real_set_gamma_ramp(window, r, g, b) : -1; 2261 return real_set_gamma_ramp ? real_set_gamma_ramp(window, r, g, b) : -1;
2264} 2262}
2265 2263
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) {
698 pending_gamma % 10, got); 698 pending_gamma % 10, got);
699 pending_gamma = -1; 699 pending_gamma = -1;
700 } 700 }
701 // In-engine brightness for HDR maps. Unlike mat_monitorgamma this does not
702 // depend on the window system applying a gamma ramp.
703 static int last_tonemap = 0;
704 static int pending_tonemap = -1;
705 if (g_tonemap != last_tonemap) {
706 char cmd[64];
707 if (g_tonemap == 0)
708 snprintf(cmd, sizeof(cmd), "mat_force_tonemap_scale 0");
709 else
710 snprintf(cmd, sizeof(cmd), "mat_force_tonemap_scale %d.%d",
711 g_tonemap / 10, g_tonemap % 10);
712 console_cmd(cmd);
713 pending_tonemap = g_tonemap;
714 last_tonemap = g_tonemap;
715 }
716 if (pending_tonemap >= 0) {
717 float got = -1.0f;
718 if (g_iface.cvar) {
719 using FindFn = void *(*)(void *, const char *);
720 void *v = vfunc<FindFn>(g_iface.cvar, 12)(g_iface.cvar,
721 "mat_force_tonemap_scale");
722 if (v)
723 got = *(float *)((uintptr_t)v + 0x2c);
724 }
725 logf("view: tonemap request %d.%d, cvar reports %.2f",
726 pending_tonemap / 10, pending_tonemap % 10, got);
727 pending_tonemap = -1;
728 }
701} 729}
702 730
703// --------------------------------------------------------------------------- 731// ---------------------------------------------------------------------------
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;
249extern int g_fov_camera; 249extern int g_fov_camera;
250extern int g_fov_viewmodel; 250extern int g_fov_viewmodel;
251extern int g_gamma; 251extern int g_gamma;
252extern int g_tonemap;
252extern int g_esp_col_hostile[3]; 253extern int g_esp_col_hostile[3];
253extern int g_esp_col_neutral[3]; 254extern int g_esp_col_neutral[3];
254extern int g_esp_col_friendly[3]; 255extern 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;
82int g_fov_camera = 75; // HL2's stock camera FOV 82int g_fov_camera = 75; // HL2's stock camera FOV
83int g_fov_viewmodel = 54; // HL2's stock viewmodel FOV 83int g_fov_viewmodel = 54; // HL2's stock viewmodel FOV
84int g_gamma = 22; // mat_monitorgamma x10, stock 2.2 84int g_gamma = 22; // mat_monitorgamma x10, stock 2.2
85int g_tonemap = 0; // mat_force_tonemap_scale x10, 0 = automatic
85int g_esp_col_hostile[3] = {255, 60, 60}; 86int g_esp_col_hostile[3] = {255, 60, 60};
86int g_esp_col_neutral[3] = {220, 220, 220}; 87int g_esp_col_neutral[3] = {220, 220, 220};
87int g_esp_col_friendly[3] = {60, 255, 60}; 88int g_esp_col_friendly[3] = {60, 255, 60};
@@ -248,8 +249,8 @@ void config_save() {
248 g_esp_col_neutral[0], g_esp_col_neutral[1], g_esp_col_neutral[2], 249 g_esp_col_neutral[0], g_esp_col_neutral[1], g_esp_col_neutral[2],
249 g_esp_col_friendly[0], g_esp_col_friendly[1], 250 g_esp_col_friendly[0], g_esp_col_friendly[1],
250 g_esp_col_friendly[2]); 251 g_esp_col_friendly[2]);
251 fprintf(f, "[view]\nfov=%d\nvmfov=%d\ngamma=%d\n", g_fov_camera, 252 fprintf(f, "[view]\nfov=%d\nvmfov=%d\ngamma=%d\ntonemap=%d\n",
252 g_fov_viewmodel, g_gamma); 253 g_fov_camera, g_fov_viewmodel, g_gamma, g_tonemap);
253 fprintf(f, "[movement]\ncrouchjump=%d\nedgejump=%d\n", 254 fprintf(f, "[movement]\ncrouchjump=%d\nedgejump=%d\n",
254 (int)g_auto_crouchjump, (int)g_edge_jump); 255 (int)g_auto_crouchjump, (int)g_edge_jump);
255 gui_config_write(f); 256 gui_config_write(f);
@@ -409,6 +410,11 @@ static bool config_load() {
409 lo = 16; 410 lo = 16;
410 hi = 26; // the engine clamps mat_monitorgamma at 2.6 411 hi = 26; // the engine clamps mat_monitorgamma at 2.6
411 stock = 22; 412 stock = 22;
413 } else if (strcmp(key, "tonemap") == 0) {
414 dst = &g_tonemap;
415 lo = 0;
416 hi = 30;
417 stock = 0;
412 } 418 }
413 if (dst) { 419 if (dst) {
414 int v = atoi(val); 420 int v = atoi(val);
@@ -605,6 +611,7 @@ void config_reset_defaults() {
605 g_fov_camera = 75; 611 g_fov_camera = 75;
606 g_fov_viewmodel = 54; 612 g_fov_viewmodel = 54;
607 g_gamma = 22; 613 g_gamma = 22;
614 g_tonemap = 0;
608 g_esp_col_hostile[0] = 255; 615 g_esp_col_hostile[0] = 255;
609 g_esp_col_hostile[1] = 60; 616 g_esp_col_hostile[1] = 60;
610 g_esp_col_hostile[2] = 60; 617 g_esp_col_hostile[2] = 60;