// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

uniform FragInfo {
  float exposure;
  vec3 camera_position;
}
frag_info;

uniform sampler2D base_color_texture;
uniform sampler2D normal_texture;
uniform sampler2D occlusion_roughness_metallic_texture;

in vec3 v_position;
in mat3 v_tangent_space;
in vec2 v_texture_coords;

out vec4 frag_color;

#include <impeller/constants.glsl>

const float kPi = 3.14159265358979323846;

const vec3 kLightNormal = normalize(vec3(2.0, 5.0, -5.0));
const vec3 kLightColor = vec3(1.0, 0.8, 0.8) * 3.0;

const vec3 kHighlightNormal = normalize(vec3(-2.0, -3.0, 0.0));
const vec3 kHighlightColor = vec3(1.0, 0.1, 0.0) * 1.5;

const float kGamma = 2.2;

// Convert from sRGB to linear space.
// This can be removed once Impeller supports sRGB texture inputs.
vec3 SampleSRGB(sampler2D tex, vec2 uv) {
  vec3 color = texture(tex, uv).rgb;
  return pow(color, vec3(kGamma));
}

//------------------------------------------------------------------------------
/// Lighting equation.
/// See also: https://learnopengl.com/PBR/Lighting
///

vec3 FresnelSchlick(float cos_theta, vec3 reflectance) {
  return reflectance +
         (1.0 - reflectance) * pow(clamp(1.0 - cos_theta, 0.0, 1.0), 5.0);
}

float DistributionGGX(vec3 normal, vec3 half_vector, float roughness) {
  float a = roughness * roughness;
  float a2 = a * a;
  float NdotH = max(dot(normal, half_vector), 0.0);
  float NdotH2 = NdotH * NdotH;

  float num = a2;
  float denom = (NdotH2 * (a2 - 1.0) + 1.0);
  denom = kPi * denom * denom;

  return num / denom;
}

float GeometrySchlickGGX(float NdotV, float roughness) {
  float r = (roughness + 1.0);
  float k = (r * r) / 8.0;

  float num = NdotV;
  float denom = NdotV * (1.0 - k) + k;

  return num / denom;
}

float GeometrySmith(vec3 normal,
                    vec3 camera_normal,
                    vec3 light_normal,
                    float roughness) {
  float camera_ggx =
      GeometrySchlickGGX(max(dot(normal, camera_normal), 0.0), roughness);
  float light_ggx =
      GeometrySchlickGGX(max(dot(normal, light_normal), 0.0), roughness);
  return camera_ggx * light_ggx;
}

vec3 LightFormula(vec3 light_color,
                  vec3 camera_normal,
                  vec3 light_normal,
                  vec3 albedo,
                  vec3 normal,
                  float metallic,
                  float roughness,
                  vec3 reflectance) {
  vec3 half_vector = normalize(camera_normal + light_normal);

  // Cook-Torrance BRDF.
  float distribution = DistributionGGX(normal, half_vector, roughness);
  float geometry =
      GeometrySmith(normal, camera_normal, light_normal, roughness);
  vec3 fresnel =
      FresnelSchlick(max(dot(half_vector, camera_normal), 0.0), reflectance);

  vec3 kS = fresnel;
  vec3 kD = vec3(1.0) - kS;
  kD *= 1.0 - metallic;

  vec3 numerator = distribution * geometry * fresnel;
  float denominator = 4.0 * max(dot(normal, camera_normal), 0.0) *
                          max(dot(normal, light_normal), 0.0) +
                      0.0001;
  vec3 specular = numerator / denominator;

  float NdotL = max(dot(normal, light_normal), 0.0);
  return (kD * albedo / kPi + specular) * light_color * NdotL;
}

void main() {
  vec3 albedo = SampleSRGB(base_color_texture, v_texture_coords);
  vec3 normal =
      normalize(v_tangent_space *
                (texture(normal_texture, v_texture_coords).rgb * 2.0 - 1.0));
  vec3 orm =
      texture(occlusion_roughness_metallic_texture, v_texture_coords).rgb;
  float occlusion = orm.r;
  float roughness = orm.g;
  float metallic = orm.b;

  vec3 camera_normal = normalize(frag_info.camera_position - v_position);

  vec3 reflectance = mix(vec3(0.04), albedo, metallic);

  vec3 out_radiance =
      LightFormula(kLightColor, camera_normal, kLightNormal, albedo, normal,
                   metallic, roughness, reflectance);
  out_radiance +=
      LightFormula(kHighlightColor, camera_normal, kHighlightNormal, albedo,
                   normal, metallic, roughness, reflectance);

  vec3 ambient = vec3(0.03) * albedo * occlusion;
  vec3 out_color = ambient + out_radiance;

  // Tone mapping.
  out_color = vec3(1.0) - exp(-out_color * frag_info.exposure);

#ifndef IMPELLER_TARGET_METAL
  out_color = pow(out_color, vec3(1.0 / kGamma));
#endif

  frag_color = vec4(out_color, 1.0);
}
