ef01c3ccf709 — Leonard Ritter 9 months ago
* VVF: fixed smooth normals
1 files changed, 138 insertions(+), 79 deletions(-)

M testing/test_cascade_dmc_cc_vvf.sc
M testing/test_cascade_dmc_cc_vvf.sc +138 -79
@@ 50,7 50,7 @@ VISUALIZE_LOD := false
 POST_TRANSFORM := false # true is worse
 OCCLUSION_CULLING := false
 FOG := false
-USE_FLAT_SHADING := false
+USE_FLAT_SHADING := true
 BALANCE_QUADS := true
 USE_COMPLEX_SURFACE := false
 HIGH_QUALITY_FEATURES := true

          
@@ 82,8 82,8 @@ let GROUP_SIZE = 4
 let MAX_SECTOR_LOD_I = 2
 let SECTOR_GROUP_SIZE = (1 << MAX_SECTOR_LOD_I)
 
-#let SUBDIVIDE_RADIUS = 6
-let SUBDIVIDE_RADIUS = 4
+let SUBDIVIDE_RADIUS = 6
+#let SUBDIVIDE_RADIUS = 4
 let SUBDIVIDE_SCALE = 12
 
 MAX_CASCADE_DEPTH := 6 # MAX_WORLD_LOD_I - MAX_SECTOR_LOD_I

          
@@ 136,6 136,15 @@ let
     BLEND+Z = 16:u32
     BLEND-Z = 32:u32
 
+# corner planes
+let
+    MASK_PLANE-X = 0x01010101
+    MASK_PLANE+X = 0x10101010
+    MASK_PLANE-Y = 0x00110011
+    MASK_PLANE+Y = 0x11001100
+    MASK_PLANE-Z = 0x00001111
+    MASK_PLANE+Z = 0x11110000
+
 struct Sector plain
     key : u32
     flags : u32 # six face bits indicating where the next highest LOD level is

          
@@ 467,8 476,25 @@ fn gradient-root (v0 v1 dir)
     q1 := (c + w) * 2.0 - 1.0
     ? ((abs q0) < (abs q1)) q0 q1
 
-fn triangle-area (A B C)
-    (length (cross (B - A) (C - A))) / 2.0
+inline triangle-area-normal (v1 v2 v3)
+    if 1
+        cross
+            (v2 - v1) . xyz
+            (v3 - v1) . xyz
+    else
+        let a b =
+            (v2 - v1) . xyz
+            (v3 - v1) . xyz
+        *
+            cross (normalize a) (normalize b)
+            length (cross a b)
+
+inline triangle-normal (v1 v2 v3)
+    normalize (triangle-area-normal v1 v2 v3)
+
+# triangle area * 2
+inline triangle-areax2 (v1 v2 v3)
+    length (triangle-area-normal v1 v2 v3)
 
 fn trimix (v p)
     # corner weights of cube in [-1..1]³ domain

          
@@ 1099,13 1125,6 @@ fn svindex2id (idx)
 
 NATIVE_LANE_WIDTH := 64
 
-fn normal (v1 v2 v3)
-    cross
-        normalize
-            (v3 - v1) . xyz
-        normalize
-            (v2 - v1) . xyz
-
 inline swapnormal (v n)
     Vertex v.pos (vec4 n 0)
 

          
@@ 1125,8 1144,8 @@ fn generate-quad (v00 v01 v10 v11)
     let ofs = (atomicAdd vertex-out.count 6)
     entries := vertex-out.entries
     static-if USE_FLAT_SHADING
-        n0 := (normal v00.pos v10.pos v11.pos)
-        n1 := (normal v11.pos v01.pos v00.pos)
+        n0 := (triangle-normal v00.pos v10.pos v11.pos)
+        n1 := (triangle-normal v11.pos v01.pos v00.pos)
         #n1 := (normal v00.pos v11.pos v01.pos)
 
         entries @ (ofs + 0) = (swapnormal v00 n0)

          
@@ 1153,8 1172,8 @@ let
     BLEND-Z = 32:u32
 
 fn lod-skirt? (p sector-flags)
-    MIND := SECTOR_GROUP_SIZE // 2
-    MAXD := SECTOR_GROUP_SIZE
+    MIND := 2
+    MAXD := SECTOR_GROUP_SIZE - 2
     predicate-flags :=
         |
             ? (p.x >= MAXD) BLEND+X 0:u32

          
@@ 1209,7 1228,6 @@ fn generate-cell-verts ()
         local cflags = 0:u32
         for i in (range 0 8)
             let x y z = (i & 1) ((i >> 1) & 1) ((i >> 2) & 1)
-            #d := (((x ^ y ^ z) & 1) * 2 - 1) as f32
             delta := (ivec3 x y z)
             wpos := gpos + delta
             let wpos lod =

          
@@ 1233,37 1251,72 @@ fn generate-cell-verts ()
                     _ (gpos >> 1) (lod + 1) 2.0 (1.0 - (vec3 (gpos & 1)) * 2.0)
                 else
                     _ gpos lod 1.0 (vec3 0.0)
+
+            local cflags = 0:u32
+            for i in (range 0 8)
+                let x y z = (i & 1) ((i >> 1) & 1) ((i >> 2) & 1)
+                delta := (ivec3 x y z)
+                wpos := vpos + delta
+                let vx cf =
+                    unpack-vvf (texelFetch smp-world wpos vlod)
+                cflags |= ((cf & 1) << (i as u32))
+            cflags := (deref cflags)
+
             inline fetch (offset)
                 let vx =
                     static-if BLOCKY_WORLD (vec3 0)
                     else
                         _ (unpack-vvf (texelFetch smp-world (vpos + offset) vlod)) ()
-                vx := vx + (vec3 offset) * 2.0
-                vx := vx * vscale + voffset
-            let vc v-x v+x v-y v+y v-z v+z =
-                fetch (ivec3 0)
-                fetch (ivec3 1 0 0)
-                fetch (ivec3 -1 0 0)
-                fetch (ivec3 0 1 0)
-                fetch (ivec3 0 -1 0)
-                fetch (ivec3 0 0 1)
-                fetch (ivec3 0 0 -1)
-            inline edgeweight (mask)
-                m := (cflags & mask)
-                ? ((m != mask) & (m != 0)) 1.0 0.0
-            let nvert =
-                +
-                    (vec4 (v+x - vc) 1) * (edgeweight 0x10101010)
-                    (vec4 (vc - v-x) 1) * (edgeweight 0x01010101)
-                    (vec4 (v+y - vc) 1) * (edgeweight 0x11001100)
-                    (vec4 (vc - v-y) 1) * (edgeweight 0x00110011)
-                    (vec4 (v+z - vc) 1) * (edgeweight 0x11110000)
-                    (vec4 (vc - v-z) 1) * (edgeweight 0x00001111)
-            normal := nvert.xyz / nvert.w
+                vx + (vec3 offset) * 2.0
+
+            let v000 = (fetch (ivec3 0 0 0))
+
+            ### compute vertex normal
+
+            inline edgebits (a b)
+                (cflags >> a as u32) & 1, (cflags >> b as u32) & 1
+
+            inline edge (a b)
+                let u v = (edgebits a b)
+                (u != v), (u == 0)
+
+            local normal_accum = (vec3 0)
+            inline collect-plane (Du fpermute u v)
+                Dv := (Du + 1) % 3
+                Dw := (Du + 2) % 3
+                i0 := (u << Du) | (v << Dv)
+                i1 := i0 ^ (1 << Dw)
+                let set? flip? = (edge i0 i1)
+                if set?
+                    flip? := flip? ^ ((u ^ v) == 1)
+                    v00 := v000
+                    let du dv = (u * 2 - 1) (v * 2 - 1)
+                    v01 := (fetch (fpermute du  0))
+                    v10 := (fetch (fpermute  0 dv))
+                    #v11 := (fetch (fpermute du dv))
+                    n1 := (triangle-area-normal v00 v01 v10)
+                    #n2 := (triangle-area-normal v11 v10 v00)
+
+                    #normal_accum += (n1 + n2) * (? flip? -1.0 1.0)
+                    normal_accum += n1 * (? flip? -1.0 1.0)
+                    ;
+
+            for u v in (dim 2 2)
+                collect-plane 0 # XY
+                    inline (du dv) (ivec3 du dv 0)
+                    \ u v
+                collect-plane 1 # YZ
+                    inline (du dv) (ivec3 0 du dv)
+                    \ u v
+                collect-plane 2 # ZX
+                    inline (du dv) (ivec3 dv 0 du)
+                    \ u v
+
             vertexlod := lod as f32 + (? llod? 0.5 0.0)
+            vertex := v000 * vscale + voffset
             cell-vertex @ idx =
-                vec4 vc vertexlod
-            cell-normal @ idx = normal
+                vec4 vertex vertexlod
+            cell-normal @ idx = (normalize normal_accum)
             ;
         ;
     barrier;

          
@@ 1283,22 1336,19 @@ fn generate-cell-verts ()
             dpos := lpos + offset
             idx := (id2svindex dpos)
             v := (copy (cell-vertex @ idx))
-            transform-vertex v dpos
+            _ (transform-vertex v.xyz dpos) (copy (cell-normal @ idx))
 
         local verts : (array vec4 7)
+        local norms : (array vec4 7)
         local n = 0
         va-map
             inline (i)
                 verts @ i = (vec4 0)
+                norms @ i = (vec4 0)
             va-range 7
         let C00- C00+ C0-0 C0+0 C-00 C+00 C000 = (va-range 7)
 
-        let v000 = (getvertex (ivec3 0 0 0))
-        #inline check-edge (IDX ofs mask)
-            x := (cflags & mask)
-            if ((x != mask) & ((x ^ mask) != mask))
-                m := (v000 + (getvertex ofs))
-                w @ C00- = (vec4 m 2)
+        let v000 n000 = (getvertex (ivec3 0 0 0))
 
         inline edgebits (a b)
             (cflags >> a as u32) & 1, (cflags >> b as u32) & 1

          
@@ 1316,18 1366,22 @@ fn generate-cell-verts ()
                 let set? flip? = (edge i0 i1)
                 if set?
                     v00 := v000
+                    n00 := n000
                     let du dv = (u * 2 - 1) (v * 2 - 1)
-                    v01 := (getvertex (fpermute du  0))
-                    v10 := (getvertex (fpermute  0 dv))
-                    v11 := (getvertex (fpermute du dv))
-                    # face vertices
-                    fv := ((v00 + v01 + v10 + v11) / 4)
-                    # edge vertices
-                    ev01 := (v00 + v01) / 2
-                    ev10 := (v00 + v10) / 2
-                    verts @ C000 += (vec4 (fv + ev01 + ev10) 3)
-                    verts @ (Du * 2 + u) += (vec4 (fv + ev01) 2)
-                    verts @ (Dv * 2 + v) += (vec4 (fv + ev10) 2)
+                    let v01 n01 = (getvertex (fpermute du  0))
+                    let v10 n10 = (getvertex (fpermute  0 dv))
+                    let v11 n11 = (getvertex (fpermute du dv))
+                    inline compute-verts (verts v00 v01 v10 v11)
+                        # face vertices
+                        fv := ((v00 + v01 + v10 + v11) / 4)
+                        # edge vertices
+                        ev01 := (v00 + v01) / 2
+                        ev10 := (v00 + v10) / 2
+                        verts @ C000 += (vec4 (fv + ev01 + ev10) 3)
+                        verts @ (Du * 2 + u) += (vec4 (fv + ev01) 2)
+                        verts @ (Dv * 2 + v) += (vec4 (fv + ev10) 2)
+                    compute-verts verts v00 v01 v10 v11
+                    compute-verts norms n00 n01 n10 n11
                     n += 1
                     ;
 

          
@@ 1351,28 1405,33 @@ fn generate-cell-verts ()
                 if set?
                     flip? := flip? ^ ((u ^ v) == 1)
                     v00 := v000
+                    n00 := n000
                     let du dv = (u * 2 - 1) (v * 2 - 1)
-                    v01 := (getvertex (fpermute du  0))
-                    v10 := (getvertex (fpermute  0 dv))
-                    v11 := (getvertex (fpermute du dv))
-                    # face vertices
-                    fv := (v00 + v01 + v10 + v11) / 4
-                    # edge vertices
-                    ev01 := (copy (verts @ (Du * 2 + u)))
-                    ev01 := ev01.xyz / ev01.w
-                    ev10 := (copy (verts @ (Dv * 2 + v)))
-                    ev10 := ev10.xyz / ev10.w
-                    # center vertex
-                    cv := (copy (verts @ C000))
-                    cv := cv.xyz / cv.w
-                    let ev01 ev10 =
-                        if flip? (_ ev10 ev01)
-                        else (_ ev01 ev10)
+                    let v01 n01 = (getvertex (fpermute du  0))
+                    let v10 n10 = (getvertex (fpermute  0 dv))
+                    let v11 n11 = (getvertex (fpermute du dv))
+                    inline compute-quad (verts v00 v01 v10 v11)
+                        # face vertices
+                        fv := (v00 + v01 + v10 + v11) / 4
+                        # edge vertices
+                        ev01 := (copy (verts @ (Du * 2 + u)))
+                        ev01 := ev01.xyz / ev01.w
+                        ev10 := (copy (verts @ (Dv * 2 + v)))
+                        ev10 := ev10.xyz / ev10.w
+                        # center vertex
+                        cv := (copy (verts @ C000))
+                        cv := cv.xyz / cv.w
+                        let ev01 ev10 =
+                            if flip? (_ ev10 ev01)
+                            else (_ ev01 ev10)
+                        _ cv ev01 ev10 fv
+                    let v0 v1 v2 v3 = (compute-quad verts v00 v01 v10 v11)
+                    let n0 n1 n2 n3 = (compute-quad norms n00 n01 n10 n11)
                     generate-quad
-                        Vertex (vec4   cv 1) (vec4 0)
-                        Vertex (vec4 ev01 1) (vec4 0)
-                        Vertex (vec4 ev10 1) (vec4 0)
-                        Vertex (vec4   fv 1) (vec4 0)
+                        Vertex (vec4 v0 1) (vec4 n0 0)
+                        Vertex (vec4 v1 1) (vec4 n1 0)
+                        Vertex (vec4 v2 1) (vec4 n2 0)
+                        Vertex (vec4 v3 1) (vec4 n3 0)
 
         build-plane 0 # XY
             inline (du dv) (ivec3 du dv 0)