Add territory saturation and opacity graphics settings

Expose two new user-configurable map-overlay controls in the graphics
settings modal: territory saturation (mutes fill colors toward grayscale)
and territory opacity (lets terrain show through the fill).

The territory fragment shader blends the fill toward its luminance based
on uSaturation and applies uTerritoryAlpha as the absolute fill opacity.
Both are wired through RenderSettings, the GraphicsOverrides schema,
applyGraphicsOverrides, the debug Layout sliders, and TerritoryPass
uniforms, with defaults (saturation 1, alpha 0.588) in render-settings.json.
Adds the corresponding en.json label/description strings.
This commit is contained in:
evanpelle
2026-06-09 19:16:04 -07:00
parent 855695b78e
commit 2d28d5463b
10 changed files with 184 additions and 0 deletions
@@ -32,6 +32,14 @@ const HIGHLIGHT_THICKEN_MIN = 0;
const HIGHLIGHT_THICKEN_MAX = 5;
const HIGHLIGHT_THICKEN_STEP = 1;
const TERRITORY_SAT_MIN = 0;
const TERRITORY_SAT_MAX = 1;
const TERRITORY_SAT_STEP = 0.01;
const TERRITORY_ALPHA_MIN = 0;
const TERRITORY_ALPHA_MAX = 1;
const TERRITORY_ALPHA_STEP = 0.01;
// Train track "draw distance" is presented inverted: a higher slider value means
// tracks stay visible when more zoomed out, i.e. a lower railMinZoom.
const RAIL_ZOOM_MIN = 0;
@@ -193,6 +201,20 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
);
}
private currentTerritorySat(): number {
return (
this.userSettings.graphicsOverrides().mapOverlay?.territorySaturation ??
renderDefaults.mapOverlay.territorySaturation
);
}
private currentTerritoryAlpha(): number {
return (
this.userSettings.graphicsOverrides().mapOverlay?.territoryAlpha ??
renderDefaults.mapOverlay.territoryAlpha
);
}
private currentRailMinZoom(): number {
return (
this.userSettings.graphicsOverrides().railroad?.railMinZoom ??
@@ -215,6 +237,16 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
this.patchMapOverlay({ highlightThicken: value });
}
private onTerritorySatChange(event: Event) {
const value = parseFloat((event.target as HTMLInputElement).value);
this.patchMapOverlay({ territorySaturation: value });
}
private onTerritoryAlphaChange(event: Event) {
const value = parseFloat((event.target as HTMLInputElement).value);
this.patchMapOverlay({ territoryAlpha: value });
}
private onRailDrawDistanceChange(event: Event) {
const drawDistance = parseFloat((event.target as HTMLInputElement).value);
// Invert: higher draw distance => tracks visible when more zoomed out.
@@ -287,6 +319,8 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
const highlightFill = this.currentHighlightFill();
const highlightBrighten = this.currentHighlightBrighten();
const highlightThicken = this.currentHighlightThicken();
const territorySat = this.currentTerritorySat();
const territoryAlpha = this.currentTerritoryAlpha();
const railDrawDistance = RAIL_ZOOM_MAX - this.currentRailMinZoom();
return html`
@@ -499,6 +533,56 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
</div>
</div>
<div
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
>
<div class="flex-1">
<div class="font-medium">
${translateText("graphics_setting.territory_sat_label")}
</div>
<div class="text-sm text-slate-400">
${translateText("graphics_setting.territory_sat_desc")}
</div>
<input
type="range"
min=${TERRITORY_SAT_MIN}
max=${TERRITORY_SAT_MAX}
step=${TERRITORY_SAT_STEP}
.value=${String(territorySat)}
@input=${this.onTerritorySatChange}
class="w-full border border-slate-500 rounded-lg"
/>
</div>
<div class="text-sm text-slate-400 w-12 text-right">
${territorySat.toFixed(2)}
</div>
</div>
<div
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
>
<div class="flex-1">
<div class="font-medium">
${translateText("graphics_setting.territory_alpha_label")}
</div>
<div class="text-sm text-slate-400">
${translateText("graphics_setting.territory_alpha_desc")}
</div>
<input
type="range"
min=${TERRITORY_ALPHA_MIN}
max=${TERRITORY_ALPHA_MAX}
step=${TERRITORY_ALPHA_STEP}
.value=${String(territoryAlpha)}
@input=${this.onTerritoryAlphaChange}
class="w-full border border-slate-500 rounded-lg"
/>
</div>
<div class="text-sm text-slate-400 w-12 text-right">
${territoryAlpha.toFixed(2)}
</div>
</div>
<div
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
>