From ac6d8d739a81cea3b5dbf3b7a5ecd060912c7f5e Mon Sep 17 00:00:00 2001 From: evanpelle Date: Fri, 12 Jun 2026 15:41:03 -0700 Subject: [PATCH] Make attack ring size tunable and increase it to 30px The transport-target ring size was hardcoded as RING_SCREEN_PX in attack-ring.vert.glsl. Promote it to a uRingScreenPx uniform fed from a new fx.attackRingScreenPx entry in render-settings.json, with an "Attack Ring Size (px)" slider in the debug GUI's FX folder. Also bump the size from 20 to 30 screen px so the ring is easier to spot. The inner/outer ring fractions (0.5/0.8 of the quad) stay shader constants. --- src/client/render/gl/RenderSettings.ts | 1 + src/client/render/gl/debug/Layout.ts | 9 +++++++++ src/client/render/gl/passes/fx-pass/FxAttackRingPass.ts | 3 +++ src/client/render/gl/render-settings.json | 1 + src/client/render/gl/shaders/fx/attack-ring.vert.glsl | 8 ++++---- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/client/render/gl/RenderSettings.ts b/src/client/render/gl/RenderSettings.ts index 180317948..cca1cd316 100644 --- a/src/client/render/gl/RenderSettings.ts +++ b/src/client/render/gl/RenderSettings.ts @@ -257,6 +257,7 @@ export interface RenderSettings { }; fx: { shockwaveRingWidth: number; + attackRingScreenPx: number; // screen px — attack ring quad half-size (visible outer ring = 0.8×) nukeShockwaveDurationMs: number; nukeShockwaveRadiusFactor: number; samShockwaveDurationMs: number; diff --git a/src/client/render/gl/debug/Layout.ts b/src/client/render/gl/debug/Layout.ts index e885f11fa..242b935f9 100644 --- a/src/client/render/gl/debug/Layout.ts +++ b/src/client/render/gl/debug/Layout.ts @@ -332,6 +332,15 @@ export function buildTree(s: RenderSettings, d: RenderSettings): DebugNode[] { folder("FX", [ slider(s.fx, "shockwaveRingWidth", d.fx, 0.01, 0.2, 0.005), + slider( + s.fx, + "attackRingScreenPx", + d.fx, + 5, + 60, + 1, + "Attack Ring Size (px)", + ), slider( s.fx, "nukeShockwaveDurationMs", diff --git a/src/client/render/gl/passes/fx-pass/FxAttackRingPass.ts b/src/client/render/gl/passes/fx-pass/FxAttackRingPass.ts index c522e2880..4c0932bd7 100644 --- a/src/client/render/gl/passes/fx-pass/FxAttackRingPass.ts +++ b/src/client/render/gl/passes/fx-pass/FxAttackRingPass.ts @@ -50,6 +50,7 @@ export class FxAttackRingPass { private uTilesPerPx: WebGLUniformLocation; private uTime: WebGLUniformLocation; private uRingWidth: WebGLUniformLocation; + private uRingScreenPx: WebGLUniformLocation; private vao: WebGLVertexArrayObject; private instanceBuf: DynamicInstanceBuffer; private ringCount = 0; @@ -65,6 +66,7 @@ export class FxAttackRingPass { this.uTilesPerPx = gl.getUniformLocation(this.program, "uTilesPerPx")!; this.uTime = gl.getUniformLocation(this.program, "uTime")!; this.uRingWidth = gl.getUniformLocation(this.program, "uRingWidth")!; + this.uRingScreenPx = gl.getUniformLocation(this.program, "uRingScreenPx")!; const glBuf = gl.createBuffer()!; this.instanceBuf = new DynamicInstanceBuffer( @@ -182,6 +184,7 @@ export class FxAttackRingPass { gl.uniform1f(this.uTilesPerPx, 1 / zoom); gl.uniform1f(this.uTime, performance.now() / 1000); gl.uniform1f(this.uRingWidth, this.settings.fx.shockwaveRingWidth); + gl.uniform1f(this.uRingScreenPx, this.settings.fx.attackRingScreenPx); gl.bindBuffer(gl.ARRAY_BUFFER, this.instanceBuf.buffer); gl.bufferSubData( gl.ARRAY_BUFFER, diff --git a/src/client/render/gl/render-settings.json b/src/client/render/gl/render-settings.json index a9f5ccc87..21a6c90be 100644 --- a/src/client/render/gl/render-settings.json +++ b/src/client/render/gl/render-settings.json @@ -216,6 +216,7 @@ }, "fx": { "shockwaveRingWidth": 0.04, + "attackRingScreenPx": 30, "nukeShockwaveDurationMs": 1500, "nukeShockwaveRadiusFactor": 1.5, "samShockwaveDurationMs": 800, diff --git a/src/client/render/gl/shaders/fx/attack-ring.vert.glsl b/src/client/render/gl/shaders/fx/attack-ring.vert.glsl index 3c66df397..139b097a2 100644 --- a/src/client/render/gl/shaders/fx/attack-ring.vert.glsl +++ b/src/client/render/gl/shaders/fx/attack-ring.vert.glsl @@ -6,18 +6,18 @@ layout(location = 1) in vec3 aInstData; // x, y, alpha uniform mat3 uCamera; uniform float uTilesPerPx; +// Quad half-size in screen px; visible outer ring = 0.8× (frag OUTER_R), +// the rest is headroom for SDF AA. +uniform float uRingScreenPx; out vec2 vLocalPos; flat out float vAlpha; -// Upstream outer ring = 16 screen-px; quad needs headroom for SDF AA. -const float RING_SCREEN_PX = 20.0; - void main() { vec2 center = vec2(aInstData.x + 0.5, aInstData.y + 0.5); vAlpha = aInstData.z; - float worldRadius = RING_SCREEN_PX * uTilesPerPx; + float worldRadius = uRingScreenPx * uTilesPerPx; vec2 worldPos = center + (aPos - 0.5) * worldRadius * 2.0; vec3 clip = uCamera * vec3(worldPos, 1.0);