mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-15 22:59:37 +00:00
Add black outline to alliance icon for terrain contrast (#4353)
## Problem The green alliance icon above player names blends into similarly-colored terrain — most notably irradiated land, which is the same green — making it hard to spot allied players. ## Fix Add a configurable dark outline to the alliance status icon, rendered in the status-icon shader (the icons come from a pre-baked atlas with no regeneration script, so this is done in-shader rather than by editing the PNG). - **Outline**: an alpha dilation gated to the alliance icon (slot 3). 8-direction sampling of the icon's alpha builds a black halo around its silhouette; interior pixels and all other status icons are untouched. - **No clipping**: the alliance icon's quad is grown outward into the atlas cell's existing transparent padding so the halo isn't clipped at the quad edge. The icon's on-screen size and position are unchanged; 8px of the cell's 16px mipmap-safety padding is preserved. - **Drain stays aligned**: the alliance-expiry drain effect's cut line and faded-icon UVs are remapped into the expanded quad space so the animation still lines up. - **Tunable**: width is driven by `name.statusOutlineWidth` in `render-settings.json` (default 6 texels; 0 disables), with a matching "Status Outline Width" slider in the debug GUI. ## Testing `tsc` and `eslint` pass. Verified in-game: the handshake now reads clearly against irradiated terrain, with the outline rendering fully (no edge clipping) and the drain animation still aligned. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
committed by
evanpelle
co-authored by
Claude Opus 4.8
parent
ad9380a35d
commit
cb0d79ed6d
@@ -40,6 +40,7 @@ export class StatusIconProgram {
|
||||
private uStatusRowOffset: WebGLUniformLocation;
|
||||
private uFadeOwnerID: WebGLUniformLocation;
|
||||
private uHoverFadeAlpha: WebGLUniformLocation;
|
||||
private uStatusOutlinePx: WebGLUniformLocation;
|
||||
|
||||
constructor(
|
||||
gl: WebGL2RenderingContext,
|
||||
@@ -83,6 +84,12 @@ export class StatusIconProgram {
|
||||
gl.getUniformLocation(this.program, "uStatusPad")!,
|
||||
sm.pad ?? 0,
|
||||
);
|
||||
// Texel size for the outline dilation sampling (static).
|
||||
gl.uniform2f(
|
||||
gl.getUniformLocation(this.program, "uStatusTexel")!,
|
||||
1 / sm.width,
|
||||
1 / sm.height,
|
||||
);
|
||||
// Flash window matches the alliance renewal prompt (10 ticks/sec)
|
||||
gl.uniform1f(
|
||||
gl.getUniformLocation(this.program, "uAllianceFlashWindowSec")!,
|
||||
@@ -111,6 +118,10 @@ export class StatusIconProgram {
|
||||
this.program,
|
||||
"uHoverFadeAlpha",
|
||||
)!;
|
||||
this.uStatusOutlinePx = gl.getUniformLocation(
|
||||
this.program,
|
||||
"uStatusOutlinePx",
|
||||
)!;
|
||||
|
||||
this.loadAtlas();
|
||||
}
|
||||
@@ -159,6 +170,7 @@ export class StatusIconProgram {
|
||||
gl.uniform1f(this.uStatusRowOffset, ns.statusRowOffset);
|
||||
gl.uniform1f(this.uFadeOwnerID, fadeOwnerID);
|
||||
gl.uniform1f(this.uHoverFadeAlpha, ns.hoverFadeAlpha);
|
||||
gl.uniform1f(this.uStatusOutlinePx, ns.statusOutlineWidth);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.playerDataTex);
|
||||
|
||||
Reference in New Issue
Block a user