/* Authors:
   Yuan Kui Shen  cs162-ac  12940472
   Raul Yoni Chu  cs162-bq  12782756
/* windows.sl 
   This shader creates a spaceship like skin texture.
   - This displacement shader creates grooves in the
   surface running in the longitudinal direction (t).
   - And creates windows, running along the horizontal (s)
   direction.
   - The color of the light emitted from the window is
   specified by "window_color", while the skin color itself
   is derived from the surface it covers
   - w_base, w_height, w_width are values of the dimensions
   of the windows from 0 to 1.  (The windows are not rendered
   very clearly when used with high "freq"...antialiasing problems
   may occur)
   - "gap" defines the margin, in which the actual windows should
   appear, (the window is drawn with an offset of gap from w_base
   - maxT and minT, defines the region which windows are actually drawn
   this is convenient for some structures which there is a gap
   near the very top and bottom where there are no windows
*/
/* definitions for convenience borrowed
   from rmannotes.sl */
#define pulse(a,b,fuzz,x) (smoothstep((a)-(fuzz),(a),(x)) - \
			   smoothstep((b)-(fuzz),(b),(x)))
#define repeat(x,freq)    (mod((x) * (freq), 1.0))
#define even(x)           (mod((x), 2) == 0)
#define whichtile(x,freq) (floor((x) * (freq)))
#define blend(a,b,x) ((a) * (1 - (x)) + (b) * (x))
displacement windows (float Ka = 1;
		 float Kd = .5;
		 float Ks = .5;
		 float roughness = .1;
		 color specularcolor = 1;
		 float freq = 4; 
		 float Km = 0.005;
		 color window_color = (1, 1, 1);  /* white */
		 float w_base = 0.2;
		 float w_height = 0.2;
		 float w_width = 0.80;
		 float gap = 0.025;
		 float maxT = 0.80;
		 float minT = 0.20;
		 ) 
{

  color surface_color = Cs;
  color surface_opac = Os;
  color window_opac;

  float fuzz = 0.0025;	 
  float base_surface = 0.0;
  float windows_surface;  
  float numOfWindowsPerSquare = 2;
  
  float ss = repeat(s, numOfWindowsPerSquare * freq);
  float tt = repeat(t, freq);

  /* layer 0 */
  /* create a grove going in the t direction */
  float col = whichtile(s, numOfWindowsPerSquare*freq);
  
  /* Make the groove at even square intervals so
     as to not make the design look too crowded */
  if (even(col)) {
    windows_surface = 1 - pulse(0, 2 * gap, fuzz, ss);
    base_surface = max(windows_surface, base_surface);
    
    color groove_color = (0, 0, 0);
    window_opac = pulse(0, 2*gap, fuzz, ss);
    surface_color = blend(surface_color, groove_color, window_opac);
  }
				/* get the grouped rows of windows effect */
  if (t < maxT && t > minT) { 

    /* layer 1 */
    windows_surface = pulse(w_base, w_base + w_height, fuzz, tt);
    base_surface = max(windows_surface, base_surface);

    /* layer 2 */
    if ( tt > (w_base + gap) && tt < (w_base + w_height - gap) ) {	
      windows_surface = 1 - pulse(0.5 - (w_width / 2), 0.5 + (w_width / 2), 
				  fuzz, ss);
      base_surface = min(windows_surface, base_surface);
      

      window_opac = pulse(0.5 - (w_width / 2), 0.5 + (w_width / 2), 
			   fuzz, ss);

      surface_color = blend(surface_color, window_color, window_opac);
    }
  }

  P += Km * base_surface * normalize(N);
  N = calculatenormal(P);

  /* output */
  normal Nf = faceforward (normalize(N),I);
  Oi = surface_opac;
  if (surface_color != window_color) {
    /* for the non metalic glass portions 
       set the texture to be shiny...similar to metal/plastic */
    Ci = surface_opac * ( surface_color * (Ka*ambient() + Kd*diffuse(Nf)) +
			  specularcolor * 
			  Ks*specular(Nf,-normalize(I),roughness));
  }
  else {
    /* for the actual window use the window_color */
    Ci = window_color;
  }
}