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:         )
  
          
          tessGrid 64
              |> Sg.ofIndexedGeometry
              |> Sg.effect [
                  DefaultSurfaces.trafo |> toEffect 
                  Shader.hTessControl |> toEffect
                  Shader.hTessEval |> toEffect
                  DefaultSurfaces.constantColor C4f.White |> toEffect
                  DefaultSurfaces.diffuseTexture |> toEffect
  //                DefaultSurfaces.simpleLighting |> toEffect 
  
negative.code:                 //return { innerLevel = [|1.0; 1.0|]; outerLevel = [| 1.0; 1.0; 1.0; 1.0 |]} 
                  return { innerLevel = [|i0; i1|]; outerLevel = [| t0; t1; t2; t3 |]}  
              }
  
          type TessVertex =
              {
                  [<WorldPosition>] wp : V4d
                  [<TexCoord>] tc : V2d
                  [<TessLevelInner>] tessInner : float[]
                  [<TessLevelOuter>] tessOuter : float[]
              }
  
          let inline int4 (cx : ^a) (cy : ^a) (p0 : ^b) (p1 : ^b) (p2 : ^b) (p3 : ^b) : ^b =
              let x = (LanguagePrimitives.GenericOne - cx) * p0 + cx * p1
              let y = (LanguagePrimitives.GenericOne - cx) * p2 + cx * p3
              (LanguagePrimitives.GenericOne - cy) * x + cy * y
  
  
  
          let hTessEval (m : Patch4<Vertex>) =
              tessEval {
                  let c = m.TessCoord.XY
  
                  let a = m.P0.wp * (1.0 - c.X) + m.P1.wp * c.X
                  let b = m.P2.wp * (1.0 - c.X) + m.P3.wp * c.X
                  let wp = a * (1.0 - c.Y) + b * c.Y
  
                  let a = m.P0.tc * (1.0 - c.X) + m.P1.tc * c.X
                  let b = m.P2.tc * (1.0 - c.X) + m.P3.tc * c.X
                  let tc = a * (1.0 - c.Y) + b * c.Y
  
                  let dx = V2d(0.5, 0.0)
                  let dy = V2d(0.0, 0.5)
  
                  let cx = c + dx
                  let a = m.P0.tc * (1.0 - cx.X) + m.P1.tc * cx.X
                  let b = m.P2.tc * (1.0 - cx.X) + m.P3.tc * cx.X
                  let tcx = a * (1.0 - cx.Y) + b * cx.Y
  
                  let cy = c + dy
                  let a = m.P0.tc * (1.0 - cy.X) + m.P1.tc * cy.X
                  let b = m.P2.tc * (1.0 - cy.X) + m.P3.tc * cy.X
                  let tcy = a * (1.0 - cy.Y) + b * cy.Y
  
                  let u = tcx - tc
                  let v = tcy - tc
  
                  let h = heightSampler.SampleGrad(tc, u, v).X * heightScale
                  let wp = wp + V4d(0.0, 0.0, h, 0.0)
  
                  return {
                      pos = uniform.ViewProjTrafo * wp
  