/*
 * Copyright (C) 2013 Stellar Jockeys.
 * All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Stellar Jockeys and its suppliers, if any.  The intellectual and technical
 * concepts contained herein are proprietary to Stellar Jockeys and its suppliers.
 * Dissemination of this information or reproduction of this material is
 * strictly forbidden unless prior written permission is obtained from
 * Stellar Jockeys.
 *
 * @file fragmaterial.glsl
 * @author Harry Hsiao
 * @date 08/14/2013
 */
#ifndef FRAGMATERIAL_GLSL
#define FRAGMATERIAL_GLSL

// Requires constants.glsl
#ifndef CONSTANTS_GLSL
#error constants.glsl should also be included
#endif

/**
 * @brief Calcuates the specular contribution for a light.
 *
 * Specular contribution is modeled using three components:
 *   1. Blinn-Phong specular hightlight
 *   2. Linear term based on the specular exponent
 *   3. Schlick's approximation for Fresnel reflection
 *
 * @param normal The surface normal. Assumed to be normalized.
 * @param halfVector The halfway vector bewteen the view and light direcitons.
 *                   Assumed to be normalized.
 * @param specExp The specular exponent.
 * @param r0 Reflection coefficient for Schlick's approximation of Fresnel term.
 *           @see http://en.wikipedia.org/wiki/Schlick%27s_approximation
 */
float Specularity(in vec3 normal, in vec3 halfVector, in float specExp, in float r0)
{
    float blinn = pow(max(dot(normal, halfVector), 0.0), specExp);
    float specEnergy = specExp * SPEC_ENERGY_FACTOR + SPEC_ENERGY_CONSTANT;
    float base = 1.0 - halfVector.z;
    float fresnel = base * base;
    fresnel *= fresnel * base;
    fresnel = fresnel * (1.0 - r0) + r0;

    return (blinn * specEnergy) * fresnel;
}

vec4 PackMaterialProperties(in float fresnel, in float roughness)
{
    return vec4(fresnel, roughness, 1.0, 1.0);
}

float UnpackFresnel(in vec4 texel)
{
    return texel.r;
}

float UnpackSpecularExponent(in vec4 texel)
{
    return pow(2.0, (texel.g * 10.0 + 1.0));
}

#endif // FRAGMATERIAL_GLSL
