plain text 44 lines
shader_type spatial;
render_mode blend_mix, unshaded, cull_disabled, depth_draw_never, shadows_disabled;
// The fog of war: a dark sheet laid just over the playfield that dims everywhere the player's
// team has no vision, with a clear hole punched around each of the team's sight sources (its
// heroes, creeps, and structures). It is a presentation tint only — enemy units in fog are
// hidden by the renderer and never sent over the wire (Vision / NetProtocol), so this draws no
// units, only the darkened ground. World-space and unshaded so the tint reads flat and even
// across the arena regardless of where the plane sits; depth-tested (it does not write depth) so
// the 3D bodies standing in a lit circle rise in front of it rather than being dimmed.
// The reveal circles, packed (center.x, center.z, radius, _) in world units — one per sight
// source the driver feeds each frame, up to MAX_SOURCES. Only the first `source_count` are read,
// so the unused tail never reveals.
const int MAX_SOURCES = 64;
uniform vec4 fog_sources[MAX_SOURCES];
uniform int source_count = 0;
// The fog tint and how opaque it sits over unseen ground, plus the soft inner band: the sheet
// fades from clear at a circle's edge to full fog `fog_edge` units outside it, so the reveal has
// a feathered rim rather than a hard ring.
uniform vec3 fog_color : source_color = vec3(0.02, 0.03, 0.06);
uniform float fog_alpha : hint_range(0.0, 1.0) = 0.82;
uniform float fog_edge = 220.0;
varying vec3 world_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
void fragment() {
// The signed distance to the nearest reveal edge: negative inside a circle, positive in fog.
float nearest = 1.0e9;
for (int i = 0; i < source_count; i++) {
nearest = min(nearest, distance(world_pos.xz, fog_sources[i].xy) - fog_sources[i].z);
}
// No sources yet (pre-match, before a hero spawns) means no vision data — leave the field
// clear rather than blacking it out, so the menu backdrop and the first frame read normally.
float alpha = source_count == 0 ? 0.0 : fog_alpha * smoothstep(0.0, fog_edge, nearest);
ALBEDO = fog_color;
ALPHA = alpha;
}