diff --git a/src/client/render/gl/RenderSettings.ts b/src/client/render/gl/RenderSettings.ts index 3adfb9096..09ac2964e 100644 --- a/src/client/render/gl/RenderSettings.ts +++ b/src/client/render/gl/RenderSettings.ts @@ -194,6 +194,9 @@ export interface RenderSettings { outlineB: number; outlineUsePlayerColor: boolean; fillUsePlayerColor: boolean; + /** Name fill grayscale shade by player type (0 = black). Human is always 0. */ + nameShadeNation: number; + nameShadeBot: number; emojiRowOffset: number; statusRowOffset: number; }; diff --git a/src/client/render/gl/passes/name-pass/index.ts b/src/client/render/gl/passes/name-pass/index.ts index fd5210e28..f8ec4844b 100644 --- a/src/client/render/gl/passes/name-pass/index.ts +++ b/src/client/render/gl/passes/name-pass/index.ts @@ -499,10 +499,18 @@ export class NamePass { d[off + 10] = color[2]; d[off + 11] = 1.0; - // Column 3: nameLen, troopLen, isHuman, nameHalfWidth + // Column 3: nameLen, troopLen, nameShade, nameHalfWidth + // Name fill darkens by type: human black, nation a bit gray, bot greyer. + const ns = this.settings.name; + let nameShade = 0.0; + if (slot.static.playerType === PlayerTypeEnum.Nation) { + nameShade = ns.nameShadeNation; + } else if (slot.static.playerType === PlayerTypeEnum.Bot) { + nameShade = ns.nameShadeBot; + } d[off + 12] = slot.nameLen; d[off + 13] = slot.troopLen; - d[off + 14] = slot.static.playerType === PlayerTypeEnum.Human ? 1.0 : 0.0; + d[off + 14] = nameShade; d[off + 15] = slot.nameHalfWidth; // Column 4: flagLayerIdx, emojiAtlasIdx, [free], [free] diff --git a/src/client/render/gl/render-settings.json b/src/client/render/gl/render-settings.json index d9e85f4d6..392b44346 100644 --- a/src/client/render/gl/render-settings.json +++ b/src/client/render/gl/render-settings.json @@ -202,6 +202,8 @@ "outlineB": 0.0, "outlineUsePlayerColor": true, "fillUsePlayerColor": false, + "nameShadeNation": 0.3, + "nameShadeBot": 0.4, "emojiRowOffset": 1.4, "statusRowOffset": 1.4 }, diff --git a/src/client/render/gl/shaders/name/name.frag.glsl b/src/client/render/gl/shaders/name/name.frag.glsl index b2524f8b5..2b9727482 100644 --- a/src/client/render/gl/shaders/name/name.frag.glsl +++ b/src/client/render/gl/shaders/name/name.frag.glsl @@ -11,7 +11,7 @@ uniform float uFillUsePlayerColor; in vec2 vUV; in vec4 vPlayerColor; // player territory color (rgb) + alpha -in float vIsHuman; // 1.0 = human, 0.0 = bot/nation +in float vNameShade; // name fill grayscale shade (0.0 = black) out vec4 fragColor; float median(float r, float g, float b) { @@ -22,15 +22,14 @@ void main() { // Degenerate fragment — skip if (vPlayerColor.a <= 0.0) discard; - // Stagger fill/border curves so they never share the same gray. - // t² for border (stays dark longer, snaps white late) and √t for fill (inverse). - // At midpoint t=0.5: border=0.25 (dark), fill=0.71 (light) — always distinct. + // Border darkens with night: t² stays dark longer, snaps toward the + // outline color late in the day cycle. float t = 1.0 - uNightAmbient; float borderT = t * t; - float fillT = sqrt(t); - // Compute fill color: player color, or cycle-aware white↔black (inverse of border) - vec3 defaultFill = mix(uOutlineColor, vec3(0.0), fillT); + // Compute fill color: player color, or per-type grayscale shade + // (black for human, grayer for nation/bot). Applies in day and night. + vec3 defaultFill = vec3(vNameShade); vec3 fillColor = mix(defaultFill, vPlayerColor.rgb, uFillUsePlayerColor); vec3 msd = texture(uAtlas, vUV).rgb; diff --git a/src/client/render/gl/shaders/name/name.vert.glsl b/src/client/render/gl/shaders/name/name.vert.glsl index eb0a9ee44..eeb38b35b 100644 --- a/src/client/render/gl/shaders/name/name.vert.glsl +++ b/src/client/render/gl/shaders/name/name.vert.glsl @@ -31,7 +31,7 @@ uniform float uHighlightOwnerID; out vec2 vUV; out vec4 vPlayerColor; // player territory color (rgb) + alpha -out float vIsHuman; // 1.0 for human, 0.0 for bot/nation +out float vNameShade; // name fill grayscale shade (0.0 = black) void main() { // 1. Decode instance ID → playerIdx, lineIdx, charPos @@ -45,7 +45,7 @@ void main() { vec4 pd0 = texelFetch(uPlayerData, ivec2(0, playerIdx), 0); // srcX, srcY, srcScale, startTime vec4 pd1 = texelFetch(uPlayerData, ivec2(1, playerIdx), 0); // tgtX, tgtY, tgtScale, alive vec4 pd2 = texelFetch(uPlayerData, ivec2(2, playerIdx), 0); // r, g, b, a - vec4 pd3 = texelFetch(uPlayerData, ivec2(3, playerIdx), 0); // nameLen, troopLen, isHuman, 0 + vec4 pd3 = texelFetch(uPlayerData, ivec2(3, playerIdx), 0); // nameLen, troopLen, nameShade, nameHalfWidth vec4 pd4 = texelFetch(uPlayerData, ivec2(4, playerIdx), 0); // flagLayerIdx, emojiAtlasIdx, smallID, 0 float smallID = pd4.z; @@ -54,7 +54,7 @@ void main() { gl_Position = vec4(0.0); vUV = vec2(0.0); vPlayerColor = vec4(0.0); - vIsHuman = 0.0; + vNameShade = 0.0; return; } @@ -64,7 +64,7 @@ void main() { gl_Position = vec4(0.0); vUV = vec2(0.0); vPlayerColor = vec4(0.0); - vIsHuman = 0.0; + vNameShade = 0.0; return; } @@ -75,7 +75,7 @@ void main() { gl_Position = vec4(0.0); vUV = vec2(0.0); vPlayerColor = vec4(0.0); - vIsHuman = 0.0; + vNameShade = 0.0; return; } @@ -109,7 +109,7 @@ void main() { gl_Position = vec4(0.0); vUV = vec2(0.0); vPlayerColor = vec4(0.0); - vIsHuman = 0.0; + vNameShade = 0.0; return; } @@ -133,7 +133,7 @@ void main() { gl_Position = vec4(0.0); vUV = vec2(0.0); vPlayerColor = vec4(0.0); - vIsHuman = 0.0; + vNameShade = 0.0; return; } @@ -158,5 +158,5 @@ void main() { // 10. UV interpolation across quad vUV = vec2(mix(u0, u1, aPos.x), mix(v0, v1, aPos.y)); vPlayerColor = pd2; // player territory color (rgb) + alpha - vIsHuman = pd3.z; // 1.0 = human, 0.0 = bot/nation + vNameShade = pd3.z; // name fill grayscale shade (0.0 = black) }