diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Changelog for keid-geometry
 
+## 0.1.2.0
+
+- Changed `Quad.toVertices` to counter-clockwise winding to match new pipeline defaults.
+- Added a `Icosphere.generateIndexedCW` for generating objects with clockwise winding order.
+
 ## 0.1.1.3
 
 - Added `Neighbors.fromPoints` to generate the whole block from corners.
diff --git a/keid-geometry.cabal b/keid-geometry.cabal
--- a/keid-geometry.cabal
+++ b/keid-geometry.cabal
@@ -1,16 +1,16 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.35.1.
+-- This file has been generated from package.yaml by hpack version 0.38.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           keid-geometry
-version:        0.1.1.3
+version:        0.1.2.0
 synopsis:       Geometry primitives for Keid engine.
 category:       Game Engine
 author:         IC Rainbow
 maintainer:     keid@aenor.ru
-copyright:      2023 IC Rainbow
+copyright:      2025 IC Rainbow
 license:        BSD3
 license-file:   LICENSE
 build-type:     Simple
@@ -42,67 +42,36 @@
   default-extensions:
       NoImplicitPrelude
       ApplicativeDo
-      BangPatterns
       BinaryLiterals
       BlockArguments
-      ConstrainedClassMethods
-      ConstraintKinds
       DataKinds
       DefaultSignatures
-      DeriveDataTypeable
-      DeriveFunctor
-      DeriveGeneric
-      DeriveLift
-      DeriveTraversable
       DerivingStrategies
       DerivingVia
       DuplicateRecordFields
-      EmptyCase
-      EmptyDataDeriving
-      ExistentialQuantification
-      ExplicitForAll
-      FlexibleContexts
-      FlexibleInstances
       FunctionalDependencies
-      GADTs
-      GeneralizedNewtypeDeriving
       HexFloatLiterals
       ImportQualifiedPost
-      InstanceSigs
-      KindSignatures
       LambdaCase
-      LiberalTypeSynonyms
-      MultiParamTypeClasses
       NamedFieldPuns
-      NamedWildCards
       NumDecimals
-      NumericUnderscores
+      OverloadedRecordDot
       OverloadedStrings
       PatternSynonyms
-      PostfixOperators
-      QuantifiedConstraints
       QuasiQuotes
-      RankNTypes
       RecordWildCards
-      ScopedTypeVariables
-      StandaloneDeriving
-      StandaloneKindSignatures
       StrictData
       TemplateHaskell
-      TupleSections
-      TypeApplications
       TypeFamilies
       TypeOperators
-      TypeSynonymInstances
-      UnicodeSyntax
       ViewPatterns
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
   build-depends:
       base >=4.7 && <5
-    , geomancy
-    , keid-core >=0.1.6.1
+    , geomancy >=0.3.0.0
+    , keid-core >=0.1.11.0
     , mtl
     , rio >=0.1.12.0
     , vector
     , vulkan
-  default-language: Haskell2010
+  default-language: GHC2021
diff --git a/src/Geometry/Icosphere.hs b/src/Geometry/Icosphere.hs
--- a/src/Geometry/Icosphere.hs
+++ b/src/Geometry/Icosphere.hs
@@ -1,5 +1,6 @@
 module Geometry.Icosphere
   ( generateIndexed
+  , generateIndexedCW
 
   , icofaces
   , icopoints
@@ -19,6 +20,35 @@
 
 import Geometry.Face (Face(..))
 
+{- | Subdivide a D20 iteratively to get an indexed mesh.
+
+Normalize positions from the input to keep them on a unit sphere.
+
+The triangles would be placed in a counter-clockwise order.
+
+@
+(positions, attrs, indices) =
+  Icosphere.generateIndexed
+    3
+    mkInitialAttrs
+    mkMidpointAttrs
+    mkVertices
+  where
+    mkInitialAttrs :: Vec3 -> ()
+    mkInitialAttrs _pos = ()
+
+    mkMidpointAttrs :: Float -> Vec3 -> () -> () -> ()
+    mkMidpointAttrs _scale _midPos _attr1 _attr2 = ()
+
+    mkVertices points _faces = do
+      (rawPos, ()) <- points
+      let normPos = Vec3.normalize rawPos
+      pure
+        ( Vec3.Packed normPos
+        , Vec4.fromVec3 (normPos / 2 + 0.5) 1
+        )
+@
+-}
 generateIndexed
   :: ( Fractional scale
      , Storable pos
@@ -29,7 +59,35 @@
   -> "midpoint"      ::: (scale -> Vec3 -> pointAttr -> pointAttr -> pointAttr)
   -> "vertex"        ::: (Vector (Vec3, pointAttr) -> [Face Int] -> Vector (pos, vertexAttr))
   -> "model vectors" ::: (Storable.Vector pos, Storable.Vector vertexAttr, Storable.Vector Word32)
-generateIndexed details mkInitialAttrs mkMidpointAttrs mkVertices =
+generateIndexed = generateIndexedEx True
+
+-- | Like, `generateIndexed`, but the triangle winding order is clockwise.
+--
+-- The resulting object will appear inside-out unless the pipeline order is set to CLOCKWISE too.
+generateIndexedCW
+  :: ( Fractional scale
+     , Storable pos
+     , Storable vertexAttr
+     )
+  => "subdivisions"  ::: Natural
+  -> "initial"       ::: (Vec3 -> pointAttr)
+  -> "midpoint"      ::: (scale -> Vec3 -> pointAttr -> pointAttr -> pointAttr)
+  -> "vertex"        ::: (Vector (Vec3, pointAttr) -> [Face Int] -> Vector (pos, vertexAttr))
+  -> "model vectors" ::: (Storable.Vector pos, Storable.Vector vertexAttr, Storable.Vector Word32)
+generateIndexedCW = generateIndexedEx False
+
+generateIndexedEx
+  :: ( Fractional scale
+     , Storable pos
+     , Storable vertexAttr
+     )
+  => "clockwise"   ::: Bool
+  -> "subdivisions"  ::: Natural
+  -> "initial"       ::: (Vec3 -> pointAttr)
+  -> "midpoint"      ::: (scale -> Vec3 -> pointAttr -> pointAttr -> pointAttr)
+  -> "vertex"        ::: (Vector (Vec3, pointAttr) -> [Face Int] -> Vector (pos, vertexAttr))
+  -> "model vectors" ::: (Storable.Vector pos, Storable.Vector vertexAttr, Storable.Vector Word32)
+generateIndexedEx windingCCW details mkInitialAttrs mkMidpointAttrs mkVertices =
   ( Storable.convert pv
   , Storable.convert av
   , Storable.fromList iv
@@ -38,8 +96,8 @@
     (pv, av) = Vector.unzip $ mkVertices finalPoints faces
 
     iv = do
-      face <- faces
-      vert <- toList face
+      Face a b c <- faces
+      vert <- if windingCCW then [c, b, a] else [a, b, c]
       pure $ fromIntegral vert
 
     (faces, (_midpoints, finalPoints, _finalPointsCount)) =
diff --git a/src/Geometry/Quad.hs b/src/Geometry/Quad.hs
--- a/src/Geometry/Quad.hs
+++ b/src/Geometry/Quad.hs
@@ -32,11 +32,11 @@
   deriving (Eq, Ord, Show, Functor, Foldable, Traversable, Generic1)
   deriving Applicative via Generically1 Quad
 
--- | 2 clockwise ordered triangles
+-- | 2 counter-clockwise ordered triangles
 toVertices :: Quad (Vertex pos attrs) -> [Vertex pos attrs]
 toVertices Quad{..} =
-  [ quadLT, quadRT, quadLB
-  , quadLB, quadRT, quadRB
+  [ quadLB, quadRT, quadLT
+  , quadRB, quadRT, quadLB
   ]
 
 toVertices2 :: Quad (Vertex pos attrs) -> [Vertex pos attrs]
@@ -47,8 +47,8 @@
 {-# SPECIALIZE indicesQuad :: [Word32] #-}
 indicesQuad :: Num a => [a]
 indicesQuad =
-  [ quadLT, quadRT, quadLB
-  , quadLB, quadRT, quadRB
+  [ quadLB, quadRT, quadLT
+  , quadRB, quadRT, quadLB
   ]
   where
     Quad{..} = indices
