#version 410 core
// One portal opening. The through-view was rendered from the camera standing
// behind the linked opening with this frame's projection, so sampling it at
// this fragment's own screen position lines the two images up exactly.
//
// Two passes share this shader: the opening itself (uGlowPass 0, an opaque hole
// in the wall) and the halo lying on the wall around it (uGlowPass 1, blended).
in vec2 vUV;
in vec4 vClip;
out vec4 FragColor;
uniform sampler2D uView;
uniform vec3  uTint;
uniform float uHasView;   // 0 while the opening has nothing to look out of
uniform float uGlowPass;
uniform float uTime;
void main() {
    float r = length(vUV);
    if (uGlowPass > 0.5) {
        // Light spilling onto the wall: brightest at the lip, gone by the edge.
        float a = (1.0 - smoothstep(1.0, 1.42, r)) * smoothstep(0.90, 1.01, r);
        float flicker = 0.88 + 0.12 * sin(uTime * 2.3 + atan(vUV.y, vUV.x) * 3.0);
        FragColor = vec4(uTint * 1.7 * flicker, a * 0.75);
        return;
    }
    if (r > 1.0) discard;
    vec2 s = (vClip.xy / vClip.w) * 0.5 + 0.5;
    vec3 through = texture(uView, clamp(s, vec2(0.0005), vec2(0.9995))).rgb;
    // Unlinked: a slow boil in the opening's own colour instead of a view.
    float swirl = 0.5 + 0.5 * sin(r * 11.0 - uTime * 2.6 + atan(vUV.y, vUV.x) * 2.0);
    vec3 fill = mix(uTint * (0.14 + 0.46 * swirl), through, uHasView);
    // The ring of light: a wide wash of colour that goes white-hot at the lip.
    float wash = smoothstep(0.80, 1.0, r);
    float lip  = smoothstep(0.945, 1.0, r);
    vec3 col = mix(fill, uTint * 1.30, wash * 0.85);
    col = mix(col, mix(uTint, vec3(1.0), 0.6) * 1.7, lip);
    col += uTint * wash * 0.22;
    FragColor = vec4(col, 1.0);
}
