/*
  End Void Eye — Black Hole
  Interstellar-style black hole with a flat accretion disk warped by
  gravitational lensing, photon ring, and hard event horizon.
*/

#ifdef END

vec3 DrawVoidEye(vec3 viewPos, vec3 shadowDir) {
    vec3 nViewPos = normalize(viewPos);

    // Angle from the shadow light direction
    float VoL = dot(nViewPos, shadowDir);
    float angle = acos(clamp(VoL, -1.0, 1.0));

    // Early out
    if (angle > 0.55) return vec3(0.0);

    // 2D projection centered on shadow direction
    vec3 tangent = normalize(cross(shadowDir, upVec));
    vec3 bitangent = cross(shadowDir, tangent);

    float px = dot(nViewPos, tangent);     // horizontal
    float py = dot(nViewPos, bitangent);   // vertical
    float dist = length(vec2(px, py));
    float theta = atan(py, px);

    // === Event Horizon — hard dark sphere ===
    float eventRadius = 0.030;
    float horizon = smoothstep(eventRadius + 0.003, eventRadius - 0.001, dist);

    // === Gravitational lensing warp ===
    // Near event horizon, compress vertical coordinate so disk wraps around
    float warpStrength = smoothstep(0.18, 0.035, dist) * 0.9;
    float warpedPy = py * (1.0 - warpStrength);

    // === Accretion Disk — flat disk in equatorial plane ===
    // Disk thickness increases with distance (perspective)
    float diskThickness = 0.004 + dist * 0.035;
    float diskProfile = exp(-warpedPy * warpedPy / (2.0 * diskThickness * diskThickness));

    // Radial extent of the disk
    float diskInner = eventRadius + 0.008;
    float diskOuter = 0.20;
    float radialMask = smoothstep(diskInner, diskInner + 0.008, dist) *
                       smoothstep(diskOuter + 0.04, diskOuter, dist);

    float disk = diskProfile * radialMask;

    // === Disk structure — rotation and spiral arms ===
    float rotSpeed = frametime * END_VOID_EYE_SPEED;
    float logDist = log(max(dist, 0.001));

    // Spiral arms for non-uniform brightness
    float spiral1 = sin(theta * 2.0 + rotSpeed + logDist * 6.0) * 0.4 + 0.6;
    float spiral2 = sin(theta * 5.0 - rotSpeed * 0.7 + logDist * 10.0) * 0.2 + 0.8;
    disk *= spiral1 * spiral2;

    // Brightness falloff — hotter closer to center
    float heatGradient = smoothstep(diskOuter, diskInner, dist);
    disk *= 0.4 + 1.6 * heatGradient;

    // === Disk color — temperature-based, purple palette ===
    vec3 hotColor  = vec3(1.0, 0.85, 1.0);   // White-lavender (inner, hottest)
    vec3 warmColor = vec3(0.8, 0.4, 1.0);     // Bright purple
    vec3 coolColor = vec3(0.35, 0.15, 0.7);   // Deep purple (outer, coolest)

    vec3 diskColor = mix(coolColor, warmColor, heatGradient);
    diskColor = mix(diskColor, hotColor, heatGradient * heatGradient);

    // === Photon Ring — thin bright ring at photon sphere ===
    float photonRadius = eventRadius + 0.005;
    float photonDist = abs(dist - photonRadius);
    float photonRing = exp(-photonDist * photonDist * 80000.0);
    vec3 photonColor = vec3(0.85, 0.7, 1.0) * 2.5;

    // === Secondary lensing ring — Einstein ring ===
    // Faint secondary image of disk right at event horizon edge
    float einsteinDist = abs(dist - eventRadius - 0.002);
    float einsteinRing = exp(-einsteinDist * einsteinDist * 120000.0) * 0.5;
    vec3 einsteinColor = vec3(0.7, 0.5, 1.0) * 2.0;

    // === Compose ===
    vec3 result = diskColor * disk * 2.5
               + photonColor * photonRing
               + einsteinColor * einsteinRing;

    // Black out the event horizon
    result *= 1.0 - horizon;

    // Subtle pulsation
    result *= 0.9 + 0.1 * sin(frametime * 0.5);

    // Edge fade
    float edgeFade = smoothstep(0.5, 0.15, angle);

    return result * edgeFade * END_VOID_EYE_BRIGHTNESS * 0.10;
}

#endif
