#version 150

struct vertex_fragment
 {
   vec4 Position;
   vec4 TexCoord;
   vec4 Pos;
   vec4 Color;
};


in vertex_fragment IN;
in vec3 fL;
in vec3 fV;
in vec4 ambient2;

struct llum
{
    vec4 pos;
    vec3 dir;
    vec4 int_ambient;
    vec4 int_difusa;
    vec4 int_especular;
    float ang;
};

struct material
{

    vec4 comp_ambient;
    vec4 comp_difusa;
    vec4 comp_especular;
    float coef;
};

uniform llum l;
uniform material matPrimari;
uniform material matSecundari;
uniform float a;
uniform float b;
uniform float c;
uniform vec4 obs;
uniform vec3 vrp;
uniform vec3 dirVec;

uniform sampler1D texturaLut;
uniform sampler2D backface;
uniform sampler3D texturaVolum;
uniform float stepsize;
uniform float umbralOpacitat;
uniform float anchura;
uniform float altura;
uniform float profundidad;
uniform int umbralSaturacio;
uniform int colorMode;
uniform int rcMode;

out vec4 fColor;

const int X_RAY_MODE = 0;
const int LUT_MODE = 1;
const int PHONG_MODE = 2;
const int ONE_STEP_MODE = 0;
const int MIP_MODE = 3;

vec4 getColorSample(int mode, vec3 texCoord, vec4 colorMax){
    vec4 color = vec4(0.0,0.0,0.0,0.0);
    vec4 normal = vec4(0.0,0.0,0.0,0.0);
    vec4 prevColor = vec4(0.0,0.0,0.0,0.0);
    vec4 nextColor = vec4(0.0,0.0,0.0,0.0);

    mode = PHONG_MODE;
    if(mode == X_RAY_MODE){

        color = texture(texturaVolum, texCoord);
//        color.a = 1.0;
        if(color.x*255 < umbralSaturacio)
            color = vec4(0.0,0.0,0.0,0.0);

    } else if(mode == LUT_MODE) {

        vec4 valor = texture(texturaVolum, texCoord);
        if(valor.x*255 > umbralSaturacio){
            color = texture(texturaLut, valor.x);
//            color.a = 1.0;
        }

    } else if (mode == PHONG_MODE){


        float actValue = vec4(texture(texturaVolum, vec3(texCoord.x, texCoord.y, texCoord.z))).x;

        prevColor.x = vec4(texture(texturaVolum, vec3(texCoord.x-(1.0/anchura), texCoord.y, texCoord.z))).x;
        nextColor.x = vec4(texture(texturaVolum, vec3(texCoord.x+(1.0/anchura), texCoord.y, texCoord.z))).x;
        prevColor.y = vec4(texture(texturaVolum, vec3(texCoord.x, texCoord.y-(1.0/altura), texCoord.z))).y;
        nextColor.y = vec4(texture(texturaVolum, vec3(texCoord.x, texCoord.y+(1.0/altura), texCoord.z))).y;
        prevColor.z = vec4(texture(texturaVolum, vec3(texCoord.x, texCoord.y, texCoord.z-(1.0/profundidad)))).z;
        nextColor.z = vec4(texture(texturaVolum, vec3(texCoord.x, texCoord.y, texCoord.z+(1.0/profundidad)))).z;

        if(actValue*255 > umbralSaturacio /*&& actValue*255 > 40*/){

            normal = vec4(normalize(nextColor.xyz - prevColor.xyz),1.0);

//            vec3 N = normalize(normal.xyz);
            vec3 N = vec3(normal.x,normal.y,normal.z);
            vec3 V = normalize(fV);
            vec3 L = normalize(fL);

            vec3 H = normalize( L + V );

            float constDifusa = max( dot(L, N), 0.0 );

            //float d = length(fL - fV);
            //float atenuacio = 1/(0.8+0.65*d+0.3*pow(d,2.0));

            float constEspecular = pow( max(dot(N, H), 0.0), matPrimari.coef);

            color = (l.int_ambient * matPrimari.comp_ambient)
                                     + (constDifusa * l.int_difusa * texture(texturaLut, actValue))
                                     + (constEspecular * l.int_especular * matPrimari.comp_especular);
//            color.a = 1.0;

        } else {
            color = vec4(0.0,0.0,0.0,0.0);
        }
    } else if (mode == MIP_MODE) {
        color = texture(texturaVolum, texCoord);
        /*if(color.x > colorMax.x){
            colorMax = color;
        }
        if(colorMax.x*255 < umbralSaturacio){
            colorMax = vec4(0.0,0.0,0.0,0.0);
        }*/
        if(color.x*255 >= umbralSaturacio){
            if(color.x > colorMax.x){
                colorMax = color;
            }
        }
        return colorMax;
    }
    return color;
}

void main(void)
{


      vec4 start = IN.TexCoord; // the start position of the ray is stored in the texturecoordinate

      vec3 dir = vec3(0,0,0);
      float len = 0.0;
      if(rcMode == ONE_STEP_MODE){
//          dir.x = vrp.x - obs.x;
//          dir.y= vrp.y - obs.y;
//          dir.z = vrp.z - obs.z;
//          dir = normalize(dirVec);
          dir = dirVec;
//          len = 2.0*(length(start.xyz) /*- vrp.xyz*/);
          len = length(normalize(dir.xyz));
      } else {
          vec2 texc = ((IN.Pos.xy / IN.Pos.w) + 1) / 2; // find the right place to lookup in the backside buffer
          vec4 back_position  = texture2D(backface, texc);
          dir.x = back_position.x - start.x;
          dir.y = back_position.y - start.y;
          dir.z = back_position.z - start.z;
          len = length(dir.xyz); // the length from front to back is calculated and used to terminate the ray
      }
//      float len = length(dir.xyz); // the length from front to back is calculated and used to terminate the ray

      vec3 norm_dir = normalize(dir);
      float delta = stepsize;
      vec3 delta_dir = norm_dir * delta;
      float delta_dir_len = length(delta_dir);
      vec3 vec = vec3(start.x, start.y, start.z);
      vec4 col_acc = vec4(0,0,0,0);
      float alpha_acc = 0;
      float length_acc = 0;
      vec4 color_sample = vec4(-1.0,-1.0,-1.0,-1.0);
      vec4 aux = vec4(0.0,0.0,0.0,0.0);
      float alpha_sample = 0.0;
      int i = 0;
      vec4 colorMax = vec4(-1.0, -1.0, -1.0, -1.0);
      for(i; i < 1024; i++)
        {
          color_sample = getColorSample(colorMode, vec, color_sample);
//          color_sample += vec4(0.2,0.2,0.2,0.2);
          alpha_sample = color_sample.a * umbralOpacitat * 100 * (stepsize)/* * 400.0*sqrt(3.0)*/;
          col_acc   += (1.0 - alpha_acc) * color_sample * alpha_sample /** umbralOpacitat*//**128*/;
          alpha_acc += alpha_sample /*+ (1.0-alpha_acc)*alpha_sample*/;
          vec += delta_dir;
          length_acc += delta_dir_len;
//          if(length_acc >= len || alpha_acc > 1.0) break; // terminate if opacity > 1 or the ray is outside the volume
          if((vec.x<0.00001 || vec.x>0.999999 || vec.y<0.00001 || vec.y>0.999999 ||
          vec.z<0.000001|| vec.z>0.999999) || alpha_acc > 0.99999999) break; // terminate
          //if opacity > 1 or the ray is outside the volume
        }

      if(colorMode == MIP_MODE){
          fColor = color_sample;
      } else {
          fColor = col_acc;
      }

      fColor.a = 1.0;

//      fColor = vec4(len, 0.0,0.0,1.0);

}
