

#include "/lib/ssr/ssr_common.glsl"

#include "/lib/specular.glsl"

vec3 computeReflections(
    float skylight, float roughness, vec3 f0, vec3 albedo, float shading, vec3 normal, vec3 p3, vec3 scene)
{
    vec3 np3 = normalize(p3);
    // roughness = 0;
    // Determine if the material is metallic
    bool isMetal = (f0.y * 255.0) > 229.0;
    f0 = CalculateF0(f0, isMetal, int(f0.y * 255.0), albedo);
    roughness = max(0.0000001, roughness);
    // Compute specular term
    vec3 specular = shading * GGX2(normal, -np3, lightPos, roughness, f0) * pow(skylight, 3.0) * sunLight * SPECULAR_BOOST;
#if SSR_QUALITY == 1
    if (length(f0) == 0)
    {
        return scene + specular;
    }

    float lod = mix(3, 8.0, roughness);

    // Compute view direction
    vec3 tangent = max(normalize(vec3(-normal.y, normal.x, 0.0)), -1.0);
    vec3 bitangent = cross(normal, tangent);
    vec3 viewDir = normalize(vec3(
        dot(-np3, tangent),
        dot(-np3, bitangent),
        dot(-np3, normal)));

    // Compute reflected direction
    vec2 p2 = viewDir.xy * roughness;
    vec2 perp2 = vec2(-p2.y, p2.x) / length(p2);
    float dither = cos(6.2831 * R2_dither(gl_FragCoord.xy));
    vec3 halfway = normalize(vec3(roughness * (0.5 * p2 + 0.6667 * perp2 * dither), max(0.0, 0.1 + viewDir.z)));
    vec3 reflectedDir = reflect(-viewDir, halfway);

    vec3 L = reflectedDir.x * tangent + reflectedDir.y * bitangent + reflectedDir.z * normal;
    float NoL = max(dot(normal, L), 0.0);
    vec3 F = f0 + (1.0 - f0) * pow(clamp(1.0 + dot(-reflectedDir, halfway), 0.0, 1.0), 5.0);
    vec3 rayContrib = F * (NoL / (NoL * (1.0 - roughness * roughness * 0.5) + roughness * roughness * 0.5));

    // Sky and reflection contributions
    vec4 sky = skyFromTexLod(L, colortex6, lod);
    sky.rgb = mix(sky.rgb, vec3(sky.a * sunLight), clamp(sky.a, 0, 1));

    vec3 reflectionColor = mix(scene, sky.rgb, clamp(L.y + 0.25, 0.0, 1.0)) * pow(skylight, 3.0);
    vec3 indirectSpecular = reflectionColor * rayContrib;

    // Compute final output
    vec3 effectiveAlbedo = isMetal ? albedo : vec3(1.0);
    vec3 diffuse = isMetal ? vec3(0.0) : vec3(1.0) - rayContrib;

    //  return vec3(isMetal);
    return (indirectSpecular + specular + diffuse * scene) * effectiveAlbedo;
#else
    return scene + specular;
#endif
}