/***********************************************/
/*           Copyright (c) 2025 Belmu          */
/*             All Rights Reserved             */
/***********************************************/

#define STAR_SHAPED_BOKEH 0

vec2 cameraBokeh() {
    float currentBlade = randF() * APERTURE_BLADES;

    vec2 rotationVector = sincos(floor(currentBlade) * bladeSectorAngle);
    mat2 rotation       = mat2(rotationVector.y, -rotationVector.x, rotationVector.xy);

    #if STAR_SHAPED_BOKEH == 0
        const float halfSector = bladeSectorAngle * 0.5;
    #else
        const float halfSector = bladeSectorAngle;
    #endif

    vec2 bokeh = rotation * vec2(cos(halfSector), sin(halfSector) * (fract(currentBlade) * 2.0 - 1.0));

    float radial = 1.0 - pow(1.0 - sqrt(randF()), 1.1);

    return bokeh * radial;
}

void generateThinLensCameraRay(vec2 coords, vec3 viewPosition, inout vec3 position, inout vec3 direction) {
    vec2 focalLength    = sensorSize  * diagonal2(gbufferProjection);
    vec2 fovCorrection  = sensorSize  / focalLength;
    vec2 apertureRadius = focalLength / (F_STOPS * 2.0);

    vec2 antiAliasingOffset = rand2F() * texelSize;
    vec3 sensorRayOrigin    = vec3(((coords * 2.0 - 1.0) + antiAliasingOffset) * fovCorrection, -1.0);

    #if MANUAL_CAMERA == 0
        vec3 focusDirection = mat3(gbufferModelViewInverse) * normalize(vec3(antiAliasingOffset * fovCorrection, -1.0));
        float focusDistance = getAutoFocusDistance(position, focusDirection);
    #else
        float focusDistance = FOCAL;
    #endif

    vec3 aperturePoint = vec3(cameraBokeh() * apertureRadius, 0.0);

    position  = viewToWorld(aperturePoint);
    direction = normalize(mat3(gbufferModelViewInverse) * normalize((sensorRayOrigin * focusDistance) - aperturePoint));
}
