Tune structure rendering to match the previous version's look

Bring the WebGL structure renderer closer to the old canvas render:
larger icons, classic icon styling by default, and more prominent,
better-positioned level numbers.
This commit is contained in:
evanpelle
2026-06-13 09:28:47 -07:00
parent de84f0e867
commit 49a12519d7
7 changed files with 53 additions and 8 deletions
@@ -320,7 +320,7 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
private currentClassicIcons(): boolean { private currentClassicIcons(): boolean {
return ( return (
this.userSettings.graphicsOverrides().structure?.classicIcons ?? false this.userSettings.graphicsOverrides().structure?.classicIcons ?? true
); );
} }
+2 -2
View File
@@ -27,8 +27,8 @@ export function applyGraphicsOverrides(
if (overrides.name?.hoverGlowAlpha !== undefined) { if (overrides.name?.hoverGlowAlpha !== undefined) {
settings.name.hoverGlowAlpha = overrides.name.hoverGlowAlpha; settings.name.hoverGlowAlpha = overrides.name.hoverGlowAlpha;
} }
if (overrides.structure?.classicIcons === true) { if (overrides.structure?.classicIcons ?? true) {
// Classic look: lighter player-colored shape behind a darkened // Classic look (default): lighter player-colored shape behind a darkened
// player-colored icon glyph (matching the old canvas renderer's // player-colored icon glyph (matching the old canvas renderer's
// structureColors().dark), with a touch of translucency. // structureColors().dark), with a touch of translucency.
settings.structure.borderDarken = 0.7; settings.structure.borderDarken = 0.7;
+1
View File
@@ -191,6 +191,7 @@ export interface RenderSettings {
structureLevel: { structureLevel: {
scale: number; scale: number;
outlineWidth: number; outlineWidth: number;
offsetY: number;
}; };
bar: { bar: {
healthBarW: number; healthBarW: number;
+31 -1
View File
@@ -214,7 +214,7 @@ export function buildTree(s: RenderSettings, d: RenderSettings): DebugNode[] {
]), ]),
folder("Structure", [ folder("Structure", [
slider(s.structure, "iconSize", d.structure, 10, 60, 1), slider(s.structure, "iconSize", d.structure, 10, 100, 1),
slider(s.structure, "dotsZoomThreshold", d.structure, 0.1, 2, 0.05), slider(s.structure, "dotsZoomThreshold", d.structure, 0.1, 2, 0.05),
slider( slider(
s.structure, s.structure,
@@ -269,6 +269,36 @@ export function buildTree(s: RenderSettings, d: RenderSettings): DebugNode[] {
), ),
]), ]),
folder("Structure Level", [
slider(
s.structureLevel,
"scale",
d.structureLevel,
0.5,
3,
0.05,
"Scale",
),
slider(
s.structureLevel,
"outlineWidth",
d.structureLevel,
0,
20,
0.1,
"Outline Width (px)",
),
slider(
s.structureLevel,
"offsetY",
d.structureLevel,
-2,
2,
0.05,
"Height Above Icon",
),
]),
folder("Bar", [ folder("Bar", [
slider(s.bar, "healthBarW", d.bar, 3, 30, 1, "Health Width"), slider(s.bar, "healthBarW", d.bar, 3, 30, 1, "Health Width"),
slider(s.bar, "healthBarH", d.bar, 1, 10, 1, "Health Height"), slider(s.bar, "healthBarH", d.bar, 1, 10, 1, "Health Height"),
@@ -65,9 +65,11 @@ export class StructureLevelPass {
private uIconSize: WebGLUniformLocation; private uIconSize: WebGLUniformLocation;
private uDotsThreshold: WebGLUniformLocation; private uDotsThreshold: WebGLUniformLocation;
private uScaleFactor: WebGLUniformLocation; private uScaleFactor: WebGLUniformLocation;
private uIconGrowZoom: WebGLUniformLocation;
private uDistRange: WebGLUniformLocation; private uDistRange: WebGLUniformLocation;
private uOutlineWidth: WebGLUniformLocation; private uOutlineWidth: WebGLUniformLocation;
private uLevelScale: WebGLUniformLocation; private uLevelScale: WebGLUniformLocation;
private uLevelOffsetY: WebGLUniformLocation;
private uHighlightMask: WebGLUniformLocation; private uHighlightMask: WebGLUniformLocation;
private uHighlightDimAlpha: WebGLUniformLocation; private uHighlightDimAlpha: WebGLUniformLocation;
@@ -152,9 +154,11 @@ export class StructureLevelPass {
"uDotsThreshold", "uDotsThreshold",
)!; )!;
this.uScaleFactor = gl.getUniformLocation(this.program, "uScaleFactor")!; this.uScaleFactor = gl.getUniformLocation(this.program, "uScaleFactor")!;
this.uIconGrowZoom = gl.getUniformLocation(this.program, "uIconGrowZoom")!;
this.uDistRange = gl.getUniformLocation(this.program, "uDistRange")!; this.uDistRange = gl.getUniformLocation(this.program, "uDistRange")!;
this.uOutlineWidth = gl.getUniformLocation(this.program, "uOutlineWidth")!; this.uOutlineWidth = gl.getUniformLocation(this.program, "uOutlineWidth")!;
this.uLevelScale = gl.getUniformLocation(this.program, "uLevelScale")!; this.uLevelScale = gl.getUniformLocation(this.program, "uLevelScale")!;
this.uLevelOffsetY = gl.getUniformLocation(this.program, "uLevelOffsetY")!;
this.uHighlightMask = gl.getUniformLocation( this.uHighlightMask = gl.getUniformLocation(
this.program, this.program,
"uHighlightMask", "uHighlightMask",
@@ -290,9 +294,11 @@ export class StructureLevelPass {
gl.uniform1f(this.uIconSize, ss.iconSize); gl.uniform1f(this.uIconSize, ss.iconSize);
gl.uniform1f(this.uDotsThreshold, ss.dotsZoomThreshold); gl.uniform1f(this.uDotsThreshold, ss.dotsZoomThreshold);
gl.uniform1f(this.uScaleFactor, ss.iconScaleFactorZoomedOut); gl.uniform1f(this.uScaleFactor, ss.iconScaleFactorZoomedOut);
gl.uniform1f(this.uIconGrowZoom, ss.iconGrowZoom);
gl.uniform1f(this.uDistRange, this.distanceRange); gl.uniform1f(this.uDistRange, this.distanceRange);
gl.uniform1f(this.uOutlineWidth, sl.outlineWidth); gl.uniform1f(this.uOutlineWidth, sl.outlineWidth);
gl.uniform1f(this.uLevelScale, sl.scale); gl.uniform1f(this.uLevelScale, sl.scale);
gl.uniform1f(this.uLevelOffsetY, sl.offsetY);
gl.uniform1i(this.uHighlightMask, this.highlightMask); gl.uniform1i(this.uHighlightMask, this.highlightMask);
gl.uniform1f(this.uHighlightDimAlpha, ss.highlightDimAlpha); gl.uniform1f(this.uHighlightDimAlpha, ss.highlightDimAlpha);
+4 -3
View File
@@ -111,7 +111,7 @@
"railThickness": 1 "railThickness": 1
}, },
"structure": { "structure": {
"iconSize": 50, "iconSize": 60,
"dotsZoomThreshold": 1.2, "dotsZoomThreshold": 1.2,
"dotScale": 0.3, "dotScale": 0.3,
"iconScaleFactorZoomedOut": 3, "iconScaleFactorZoomedOut": 3,
@@ -153,8 +153,9 @@
"iconDarken": 0 "iconDarken": 0
}, },
"structureLevel": { "structureLevel": {
"scale": 1.2, "scale": 1,
"outlineWidth": 1.4 "outlineWidth": 8,
"offsetY": -0.4
}, },
"bar": { "bar": {
"healthBarW": 11, "healthBarW": 11,
@@ -16,12 +16,14 @@ uniform float uZoom;
uniform float uIconSize; uniform float uIconSize;
uniform float uDotsThreshold; uniform float uDotsThreshold;
uniform float uScaleFactor; uniform float uScaleFactor;
uniform float uIconGrowZoom;
// Text sizing // Text sizing
uniform float uFontSize; uniform float uFontSize;
uniform float uAtlasScaleH; uniform float uAtlasScaleH;
uniform float uBase; uniform float uBase;
uniform float uLevelScale; uniform float uLevelScale;
uniform float uLevelOffsetY; // extra height above icon, in halfIconSize units
out vec2 vUV; out vec2 vUV;
flat out float vAlive; flat out float vAlive;
@@ -37,6 +39,9 @@ void main() {
float iconScale; float iconScale;
if (uZoom <= uDotsThreshold) { if (uZoom <= uDotsThreshold) {
iconScale = 0.0; // hidden in dots mode iconScale = 0.0; // hidden in dots mode
} else if (uZoom >= uIconGrowZoom) {
// World-anchored: grow with the map past this zoom, matching the icons.
iconScale = uZoom / uIconGrowZoom;
} else { } else {
iconScale = min(1.0, uZoom / uScaleFactor); iconScale = min(1.0, uZoom / uScaleFactor);
} }
@@ -78,7 +83,9 @@ void main() {
// Position above icon center // Position above icon center
vec2 center = vec2(worldX + 0.5, worldY + 0.5); vec2 center = vec2(worldX + 0.5, worldY + 0.5);
float baselineY = -uBase * 0.5; float baselineY = -uBase * 0.5;
float yOff = -halfIconSize - levelScale * uBase * 0.6; // above icon top edge // above icon top edge; uLevelOffsetY raises (or lowers) it proportionally
float yOff =
-halfIconSize * (1.0 + uLevelOffsetY) - levelScale * uBase * 0.6;
vec2 glyphOrigin = vec2( vec2 glyphOrigin = vec2(
cursorX + m0.y, // + xoffset cursorX + m0.y, // + xoffset