text: import { addLightLocations, uniformLights } from './light';
  import { PI } from '.';
  
  export const uniformPBR = `
  uniform vec4 color;
  uniform float metal;
  uniform float rough;
  uniform float ao;
  `;
  
  export const funcPBR = `
  ${PI}
  ${uniformLights}
  ${uniformPBR}
  
  float DistributionGGX(vec3 N, vec3 H, float roughness) {
    float a      = roughness * roughness;
    float a2     = a * a;
    float NdotH  = max(dot(N, H), 0.0);
    float NdotH2 = NdotH * NdotH;
    float num   = a2;
    float denom = (NdotH2 * (a2 - 1.0) + 1.0);
    denom = PI * 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 N, vec3 V, vec3 L, float roughness) {
    float NdotV = max(dot(N, V), 0.0);
    float NdotL = max(dot(N, L), 0.0);
    float ggx2  = GeometrySchlickGGX(NdotV, roughness);
    float ggx1  = GeometrySchlickGGX(NdotL, roughness);
    return ggx1 * ggx2;
  }
  
  vec3 fresnelSchlick(float cosTheta, vec3 F0) {
    return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
  }
  
  vec3 funcPBR(vec3 position, vec3 normale, vec3 posEye) {		
    vec3 N = normalize(normale);
    vec3 V = normalize(posEye - position);
  
    vec3 F0 = vec3(0.04); 
    F0 = mix(F0, color.xyz, metal);
  
    // reflectance equation
    vec3 Lo = vec3(0.0);
    
    for (int i = 0; i < MAX_LIGHTS; ++i) {
      if (i < numLights) {
        // calculate per-light radiance
        vec3 L = normalize(lights[i].position - position);
        vec3 H = normalize(V + L);
        float distance    = length(lights[i].position - position);
        float attenuation = lights[i].strength / (distance * distance);
        vec3 radiance     = lights[i].ambiant * attenuation;        
        
        // cook-torrance brdf
        float NDF = DistributionGGX(N, H, rough);        
        float G   = GeometrySmith(N, V, L, rough);      
        vec3 F    = fresnelSchlick(max(dot(H, V), 0.0), F0);       
        
        vec3 kS = F;
        vec3 kD = vec3(1.0) - kS;
        kD *= 1.0 - metal;	  
        
        vec3 numerator    = NDF * G * F;
        float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0);
        vec3 specular     = numerator / max(denominator, 0.001);  
            
        // add to outgoing radiance Lo
        float NdotL = max(dot(N, L), 0.0);                
        Lo += (kD * color.xyz / PI + specular) * radiance * NdotL; 
      }
    }
  
    vec3 ambient = vec3(0.03) * color.xyz * ao;
    vec3 finalColor = ambient + Lo;
    finalColor = finalColor / (finalColor + vec3(1.0));
    finalColor = pow(finalColor, vec3(1.0 / 2.2));  
    return finalColor;
  }
  `;
  
  export const locationsPBR = addLightLocations().concat(['color', 'metal', 'rough', 'ao']);
  