const float cutoff = 1.0; // Gode Gamle Dobbel Nyquist(tm) -- fordi LITT aliasing aldri har skadet noen.
float getChecker(vec2 fw, vec2 hit, float checkerFreq)
{
  vec2 fuzz = fw * checkerFreq * 2.0;
  float fuzzMax = max(fuzz.x, fuzz.y);

  vec3 color;
  if (fuzzMax < cutoff)
  {
    vec2 checkPos = fract(hit * checkerFreq + fuzz * 0.5);
    vec2 p =
             smoothstep(vec2(0.5,0.5), fuzz + vec2(0.5, 0.5), checkPos)
    + (1.0 - smoothstep(vec2(0.0,0.0), fuzz, checkPos));

    float t = p.x * p.y + (1.0 - p.x) * (1.0 - p.y);
    return mix(t, 0.5, smoothstep(0.125, cutoff, fuzzMax));
  }
  return 0.5;
}

uniform float CheckerFreq1;
uniform float CheckerFreq2;
uniform float HazeDist;
uniform float PlaneZ;
uniform float InvScaleZ;

uniform vec3 CheckerColor1;
uniform vec3 CheckerColor2;
uniform float rPlaneOpacity;

uniform sampler2D myDepthPeelingZTexture;
uniform vec2 cViewportSize;

varying vec3 pos;
varying vec3 vdir;

void main(void)
{
  vec3 dir = normalize(vdir);
  dir.z *= InvScaleZ;

  float t =  -(pos.z - PlaneZ) / dir.z;
  vec2 hit = pos.xy + dir.xy * t;

  vec2 fw = fwidth(hit); // needs to be done outside of control logic

  if (t < 0.0)
  {
    discard;
  }

  float rChecker = getChecker(fw, hit, CheckerFreq1);
  rChecker = mix(rChecker, getChecker(fw, hit, CheckerFreq2), 0.25);
  vec3 color = mix(CheckerColor1, CheckerColor2, rChecker);
  float rHazing = HazeDist / (HazeDist + distance(pos, vec3(hit, PlaneZ)));
  gl_FragColor = vec4(color, rPlaneOpacity) * rHazing;

  // calculate depth coordinate
  // equations taken from section 2.14.1 of the OpenGL spec

  // calculate clip-space z/w
  vec2 tmp = (gl_ModelViewProjectionMatrix * vec4(hit.xy, PlaneZ, 1.0)).zw;
  // project
  float depth = tmp.x / tmp.y;
  // viewport map
  depth = (gl_DepthRange.diff * depth + gl_DepthRange.near + gl_DepthRange.far) * 0.5;

  // clamp to avoid z-fighting
  gl_FragDepth = clamp(depth, 1e-5, 1.0 - 1e-5);

  // depth peel
  if (cViewportSize.x > 0.0 && texture2D(myDepthPeelingZTexture, (gl_FragCoord.xy + vec2(0.0)) * cViewportSize).r >= gl_FragDepth)
  {
    discard;
  }
}
