diff --git a/Runtime/VectorTile.cs b/Runtime/VectorTile.cs
index ad10d351f9b039b448856b5b1ef9ae5a4b84200e..61b08dc918729b75a2dff17a6940da7e0614efbd 100644
--- a/Runtime/VectorTile.cs
+++ b/Runtime/VectorTile.cs
@@ -51,7 +51,8 @@ namespace Wander
 
                 // float denominator = ((vertex2.y - vertex3.y) * (vertex1.x - vertex3.x) + (vertex3.x - vertex2.x) * (vertex1.y - vertex3.y));
                 float denominator = ((vertices[i+1].y - vertices[i+2].y) * (vertices[i].x - vertices[i+2].x) + (vertices[i+2].x - vertices[i+1].x) * (vertices[i].y - vertices[i+2].y));
-                denoms.Add( 1.0f / denominator );
+                denominator = 1.0f / denominator;
+                denoms.Add( denominator );
             }
         }
     }
@@ -111,6 +112,12 @@ namespace Wander
             return finished;
         }
 
+        static bool IsTriangleCCW( Vector2 vertex1, Vector2 vertex2, Vector2 vertex3 )
+        {
+            float signedArea = (vertex2.x - vertex1.x) * (vertex3.y - vertex1.y) - (vertex3.x - vertex1.x) * (vertex2.y - vertex1.y);
+            return signedArea > 0;
+        }
+
         // Number of failed polys to triangulate are returned.
         public int Triangulate()
         {
@@ -158,6 +165,15 @@ namespace Wander
                             double y = vertices[indices[k]*2+1];
                             poly.vertices.Add( new Vector2( (float)x, (float)y ) );
                         }
+                        //for ( int k = 0; k < indices.Count; k += 3)
+                        //{
+                        //    if ( !IsTriangleCCW( poly.vertices[k], poly.vertices[k+1], poly.vertices[k+2] ))
+                        //    {
+                        //        var t = poly.vertices[k];
+                        //        poly.vertices[k] = poly.vertices[k+2];
+                        //        poly.vertices[k+2] = t;
+                        //    }
+                        //}
                         polygons[polygons.Count-1] = poly;
                         Debug.Assert( poly.vertices.Count % 3 == 0 );
                     }
@@ -211,7 +227,7 @@ namespace Wander
             int resolution,
             out Dictionary<byte, byte> remappedLayerIndices,     
             out List<Vector3Int> failedPixels,
-            bool? cancelToken)
+            bool? cancelToken )
         {
             Debug.Assert( triangulated, "First call Triangulate." );
             Debug.Assert( layersIdentified, "Identify layers first." );
@@ -220,12 +236,11 @@ namespace Wander
             byte [] texture = new byte[resolution*resolution];
             failedPixels = new List<Vector3Int>();
             remappedLayerIndices = new Dictionary<byte, byte>();
-            byte cachedPixel = 0;
             float oneOverRes = 1.0f / resolution;
 
-            TriangulatedPolygon cachedPoly = default;
-            int cachedVtxIdx  = -1;
-            int cachedTriIdx  = -1;
+            int cachedTriIdx  = 0;
+            int cachedLyrIdx  = 0;
+            int cachedFtrIdx  = 0;
 
             // For each pixel.
             for (int y = 0;y < resolution ;y++)
@@ -237,70 +252,58 @@ namespace Wander
                     // For each layer, check triangle intersections.
                     for (int l = 0;l < layers.Count && !cancelToken.Value;l++)
                     {
-                        var layer = layers[l];
+                        var lIdx  = (l+cachedLyrIdx) % layers.Count; // Try last layer/feature/triangle first.
+                        var layer = layers[lIdx];
                         float fx  = layer.Extent * oneOverRes;
-                        Vector2 p = new Vector2(fx*x+0.5f*fx, fx*y+0.5f*fx);
-
-                        // First try cache, quite often adjacent pixels will hit the same triangle.
-                        if (cachedVtxIdx!=-1)
-                        {
-                            var vertices = cachedPoly.vertices;
-                            var denoms   = cachedPoly.denoms;
-                            var mins     = cachedPoly.mins;
-                            var maxs     = cachedPoly.maxs;
-                            if (!(p.x < mins[cachedTriIdx].x || p.x > maxs[cachedTriIdx].x) &&
-                                !(p.y < mins[cachedTriIdx].y || p.y > maxs[cachedTriIdx].y))
-                            {
-                                hit = GeomUtil.PointIsInsideTriangle2( p, vertices[cachedVtxIdx], vertices[cachedVtxIdx+1], vertices[cachedVtxIdx+2], denoms[cachedTriIdx] );
-                                if (hit)
-                                {
-                                    texture[(resolution - y -1)*resolution+x] = cachedPixel;
-                                    break; // Pass from cache, continue to next pixel.
-                                }
-                            }
-                        }
+                        Vector2 p = new Vector2(fx*x+0.5f, fx*y+0.5f);
 
-                        // Must check all triangles, no cache or was no hit with cache.
                         for (int f = 0;f < layer.VectorTileFeatures.Count;f++)
                         {
-                            var feature = layer.VectorTileFeatures[f];
+                            var ftrIdx  = (f + cachedFtrIdx) % layer.VectorTileFeatures.Count;
+                            var feature = layer.VectorTileFeatures[ftrIdx];
 
                             if (feature.GeometryType != Tile.GeomType.Polygon)
                                 continue;
 
-                            var polygons = polygonLayers[l][f];
+                            var polygons = polygonLayers[lIdx][ftrIdx];
                             if (polygons.vertices.Count == 0)
                                 continue;
 
-                            cachedVtxIdx = -1;
-                            cachedPoly   = polygonLayers[l][f];
-                            var mins     = cachedPoly.mins;
-                            var maxs     = cachedPoly.maxs;
-                            var denoms   = cachedPoly.denoms;
-                            var vertices = cachedPoly.vertices;
-                            for (int vIdx = 0, triIdx = 0;vIdx < vertices.Count;vIdx += 3, triIdx++)
+                            var poly     = polygonLayers[lIdx][ftrIdx];
+                            var mins     = poly.mins;
+                            var maxs     = poly.maxs;
+                            var denoms   = poly.denoms;
+                            var vertices = poly.vertices;
+                            var triCount = vertices.Count/3;
+                            for (int t = 0; t < triCount;t++)
                             {
+                                int triIdx = (t+cachedTriIdx) % triCount;
                                 if (p.x < mins[triIdx].x || p.x > maxs[triIdx].x) continue;
                                 if (p.y < mins[triIdx].y || p.y > maxs[triIdx].y) continue;
-                                hit = GeomUtil.PointIsInsideTriangle2( p, vertices[vIdx], vertices[vIdx+1], vertices[vIdx+2], denoms[triIdx] );
+                                hit = GeomUtil.PointIsInsideTriangle2( p, vertices[triIdx*3], vertices[triIdx*3+1], vertices[triIdx*3+2], denoms[triIdx] );
                                 if (hit)
                                 {
                                     cachedTriIdx = triIdx;
-                                    cachedVtxIdx = vIdx;
-                                    cachedPixel  = (byte)feature.SelectedLayerIdx;
-                                    texture[(resolution - y -1)*resolution+x] = cachedPixel;
+                                    cachedLyrIdx = lIdx;
+                                    cachedFtrIdx = ftrIdx;
+                                    texture[(resolution - y -1)*resolution+x] = (byte)feature.SelectedLayerIdx;
                                     break;
                                 }
                             }
 
                             if (hit) break;
+
+                            cachedTriIdx = 0;
                         }
 
                         if (hit) break;
+
+                        cachedFtrIdx = 0;
                     }
 
                     if (!hit)
                     {
+                        cachedLyrIdx = 0;
                         texture[(resolution - y -1)*resolution+x] = 255;
                         failedPixels.Add( new Vector3Int( x, y, 255 ) );
                     }
@@ -309,7 +312,7 @@ namespace Wander
 
             // Determine number of different layers. For instance, if only layer 3, 8, 14 and 15 are used, we select
             // a material that only uses 4 textures and put 3 -> Albedo_0 -> 8 to Albedo_1, etc. in the shader.
-            cachedPixel = 255;
+            byte cachedPixel = 255;
             int remappedIndexCounter = -1;
             byte remappedPixel = 255;
             int addr = 0;
@@ -318,21 +321,24 @@ namespace Wander
                 for (int x = 0;x < resolution;x++)
                 {
                     byte pixel = texture[addr];
-                    if ( pixel != cachedPixel && pixel < 254  /*used for not matched layer*/ )
+                    if (pixel < 254)
                     {
-                        if (!remappedLayerIndices.TryGetValue( pixel, out remappedPixel ))
+                        if (pixel != cachedPixel)
                         {
-                            if (remappedIndexCounter < 253) // 254 is reserved for no layer match, 255 is ray hit with triangle.
+                            if (!remappedLayerIndices.TryGetValue( pixel, out remappedPixel ))
                             {
-                                remappedIndexCounter++;
-                                remappedPixel = (byte)remappedIndexCounter;
-                                remappedLayerIndices.Add( pixel, remappedPixel );
+                                if (remappedIndexCounter < 253) // 254 is reserved for no layer match, 255 is ray hit with triangle.
+                                {
+                                    remappedIndexCounter++;
+                                    remappedPixel = (byte)remappedIndexCounter;
+                                    remappedLayerIndices.Add( pixel, remappedPixel );
+                                }
+                                else remappedPixel = 0;
                             }
-                            else remappedPixel = 0;
+                            cachedPixel = pixel;
                         }
-                        cachedPixel = pixel;
-                    }
-                    texture[addr] = remappedPixel;
+                        texture[addr] = remappedPixel;
+                    } // leave unfound or unhit pixels on their original value.
                     addr++;
                 }
             }