//
// Fragment shader for doing emboss effect
//
// Author: Jeff Brown
//
//


#version 330

#include "alpha.h"

uniform sampler2DRect inputTex;
uniform sampler2DRect maskTex;
uniform float lightX;
uniform float lightY;
uniform float uBlendValue=1.0;

in vec2 fsTexture;
in vec2 fsMaskTexture;
in vec2 fsTextureSize;
out vec4 outColor;

// Using a sobel filter to create a normal map and then applying simple lighting.

// This makes the darker areas less bumpy but I like it
#define USE_LINEAR_FOR_BUMPMAP

//#define SHOW_NORMAL_MAP
//#define SHOW_ALBEDO

struct C_Sample
{
    vec3 vAlbedo;
    vec3 vNormal;
};

C_Sample SampleMaterial(const in vec2 vUV,  const in vec2 vTextureSize, const in float fNormalScale)
{
    C_Sample result;
    
    vec2 vInvTextureSize = vec2(1.0) / vTextureSize;
    
    vec4 cSampleNegXNegY = texture(inputTex, (vUV + (vec2(-1.0, -1.0)) * vInvTextureSize.xy)*fsTextureSize);
    vec4 cSampleZerXNegY = texture(inputTex, (vUV + (vec2( 0.0, -1.0)) * vInvTextureSize.xy)*fsTextureSize);
    vec4 cSamplePosXNegY = texture(inputTex, (vUV + (vec2( 1.0, -1.0)) * vInvTextureSize.xy)*fsTextureSize);
#ifdef PRE_MULT
    divideAlpha(cSampleNegXNegY);
    divideAlpha(cSampleZerXNegY);
    divideAlpha(cSamplePosXNegY);
#endif

    vec4 cSampleNegXZerY = texture(inputTex, (vUV + (vec2(-1.0, 0.0)) * vInvTextureSize.xy)*fsTextureSize);
    vec4 cSampleZerXZerY = texture(inputTex, (vUV + (vec2( 0.0, 0.0)) * vInvTextureSize.xy)*fsTextureSize);
    vec4 cSamplePosXZerY = texture(inputTex, (vUV + (vec2( 1.0, 0.0)) * vInvTextureSize.xy)*fsTextureSize);
#ifdef PRE_MULT
    divideAlpha(cSampleNegXZerY);
    divideAlpha(cSampleZerXZerY);
    divideAlpha(cSamplePosXZerY);
#endif

    vec4 cSampleNegXPosY = texture(inputTex, (vUV + (vec2(-1.0,  1.0)) * vInvTextureSize.xy)*fsTextureSize);
    vec4 cSampleZerXPosY = texture(inputTex, (vUV + (vec2( 0.0,  1.0)) * vInvTextureSize.xy)*fsTextureSize);
    vec4 cSamplePosXPosY = texture(inputTex, (vUV + (vec2( 1.0,  1.0)) * vInvTextureSize.xy)*fsTextureSize);
#ifdef PRE_MULT
    divideAlpha(cSampleNegXPosY);
    divideAlpha(cSampleZerXPosY);
    divideAlpha(cSamplePosXPosY);
#endif

    // convert to linear
    vec3 cLSampleNegXNegY = cSampleNegXNegY.rgb * cSampleNegXNegY.rgb;
    vec3 cLSampleZerXNegY = cSampleZerXNegY.rgb * cSampleZerXNegY.rgb;
    vec3 cLSamplePosXNegY = cSamplePosXNegY.rgb * cSamplePosXNegY.rgb;

    vec3 cLSampleNegXZerY = cSampleNegXZerY.rgb * cSampleNegXZerY.rgb;
    vec3 cLSampleZerXZerY = cSampleZerXZerY.rgb * cSampleZerXZerY.rgb;
    vec3 cLSamplePosXZerY = cSamplePosXZerY.rgb * cSamplePosXZerY.rgb;

    vec3 cLSampleNegXPosY = cSampleNegXPosY.rgb * cSampleNegXPosY.rgb;
    vec3 cLSampleZerXPosY = cSampleZerXPosY.rgb * cSampleZerXPosY.rgb;
    vec3 cLSamplePosXPosY = cSamplePosXPosY.rgb * cSamplePosXPosY.rgb;

    // Average samples to get albdeo colour
    result.vAlbedo = ( cLSampleNegXNegY + cLSampleZerXNegY + cLSamplePosXNegY
                      + cLSampleNegXZerY + cLSampleZerXZerY + cLSamplePosXZerY
                      + cLSampleNegXPosY + cLSampleZerXPosY + cLSamplePosXPosY ) / 9.0;
    
    vec3 vScale = vec3(0.3333);
    
#ifdef USE_LINEAR_FOR_BUMPMAP
    
    float fSampleNegXNegY = dot(cLSampleNegXNegY, vScale);
    float fSampleZerXNegY = dot(cLSampleZerXNegY, vScale);
    float fSamplePosXNegY = dot(cLSamplePosXNegY, vScale);
    
    float fSampleNegXZerY = dot(cLSampleNegXZerY, vScale);
    float fSamplePosXZerY = dot(cLSamplePosXZerY, vScale);
    
    float fSampleNegXPosY = dot(cLSampleNegXPosY, vScale);
    float fSampleZerXPosY = dot(cLSampleZerXPosY, vScale);
    float fSamplePosXPosY = dot(cLSamplePosXPosY, vScale);
    
#else
    
    float fSampleNegXNegY = dot(cSampleNegXNegY, vScale);
    float fSampleZerXNegY = dot(cSampleZerXNegY, vScale);
    float fSamplePosXNegY = dot(cSamplePosXNegY, vScale);
    
    float fSampleNegXZerY = dot(cSampleNegXZerY, vScale);
    float fSamplePosXZerY = dot(cSamplePosXZerY, vScale);
    
    float fSampleNegXPosY = dot(cSampleNegXPosY, vScale);
    float fSampleZerXPosY = dot(cSampleZerXPosY, vScale);
    float fSamplePosXPosY = dot(cSamplePosXPosY, vScale);
    
#endif
    
    // Sobel operator - http://en.wikipedia.org/wiki/Sobel_operator
    
    vec2 vEdge;
    vEdge.x = (fSampleNegXNegY - fSamplePosXNegY) * 0.25
    + (fSampleNegXZerY - fSamplePosXZerY) * 0.5
    + (fSampleNegXPosY - fSamplePosXPosY) * 0.25;
    
    vEdge.y = (fSampleNegXNegY - fSampleNegXPosY) * 0.25
    + (fSampleZerXNegY - fSampleZerXPosY) * 0.5
    + (fSamplePosXNegY - fSamplePosXPosY) * 0.25;
    
    result.vNormal = normalize(vec3(vEdge * fNormalScale, 1.0));
    
    return result;
}

void main()
{
    vec2 vUV = fsTexture.xy / fsTextureSize.xy;
    
    C_Sample materialSample;
    
    float fNormalScale = 10.0;
    materialSample = SampleMaterial( vUV, fsTextureSize, fNormalScale );
    
    // Random Lighting...
    
    float fLightHeight = 0.2;
    float fViewHeight = 2.0;
    
    vec3 vSurfacePos = vec3(vUV, 0.0);
    
    vec3 vViewPos = vec3(0.5, 0.5, fViewHeight);
    
    vec3 vLightPos = vec3( vec2(lightX,lightY), fLightHeight);
    
    
    vec3 vDirToView = normalize( vViewPos - vSurfacePos );
    vec3 vDirToLight = normalize( vLightPos - vSurfacePos );
    
    float fNDotL = clamp( dot(materialSample.vNormal, vDirToLight), 0.0, 1.0);
    float fDiffuse = fNDotL;
    
    vec3 vHalf = normalize( vDirToView + vDirToLight );
    float fNDotH = clamp( dot(materialSample.vNormal, vHalf), 0.0, 1.0);
    float fSpec = pow(fNDotH, 10.0) * fNDotL * 0.5;
    
    vec3 vResult = materialSample.vAlbedo * fDiffuse + fSpec;
    
    vResult = sqrt(vResult);
    
#ifdef SHOW_NORMAL_MAP
    vResult = materialSample.vNormal * 0.5 + 0.5;
#endif
    
#ifdef SHOW_ALBEDO
    vResult = sqrt(materialSample.vAlbedo);
#endif
    
    vec4 texel=texture(inputTex,fsTexture);
#ifdef PRE_MULT
    divideAlpha(texel);
#endif
    float blendValue=uBlendValue;
#ifdef USE_MASK
    blendValue*=texture(maskTex,fsMaskTexture).a;
#endif
    outColor = mix(texel,vec4(vResult,texel.a),blendValue);
#ifdef PRE_MULT
    multiplyAlpha(outColor);
#endif
}

