anchor.diff:              let wp = world + V4d(0.0, 0.0, h, 0.0)
               wp
   
  -        let project (v : V4d) =
  +        let isVisible (world : V4d) =
  +            let v = uniform.ViewProjTrafo * world
               let ss = v.XYZ / v.W
  -            V2d uniform.ViewportSize * (V2d(ss.X * 0.5 + 0.5, 0.5 - ss.Y * 0.5))
  +            ss.X >= -1.0 && ss.Y >= -1.0 && ss.X <= 1.0 && ss.Y <= 1.0
  +
  +        type Coord = { value : V2d; offscreen : bool }
  +
  +
  +        let getMaxInDirection (dir : V3d) (min : V3d) (max : V3d) =
  +            V3d(
  +                (if dir.X > 0.0 then max.X else min.X),
  +                (if dir.Y > 0.0 then max.Y else min.Y),
  +                (if dir.Z > 0.0 then max.Z else min.Z)
  +            )
  +
  +        let outsidePlane (p : V4d) (min : V3d) (max : V3d) =
  +            let n = p.XYZ
  +            let md = getMaxInDirection n min max
  +            let h = Vec.dot md n + p.W 
  +            h < 0.0
  +
  +        let boxOutsideFrustum (min : V3d) (max : V3d) (frustum : M44d) =
  +            let r0 = frustum.R0
  +            let r1 = frustum.R1
  +            let r2 = frustum.R2
  +            let r3 = frustum.R3
  +
  +            outsidePlane (r3 + r0) min max || 
  +            outsidePlane (r3 - r0) min max ||
  +            outsidePlane (r3 + r1) min max || 
  +            outsidePlane (r3 - r1) min max ||
  +            outsidePlane (r3 + r2) min max || 
  +            outsidePlane (r3 - r2) min max
  +
  +
  +             
  +
  +        let project (world : V4d) =
  +            let visible = isVisible world || isVisible (world + V4d(0.0, 0.0, heightScale, 0.0))
  +            let v = uniform.ViewProjTrafo * world
  +            let ss = v.XYZ / v.W
  +            let c = V2d uniform.ViewportSize * (V2d(ss.X * 0.5 + 0.5, 0.5 - ss.Y * 0.5))
  +            c
  +
  +        let bounds (p0 : V4d) (p1 : V4d) (p2 : V4d) (p3 : V4d) =
  +            let min = 
  +                V3d(
  +                    min (min p0.X p1.X) (min p2.X p3.X),
  +                    min (min p0.Y p1.Y) (min p2.Y p3.Y),
  +                    0.0
  +                )
  +
  +            let max = 
  +                V3d(
  +                    max (max p0.X p1.X) (max p2.X p3.X),
  +                    max (max p0.Y p1.Y) (max p2.Y p3.Y),
  +                    heightScale
  +                )
  +
  +            min, max
   
           let hTessControl (m : Patch4<Vertex>) =
               tessControl {
  -                let p0 = project m.P2.pos
  -                let p1 = project m.P0.pos
  -                let p2 = project m.P1.pos
  -                let p3 = project m.P3.pos
  -
  +                let p0 = project m.P2.wp
  +                let p1 = project m.P0.wp
  +                let p2 = project m.P1.wp
  +                let p3 = project m.P3.wp
   
                   let l0 = p1 - p0
                   let l1 = p2 - p1
  
positive.code:         let heightSampler =
              sampler2d {
                  texture uniform?HeightFieldTexture
                  filter Filter.MinMagLinear
                  addressU WrapMode.Clamp
                  addressV WrapMode.Clamp
              }
  
          let planeSize = 10.0
          let heightScale = 0.5
          let pixelSize = 2.0
  
          [<ReflectedDefinition>]
          let sampleHeight (world : V4d)  =
  
negative.code:                 let ll3 = l3.Length
  
  
                  let min, max = bounds m.P0.wp m.P1.wp m.P2.wp m.P3.wp
                  let offscreen = boxOutsideFrustum min max uniform.ViewProjTrafo
  
                  let t0 = if offscreen then 0.0 else ll0 / pixelSize |> clamp 1.0 64.0
                  let t1 = if offscreen then 0.0 else ll1 / pixelSize |> clamp 1.0 64.0
                  let t2 = if offscreen then 0.0 else ll2 / pixelSize |> clamp 1.0 64.0
                  let t3 = if offscreen then 0.0 else ll3 / pixelSize |> clamp 1.0 64.0
  
                  let avg = (t0 + t1 + t2 + t3) / 4.0
  
  