/*
 * cubic_surface_mapping(): Shade a box with background repeatable texture.  Also apply bump mapping to texture using
 *                          the alpha channel (channel[3]) of the background texture file as the texture map.  Add up to 5 foreground textures.
 *                          foregrndx_P (where u_offset is from 1 to 5) is a point whose u_offset and v_offset are the u,v offset and z component is scaling.
*/

surface
cubic_surface_mapping(
     float Ka = 0.5,
              Kd = 0.4,
              Ks = 0.1,
               roughness = 0.1,
               urepeat = 1.0,
               vrepeat = 1.0;
     color specularcolor = 1;
     string bkgrnd_texturename = "wood_panel2.tif";
     string foregrnd1_texturename = "";
     string foregrnd2_texturename = "";
     string foregrnd3_texturename = "";
     string foregrnd4_texturename = "";
     string foregrnd5_texturename = "";
     string foregrnd1_bumpname = "";
     string foregrnd2_bumpname = "";
     string foregrnd3_bumpname = "";
     string foregrnd4_bumpname = "";
     string foregrnd5_bumpname = "";
     float foregrnd1_P_x; 
     float foregrnd1_P_y; 
     float foregrnd1_P_z; 
     float foregrnd2_P_x; 
     float foregrnd2_P_y; 
     float foregrnd2_P_z; 
     float foregrnd3_P_x; 
     float foregrnd3_P_y; 
     float foregrnd3_P_z; 
     float foregrnd4_P_x; 
     float foregrnd4_P_y; 
     float foregrnd4_P_z; 
     float foregrnd5_P_x; 
     float foregrnd5_P_y; 
     float foregrnd5_P_z)
{
 
     point Nf;
     color cs, ct;
     float opacity = 1;
     float u_offset, v_offset, scale, s_new, t_new;

     ct = 0;
     Nf = faceforward(normalize(N), I);
     Oi = 1.0;

     /* Apply the background texture */
     cs = color texture(bkgrnd_texturename, u*urepeat, v*vrepeat);
     cs = cs * (1-float texture(bkgrnd_texturename [3], u*urepeat, v*vrepeat));   /** Bump mapping **/

     if(foregrnd1_texturename != ""){
          u_offset = foregrnd1_P_x;
          v_offset = foregrnd1_P_y;
          scale = foregrnd1_P_z;
          if((u >= u_offset) && (v >= v_offset) && (u <= u_offset + scale) && (v <= v_offset + scale)){
              /* Recalculate s,t by offsetting it to u_offset,v_offset */
              s_new = (u-u_offset)*(du/dv)*(1/scale);
              t_new = (v-v_offset)*1.0;
              if((s_new <= (1.0/2.0) + u_offset)){
              /* Find color from foreground texture and calculate opacity from alpha channel.  Scale is as well) */
              ct = color texture(foregrnd1_texturename, s_new*(1/scale),t_new*(1/scale));	
              ct = ct * (1 - float texture(foregrnd1_bumpname, s_new*(1/scale),t_new*(1/scale)));		    /* Calculate bump mapping */
              opacity = 1-float texture(foregrnd1_texturename [3], s_new*(1/scale),t_new*(1/scale));            /*Use the alpha channel as a clipping channel */
             }
          }
    } 

     if(foregrnd2_texturename != ""){
          u_offset = foregrnd2_P_x;
          v_offset = foregrnd2_P_y;
          scale = foregrnd2_P_z;

          if((u >= u_offset) && (v >= v_offset) && (u <= u_offset + scale) && (v <= v_offset + scale)){
              /* Recalculate s,t by offsetting it to u_offset,v_offset */
              s_new = u-u_offset;              
              t_new = v-v_offset;
              /* Find color from foreground texture and calculate opacity from alpha channel.  Scale is as well) */
              ct = color texture(foregrnd2_texturename, s_new*(1/scale),t_new*(1/scale));
              opacity = 1-float texture(foregrnd2_texturename [3], s_new*(1/scale),t_new*(1/scale));            /*Use the alpha channel as a clipping channel */
          }
    } 

     if(foregrnd3_texturename != ""){
          u_offset = foregrnd3_P_x;
          v_offset = foregrnd3_P_y;
          scale = foregrnd3_P_z;

          if((u >= u_offset) && (v >= v_offset) && (u <= u_offset + scale) && (v <= v_offset + scale)){
              /* Recalculate s,t by offsetting it to u_offset,v_offset */
              s_new = u-u_offset;              
              t_new = v-v_offset;
              /* Find color from foreground texture and calculate opacity from alpha channel.  Scale is as well) */
              ct = color texture(foregrnd3_texturename, s_new*(1/scale),t_new*(1/scale));
              opacity = 1-float texture(foregrnd3_texturename [3], s_new*(1/scale),t_new*(1/scale));            /*Use the alpha channel as a clipping channel */
          }
    } 

     if(foregrnd4_texturename != ""){
          u_offset = foregrnd4_P_x;
          v_offset = foregrnd4_P_y;
          scale = foregrnd4_P_z;

          if((u >= u_offset) && (v >= v_offset) && (u <= u_offset + scale) && (v <= v_offset + scale)){
              /* Recalculate s,t by offsetting it to u_offset,v_offset */
              s_new = u-u_offset;              
              t_new = v-v_offset;
              /* Find color from foreground texture and calculate opacity from alpha channel.  Scale is as well) */
              ct = color texture(foregrnd4_texturename, s_new*(1/scale),t_new*(1/scale));
              opacity = 1-float texture(foregrnd4_texturename [3], s_new*(1/scale),t_new*(1/scale));            /*Use the alpha channel as a clipping channel */
          }
    } 

     if(foregrnd5_texturename != ""){
          u_offset = foregrnd5_P_x;
          v_offset = foregrnd5_P_y;
          scale = foregrnd5_P_z;

          if((u >= u_offset) && (v >= v_offset) && (u <= u_offset + scale) && (v <= v_offset + scale)){
              /* Recalculate s,t by offsetting it to u_offset,v_offset */
              s_new = u-u_offset;              
              t_new = v-v_offset;
              /* Find color from foreground texture and calculate opacity from alpha channel.  Scale is as well) */
              ct = color texture(foregrnd5_texturename, s_new*(1/scale),t_new*(1/scale));
              opacity = 1-float texture(foregrnd5_texturename [3], s_new*(1/scale),t_new*(1/scale));            /*Use the alpha channel as a clipping channel */
          }
    } 

     cs = mix(ct, cs, opacity);
     Ci = cs * (Ka*ambient() + Kd*diffuse(Nf)) + Ks*specularcolor*specular(Nf, normalize(-I), roughness);
}