packages feed

mischief-render-0.1.0.0: src/Mischief/Shader/Types.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}

module Mischief.Shader.Types where

import Data.Data
import Data.List
import Data.Singletons (SingI)
import Data.Text qualified as T
import Data.Type.Ord (type (>=))
import GHC.Records (HasField (getField))
import GHC.TypeLits
import Mischief.Shader.Internal.Singletons
import Mischief.Shader.Internal.State
import Prelude (Bool (..), Char, Maybe (Just, Nothing), Show (show), String, undefined, ($), type (~))
import Prelude qualified

float :: Prelude.Float -> Float
float = ConstantFloat

int :: Prelude.Int -> Int
int = ConstantInt

uint :: Prelude.Int -> Uint
uint = ConstantUInt

f32 :: Prelude.Float -> Float
f32 = float

i32 :: Prelude.Int -> Int
i32 = int

u32 :: Prelude.Int -> Uint
u32 = uint

vec2 :: forall a. (Expr (Primitive (DesugarPrimitiveExpr a)) ~ a, SingI (DesugarPrimitiveExpr a), PrintVecElements 2 (DesugarPrimitiveExpr a)) => Expr (Primitive (DesugarPrimitiveExpr a)) -> Expr (Primitive (DesugarPrimitiveExpr a)) -> Vec 2 a
vec2 a b = ConstantVec Proxy (a, b)

vec3 :: forall a. (Expr (Primitive (DesugarPrimitiveExpr a)) ~ a, SingI (DesugarPrimitiveExpr a), PrintVecElements 3 (DesugarPrimitiveExpr a)) => Expr (Primitive (DesugarPrimitiveExpr a)) -> Expr (Primitive (DesugarPrimitiveExpr a)) -> Expr (Primitive (DesugarPrimitiveExpr a)) -> Vec 3 a
vec3 a b c = ConstantVec Proxy (a, b, c)

vec4 :: forall a. (Expr (Primitive (DesugarPrimitiveExpr a)) ~ a, SingI (DesugarPrimitiveExpr a), PrintVecElements 4 (DesugarPrimitiveExpr a)) => Expr (Primitive (DesugarPrimitiveExpr a)) -> Expr (Primitive (DesugarPrimitiveExpr a)) -> Expr (Primitive (DesugarPrimitiveExpr a)) -> Expr (Primitive (DesugarPrimitiveExpr a)) -> Vec 4 a
vec4 a b c d = ConstantVec Proxy (a, b, c, d)

(+:) :: (SingI a, PrintVecElements (n + 1) a, KnownNat (n + 1)) => Expr (VectorType n a) -> Expr (Primitive a) -> Expr (VectorType (n + 1) a)
(+:) = ExtendVec Proxy

(<>) :: (SingI a, PrintVecElements (n + m) a, KnownNat (n + m)) => Expr (VectorType n a) -> Expr (VectorType m a) -> Expr (VectorType (n + m) a)
(<>) = AppendVecs Proxy

array :: forall a. (SingI (DesugarExpr a)) => [Expr (DesugarExpr a)] -> Array a
array = ConstantArray (Proxy @(DesugarExpr a))

(!!) :: (SingI a) => Array (Expr a) -> Uint -> Expr a
(!!) = Index

type Boolean = Expr TBool

type Int = Expr (Primitive TInt)

type Float = Expr (Primitive TFloat)

type Uint = Expr (Primitive TUInt)

type family DesugarExpr a where
  DesugarExpr (Expr a) = a

type family DesugarPrimitiveExpr a where
  DesugarPrimitiveExpr Int = TInt
  DesugarPrimitiveExpr Float = TFloat
  DesugarPrimitiveExpr Uint = TUInt

type Array b = Expr (ArrayType (DesugarExpr b))

type Vec n a = Expr (VectorType n (DesugarPrimitiveExpr a))

type Vec2 a = Vec 2 a

type Vec3 a = Vec 3 a

type Vec4 a = Vec 4 a

type Mat n m = Expr (MatrixType n m)

mat :: forall n m. (KnownNat n, KnownNat m, PrintMatElements n m) => MatInit n m -> Mat n m
mat = ConstantMat (Proxy @(MatrixType n m))

class (SingI b, SingI a) => Cast b a where
  cast :: Expr a -> Expr b

instance (SingI (Primitive a), SingI (Primitive b)) => Cast (Primitive a) (Primitive b) where
  cast = Cast (Proxy @(Primitive a))

instance (SingI (VectorType n a), SingI (VectorType n b)) => Cast (VectorType n a) (VectorType n b) where
  cast = CastVec (Proxy @(VectorType n a))

type family Fractional a where
  Fractional Float = True
  Fractional (Expr (VectorType n a)) = Fractional (Expr (Primitive a))
  Fractional a = False

type family Algebric (a :: Types) where
  Algebric (Primitive a) = True
  Algebric (VectorType n a) = True
  Algebric a = False

type family Integral (a :: Types) where
  Integral (Primitive TInt) = True
  Integral (Primitive TUInt) = True
  Integral (VectorType n TInt) = True
  Integral (VectorType n TUInt) = True
  Integral a = False

diag :: forall n a. (n <= 4, KnownNat n, SingI a) => Expr (Primitive a) -> Expr (VectorType n a)
diag a = case eqT @2 @n of
  Just Refl -> ConstantVec (Proxy @(VectorType 2 a)) (a, a)
  Nothing -> case eqT @3 @n of
    Just Refl -> ConstantVec (Proxy @(VectorType 3 a)) (a, a, a)
    Nothing -> case eqT @4 @n of
      Just Refl -> ConstantVec (Proxy @(VectorType 4 a)) (a, a, a, a)
      Nothing -> undefined

type family SwizzleChar c n where
  SwizzleChar 'x' 1 = True
  SwizzleChar 'r' 1 = True
  SwizzleChar 'y' 2 = True
  SwizzleChar 'g' 2 = True
  SwizzleChar 'z' 3 = True
  SwizzleChar 'b' 3 = True
  SwizzleChar 'w' 4 = True
  SwizzleChar 'a' 4 = True
  SwizzleChar c 1 = False
  SwizzleChar c n = SwizzleChar c (n - 1)

type family Swizzle (s :: Symbol) (n :: Nat) :: Maybe Nat where
  Swizzle "" n = Just 0
  Swizzle s n = SwizzleRec (UnconsSymbol s) n

type family SwizzleRec (s :: Maybe (Char, Symbol)) (n :: Nat) :: Maybe Nat where
  SwizzleRec (Just '(c, s)) n = SwizzleRec' s n (SwizzleChar c n)
  SwizzleRec s n = Nothing

type family SwizzleRec' s n b where
  SwizzleRec' s n True = IncMaybe (Swizzle s n)
  SwizzleRec' s n b = Nothing

type family IncMaybe (n :: Maybe Nat) :: Maybe Nat where
  IncMaybe (Just n) = Just (n + 1)
  IncMaybe Nothing = Nothing

type family SwizzleOutput (a :: PrimitiveTypes) (n :: Nat) where
  SwizzleOutput a 1 = Primitive a
  SwizzleOutput a n = VectorType n a

instance (KnownSymbol s, KnownNat n, SingI a, Swizzle s n ~ Just m, m >= 1, m <= 4, SwizzleOutput a m ~ out) => HasField s (Expr (VectorType n a)) (Expr out) where
  getField v = AccessField v (T.pack $ map m $ symbolVal $ Proxy @s)
    where
      m 'r' = 'x'
      m 'g' = 'y'
      m 'b' = 'z'
      m 'a' = 'w'
      m a = a