#version 330 core
precision highp float;

// Endless wireframe corridor: two vertical walls (left & right) drawn as a grid of squares, with the
// camera dollying backwards so the grid streams toward the vanishing point. Only the wire lines are
// opaque (the cell interiors and the space between the walls stay transparent), so the demopart
// alpha-blends this over whatever is below. Purely iTime-driven -> identical under --record.
// Tune the constants below to taste.

uniform vec3  iResolution;
uniform float iTime;
uniform float alpha;

in vec2 fragCoord;
out vec4 fragColor;

const float kHalfWidth  = 1.0;   // walls at x = +/- kHalfWidth (corridor half-width)
const float kHalfHeight = 2.0;   // walls span y in [-kHalfHeight, +kHalfHeight]
const float kCell       = 0.5;   // grid square size (world units) -> the "squares"
const float kLineWidth  = 0.04;  // wireframe line thickness (fraction of a cell)
const float kCamSpeed   = 3.0;   // backing-out speed (world units / second)
const float kFov        = 0.9;   // ~tan(half field-of-view)
const float kFogDensity = 0.05;  // higher = walls fade in nearer (keeps them "endless")
const vec3  kWireColor  = vec3(0.55, 0.75, 1.0); // cool blue wire
const float kVeil       = 0.55;  // dark backdrop so the wire reads over the scene (0 = pure overlay, 1 = opaque)
const vec3  kBackdrop   = vec3(0.01, 0.02, 0.05); // corridor backdrop colour behind the wire

// 1.0 on a grid line, 0.0 in the cell interior (screen-space antialiased so it does not shimmer far off).
float gridLine(vec2 p) {
	vec2 f = fract(p / kCell);
	vec2 d = min(f, 1.0 - f) * kCell; // distance (world units) to the nearest grid line, per axis
	float line = min(d.x, d.y);
	float aa = fwidth(line) + 1e-4;
	float w = kLineWidth * kCell;
	return 1.0 - smoothstep(w - aa, w + aa, line);
}

void main() {
	vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;

	// Camera at the corridor centre, looking down +z, dollying backwards over time.
	vec3 ro = vec3(0.0, 0.0, -kCamSpeed * iTime);
	vec3 rd = normalize(vec3(uv * kFov, 1.0));

	float a = 0.0; // strongest wire coverage for this pixel

	// Intersect the ray with the left wall (x = -kHalfWidth) and the right wall (x = +kHalfWidth).
	for (int s = 0; s < 2; ++s) {
		float wx = (s == 0) ? -kHalfWidth : kHalfWidth;
		if (abs(rd.x) < 1e-4) {
			continue;
		}
		float t = (wx - ro.x) / rd.x;
		if (t <= 0.0) {
			continue; // wall is behind the camera for this pixel
		}
		vec3 p = ro + t * rd;
		if (abs(p.y) > kHalfHeight) {
			continue; // above / below the wall
		}
		float m = gridLine(vec2(p.z, p.y)); // squares across (depth, height)
		float fog = exp(-t * kFogDensity);  // fade with distance -> no visible end
		a = max(a, m * fog);                // keep the nearer / stronger wall for this pixel
	}

	// Dark backdrop veil (dims the busy scene below) with the bright wire on top.
	float wire = clamp(a, 0.0, 1.0);
	vec3 outColor = mix(kBackdrop, kWireColor, wire);
	float outAlpha = max(kVeil, wire) * alpha;
	fragColor = vec4(outColor, outAlpha);
}
