module Mischief.Render.Plugin where

import Control.Monad
import Control.Monad.IO.Class
import Data.Data (Proxy (..))
import Data.Default
import Data.Foldable (for_)
import Data.Text qualified as T
import Data.Traversable
import Foreign (Storable (peek), free, malloc, nullPtr, with)
import Foreign.C.ConstPtr (ConstPtr (..))
import GHC.Generics
import Linear (V3 (..))
import Mischief.Assets.Asset (store)
import Mischief.ECS hiding (get, set)
import Mischief.ECS.Relationships.Order (Before (..))
import Mischief.ECS.Systems qualified as Systems
import Mischief.ECS.World.Query (queryOne)
import Mischief.Materials qualified as Mat
import Mischief.Materials.Sprite (SpriteMaterial)
import Mischief.Math (TransformPlugin)
import Mischief.Render.Bind
import Mischief.Render.Buffer
import Mischief.Render.Camera
import Mischief.Render.Core
import Mischief.Render.Material qualified as Material
import Mischief.Render.Material.Definition
import Mischief.Render.Material.Pipeline (qgetPipeline)
import Mischief.Render.Sprite (SpritePlugin (..), fetchSpriteBindings)
import Mischief.Render.Texture
import Mischief.Render.Texture qualified as Texture
import Mischief.Render.Time (TimeMaterialPlugin)
import Mischief.SDL (SDLPlugin (..))
import Mischief.SDL.Window
import Mischief.Shader (Bindable, Binding, BuiltIn, GPU, Location, Shader, ShaderParam, sample, var)
import Mischief.Shader.Internal.Bindings hiding (Bindings)
import Mischief.Shader.Types qualified as ST
import Mischief.WGPU
import Mischief.WGPU.Types.Enums
import Mischief.WGPU.Types.General

data RenderPlugin = RenderPlugin deriving (RenderPlugin -> RenderPlugin -> Bool
(RenderPlugin -> RenderPlugin -> Bool)
-> (RenderPlugin -> RenderPlugin -> Bool) -> Eq RenderPlugin
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RenderPlugin -> RenderPlugin -> Bool
== :: RenderPlugin -> RenderPlugin -> Bool
$c/= :: RenderPlugin -> RenderPlugin -> Bool
/= :: RenderPlugin -> RenderPlugin -> Bool
Eq)

instance Plugin RenderPlugin where
  init :: System ()
init = do
    first <- forall sch. Schedule sch => System Entity
forall {k} (sch :: k). Schedule sch => System Entity
scheduleEntity @RenderFirst
    prepare <- scheduleEntity @RenderPrepare
    update <- scheduleEntity @RenderUpdate
    transparent <- scheduleEntity @RenderTransparent
    postprocess <- scheduleEntity @RenderPostprocess
    last <- scheduleEntity @RenderLast

    update' <- scheduleEntity @PostUpdate

    insert (Rel Before first) update'
    insert (Rel Before prepare) first
    insert (Rel Before update) prepare
    insert (Rel Before transparent) update
    insert (Rel Before postprocess) transparent
    insert (Rel Before last) postprocess

    for_ [first, update, prepare, transparent, postprocess, last] $ insert UpdateSchedule

    insertRes =<< liftIO (RenderInstance <$> wgpuCreateInstance)
    void $ spawn $ Observer onAddWindow
    void $ spawn $ Observer onSetWindowSize

    systems renderCameras
      & schedule @RenderLast

    systems clearCameras
      & schedule @RenderFirst

  deps :: [Dependency]
deps = [forall p. Plugin p => Dependency
dep @SDLPlugin, forall p. Plugin p => Dependency
dep @SpritePlugin, forall p. Plugin p => Dependency
dep @CameraPlugin, forall p. Plugin p => Dependency
dep @TimeMaterialPlugin, forall p. Plugin p => Dependency
dep @TransformPlugin]

-- TODO: refactor this to use the query monad
renderCameras :: System ()
renderCameras :: System ()
renderCameras = do
  resources <- System (Maybe (RenderAdapter, RenderDevice, RenderQueue))
getRenderingResources
  case resources of
    Maybe (RenderAdapter, RenderDevice, RenderQueue)
Nothing -> () -> System ()
forall a. a -> System a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    Just (RenderAdapter
adapter, RenderDevice
device, RenderQueue
queue) -> do
      cameras <- Query System (CameraTexture, From RenderSurface)
-> System [(CameraTexture, From RenderSurface)]
forall w (m :: * -> *) out.
MonadSystem w m =>
Query m out -> m [out]
query [q|CameraTexture, OutputTo -> (RenderSurface)|]
      for_ cameras $ \(CameraTexture SwappableTexture {currentTexture :: SwappableTexture -> Ptr WGPUTexture
currentTexture = Ptr WGPUTexture
texture}, From Entity
_ RenderSurface
surface) -> do
        format <- RenderSurface -> RenderAdapter -> System TextureFormat
getFormat RenderSurface
surface RenderAdapter
adapter
        withSurfaceTexture surface (def {Texture.format}) $ \Texture
output -> do
          sampler <- RenderDevice -> System Sampler
newSampler RenderDevice
device
          tex <- liftIO $ wgpuTextureCreateView texture (ConstPtr nullPtr)
          let command = [ErasedBindingValue] -> Nat -> DrawCommand Bindings
forall {k} (bindings :: k).
[ErasedBindingValue] -> Nat -> DrawCommand bindings
Draw [Bindings CPU -> ErasedBindingValue
forall (b :: * -> *).
(Bindable b, Typeable b) =>
b CPU -> ErasedBindingValue
ErasedBindingValue Bindings {tex :: Binding CPU Texture
tex = Ptr WGPUTextureView -> TextureView
TextureView Ptr WGPUTextureView
tex, Sampler
Binding CPU Sampler
sampler :: Sampler
sampler :: Binding CPU Sampler
sampler}] Nat
3
          Just pipeline <- queryOne $ qgetPipeline @DummyFullscreenMaterial format
          render @DummyFullscreenMaterial device queue pipeline def output [command]
          presentSurface surface

clearCameras :: System ()
clearCameras :: System ()
clearCameras = Query System () -> System ()
forall w (m :: * -> *) out. MonadSystem w m => Query m out -> m ()
query_ (Query System () -> System ()) -> Query System () -> System ()
forall a b. (a -> b) -> a -> b
$ do
  device <- Query System RenderDevice
forall c (m :: * -> *) w.
(MonadSystem w m, Component c) =>
Query m c
qres
  queue <- qres
  (CameraTexture SwappableTexture {currentTexture = texture, desc}) <- [q|CameraTexture|]
  pipeline <- qgetPipeline @DummyFullscreenMaterial desc.format
  qlift $ render @ClearMaterial device queue pipeline def {clear = Clear $ V3 0.184313725 0.211764706 0.250980392} (Texture texture desc) []

withSurfaceTexture :: RenderSurface -> TextureDescriptor -> (Texture -> System a) -> System ()
withSurfaceTexture :: forall a.
RenderSurface
-> TextureDescriptor -> (Texture -> System a) -> System ()
withSurfaceTexture (RenderSurface Ptr WGPUSurface
surface) TextureDescriptor
desc Texture -> System a
f = do
  surfaceTextureBox <- IO (Ptr WGPUSurfaceTexture) -> System (Ptr WGPUSurfaceTexture)
forall a. IO a -> System a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (Ptr WGPUSurfaceTexture)
forall a. Storable a => IO (Ptr a)
malloc
  liftIO $ wgpuSurfaceGetCurrentTexture surface surfaceTextureBox
  surfaceTexture <- liftIO $ peek surfaceTextureBox

  unless (surfaceTexture.texture == nullPtr) $ void $ f (Texture {texture = surfaceTexture.texture, desc})

  liftIO $ free surfaceTextureBox

presentSurface :: RenderSurface -> System ()
presentSurface :: RenderSurface -> System ()
presentSurface (RenderSurface Ptr WGPUSurface
surface) = IO () -> System ()
forall a. IO a -> System a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> System ()) -> IO () -> System ()
forall a b. (a -> b) -> a -> b
$ Ptr WGPUSurface -> IO ()
wgpuSurfacePresent Ptr WGPUSurface
surface

data Bindings f = Bindings
  { forall f. Bindings f -> Binding f Texture
tex :: Binding f Texture,
    forall f. Bindings f -> Binding f Sampler
sampler :: Binding f Sampler
  }
  deriving ((forall x. Bindings f -> Rep (Bindings f) x)
-> (forall x. Rep (Bindings f) x -> Bindings f)
-> Generic (Bindings f)
forall x. Rep (Bindings f) x -> Bindings f
forall x. Bindings f -> Rep (Bindings f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall f x. Rep (Bindings f) x -> Bindings f
forall f x. Bindings f -> Rep (Bindings f) x
$cfrom :: forall f x. Bindings f -> Rep (Bindings f) x
from :: forall x. Bindings f -> Rep (Bindings f) x
$cto :: forall f x. Rep (Bindings f) x -> Bindings f
to :: forall x. Rep (Bindings f) x -> Bindings f
Generic, Typeable Bindings
Typeable Bindings =>
(Nat -> Proxy (Bindings Internal) -> (Bindings, Nat))
-> (Nat
    -> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat))
-> (Nat -> Bindings CPU -> ([WGPUBindGroupEntry], Nat))
-> (Nat -> (Bindings GPU, Nat))
-> Bindable Bindings
Nat -> (Bindings GPU, Nat)
Nat
-> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat)
Nat -> Proxy (Bindings Internal) -> (Bindings, Nat)
Nat -> Bindings CPU -> ([WGPUBindGroupEntry], Nat)
forall (a :: * -> *).
Typeable a =>
(Nat -> Proxy (a Internal) -> (Bindings, Nat))
-> (Nat -> Proxy (a Internal) -> ([WGPUBindGroupLayoutEntry], Nat))
-> (Nat -> a CPU -> ([WGPUBindGroupEntry], Nat))
-> (Nat -> (a GPU, Nat))
-> Bindable a
$ccollectBindings :: Nat -> Proxy (Bindings Internal) -> (Bindings, Nat)
collectBindings :: Nat -> Proxy (Bindings Internal) -> (Bindings, Nat)
$ccollectLayouts :: Nat
-> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat)
collectLayouts :: Nat
-> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat)
$ccollectEntries :: Nat -> Bindings CPU -> ([WGPUBindGroupEntry], Nat)
collectEntries :: Nat -> Bindings CPU -> ([WGPUBindGroupEntry], Nat)
$cdummyBinding :: Nat -> (Bindings GPU, Nat)
dummyBinding :: Nat -> (Bindings GPU, Nat)
Bindable)

newtype VertexInput f = VertexInput (BuiltIn f "vertex_index" Mat.Uint)
  deriving stock ((forall x. VertexInput f -> Rep (VertexInput f) x)
-> (forall x. Rep (VertexInput f) x -> VertexInput f)
-> Generic (VertexInput f)
forall x. Rep (VertexInput f) x -> VertexInput f
forall x. VertexInput f -> Rep (VertexInput f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall f x. Rep (VertexInput f) x -> VertexInput f
forall f x. VertexInput f -> Rep (VertexInput f) x
$cfrom :: forall f x. VertexInput f -> Rep (VertexInput f) x
from :: forall x. VertexInput f -> Rep (VertexInput f) x
$cto :: forall f x. Rep (VertexInput f) x -> VertexInput f
to :: forall x. Rep (VertexInput f) x -> VertexInput f
Generic)
  deriving anyclass (Typeable (VertexInput GPU)
Params
ParamDefinition
VertexInput GPU
Typeable (VertexInput GPU) =>
Params
-> ParamDefinition
-> VertexInput GPU
-> (VertexInput GPU -> Values)
-> ShaderParam VertexInput
VertexInput GPU -> Values
forall (a :: * -> *).
Typeable (a GPU) =>
Params
-> ParamDefinition -> a GPU -> (a GPU -> Values) -> ShaderParam a
$ccollectParams :: Params
collectParams :: Params
$cparamDefinition :: ParamDefinition
paramDefinition :: ParamDefinition
$cdummyParam :: VertexInput GPU
dummyParam :: VertexInput GPU
$ccollectValues :: VertexInput GPU -> Values
collectValues :: VertexInput GPU -> Values
Mat.ShaderParam)

data VertexOutput f = VertexOutput
  { forall f. VertexOutput f -> BuiltIn f "position" (Vec 4 Float)
pos :: Mat.BuiltIn f "position" (Mat.Vec 4 Mat.Float),
    forall f. VertexOutput f -> Location f 0 (Vec 2 Float)
uv :: Mat.Location f 0 (Mat.Vec 2 Mat.Float)
  }
  deriving ((forall x. VertexOutput f -> Rep (VertexOutput f) x)
-> (forall x. Rep (VertexOutput f) x -> VertexOutput f)
-> Generic (VertexOutput f)
forall x. Rep (VertexOutput f) x -> VertexOutput f
forall x. VertexOutput f -> Rep (VertexOutput f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall f x. Rep (VertexOutput f) x -> VertexOutput f
forall f x. VertexOutput f -> Rep (VertexOutput f) x
$cfrom :: forall f x. VertexOutput f -> Rep (VertexOutput f) x
from :: forall x. VertexOutput f -> Rep (VertexOutput f) x
$cto :: forall f x. Rep (VertexOutput f) x -> VertexOutput f
to :: forall x. Rep (VertexOutput f) x -> VertexOutput f
Generic, Typeable (VertexOutput GPU)
Params
ParamDefinition
VertexOutput GPU
Typeable (VertexOutput GPU) =>
Params
-> ParamDefinition
-> VertexOutput GPU
-> (VertexOutput GPU -> Values)
-> ShaderParam VertexOutput
VertexOutput GPU -> Values
forall (a :: * -> *).
Typeable (a GPU) =>
Params
-> ParamDefinition -> a GPU -> (a GPU -> Values) -> ShaderParam a
$ccollectParams :: Params
collectParams :: Params
$cparamDefinition :: ParamDefinition
paramDefinition :: ParamDefinition
$cdummyParam :: VertexOutput GPU
dummyParam :: VertexOutput GPU
$ccollectValues :: VertexOutput GPU -> Values
collectValues :: VertexOutput GPU -> Values
Mat.ShaderParam)

-- | Material for rendering something to the whole screen.
data DummyFullscreenMaterial

instance Material DummyFullscreenMaterial where
  type VI DummyFullscreenMaterial = VertexInput
  type VO DummyFullscreenMaterial = VertexOutput
  type B DummyFullscreenMaterial = Bindings

  vertex :: VertexInput GPU -> Shader DummyFullscreenMaterial (VertexOutput GPU)
  vertex :: VertexInput GPU
-> Shader DummyFullscreenMaterial (VertexOutput GPU)
vertex = Shader NoMaterial (VertexOutput GPU)
-> Shader DummyFullscreenMaterial (VertexOutput GPU)
forall a b c. ExtensionOf b a => Shader a c -> Shader b c
liftExt (Shader NoMaterial (VertexOutput GPU)
 -> Shader DummyFullscreenMaterial (VertexOutput GPU))
-> (VertexInput GPU -> Shader NoMaterial (VertexOutput GPU))
-> VertexInput GPU
-> Shader DummyFullscreenMaterial (VertexOutput GPU)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VertexInput GPU -> Shader NoMaterial (VertexOutput GPU)
vertexShader

  fragment :: VertexOutput GPU -> Shader DummyFullscreenMaterial (Mat.Vec 4 Mat.Float)
  fragment :: VertexOutput GPU -> Shader DummyFullscreenMaterial (Vec 4 Float)
fragment VertexOutput GPU
input = do
    b <- Shader DummyFullscreenMaterial (B DummyFullscreenMaterial GPU)
Shader DummyFullscreenMaterial (Bindings GPU)
forall a. Material a => Shader a (B a GPU)
Mat.bindings
    pure $ Mat.sample b.tex b.sampler input.uv

data ClearMaterial

data NoBindings f = NoBindings deriving ((forall x. NoBindings f -> Rep (NoBindings f) x)
-> (forall x. Rep (NoBindings f) x -> NoBindings f)
-> Generic (NoBindings f)
forall x. Rep (NoBindings f) x -> NoBindings f
forall x. NoBindings f -> Rep (NoBindings f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall k (f :: k) x. Rep (NoBindings f) x -> NoBindings f
forall k (f :: k) x. NoBindings f -> Rep (NoBindings f) x
$cfrom :: forall k (f :: k) x. NoBindings f -> Rep (NoBindings f) x
from :: forall x. NoBindings f -> Rep (NoBindings f) x
$cto :: forall k (f :: k) x. Rep (NoBindings f) x -> NoBindings f
to :: forall x. Rep (NoBindings f) x -> NoBindings f
Generic, Typeable NoBindings
Typeable NoBindings =>
(Nat -> Proxy (NoBindings Internal) -> (Bindings, Nat))
-> (Nat
    -> Proxy (NoBindings Internal)
    -> ([WGPUBindGroupLayoutEntry], Nat))
-> (Nat -> NoBindings CPU -> ([WGPUBindGroupEntry], Nat))
-> (Nat -> (NoBindings GPU, Nat))
-> Bindable NoBindings
Nat -> (NoBindings GPU, Nat)
Nat
-> Proxy (NoBindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat)
Nat -> Proxy (NoBindings Internal) -> (Bindings, Nat)
Nat -> NoBindings CPU -> ([WGPUBindGroupEntry], Nat)
forall (a :: * -> *).
Typeable a =>
(Nat -> Proxy (a Internal) -> (Bindings, Nat))
-> (Nat -> Proxy (a Internal) -> ([WGPUBindGroupLayoutEntry], Nat))
-> (Nat -> a CPU -> ([WGPUBindGroupEntry], Nat))
-> (Nat -> (a GPU, Nat))
-> Bindable a
$ccollectBindings :: Nat -> Proxy (NoBindings Internal) -> (Bindings, Nat)
collectBindings :: Nat -> Proxy (NoBindings Internal) -> (Bindings, Nat)
$ccollectLayouts :: Nat
-> Proxy (NoBindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat)
collectLayouts :: Nat
-> Proxy (NoBindings Internal) -> ([WGPUBindGroupLayoutEntry], Nat)
$ccollectEntries :: Nat -> NoBindings CPU -> ([WGPUBindGroupEntry], Nat)
collectEntries :: Nat -> NoBindings CPU -> ([WGPUBindGroupEntry], Nat)
$cdummyBinding :: Nat -> (NoBindings GPU, Nat)
dummyBinding :: Nat -> (NoBindings GPU, Nat)
Bindable)

instance Material ClearMaterial where
  type VI ClearMaterial = VertexInput
  type VO ClearMaterial = VertexOutput
  type B ClearMaterial = NoBindings
  vertex :: VI ClearMaterial GPU -> Shader ClearMaterial (VO ClearMaterial GPU)
vertex = Shader NoMaterial (VertexOutput GPU)
-> Shader ClearMaterial (VertexOutput GPU)
forall a b c. ExtensionOf b a => Shader a c -> Shader b c
liftExt (Shader NoMaterial (VertexOutput GPU)
 -> Shader ClearMaterial (VertexOutput GPU))
-> (VertexInput GPU -> Shader NoMaterial (VertexOutput GPU))
-> VertexInput GPU
-> Shader ClearMaterial (VertexOutput GPU)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VertexInput GPU -> Shader NoMaterial (VertexOutput GPU)
vertexShader

  fragment :: VO ClearMaterial GPU -> Shader ClearMaterial (Vec 4 Float)
fragment VO ClearMaterial GPU
_ = Vec 4 Float -> Shader ClearMaterial (Vec 4 Float)
forall a. a -> Shader ClearMaterial a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Vec 4 Float -> Shader ClearMaterial (Vec 4 Float))
-> Vec 4 Float -> Shader ClearMaterial (Vec 4 Float)
forall a b. (a -> b) -> a -> b
$ Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Vec 4 Float
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
Mat.vec4 Float
Expr ('Primitive (DesugarPrimitiveExpr Float))
0 Float
Expr ('Primitive (DesugarPrimitiveExpr Float))
0 Float
Expr ('Primitive (DesugarPrimitiveExpr Float))
0 Float
Expr ('Primitive (DesugarPrimitiveExpr Float))
0

vertexShader :: VertexInput GPU -> Shader NoMaterial (VertexOutput GPU)
vertexShader :: VertexInput GPU -> Shader NoMaterial (VertexOutput GPU)
vertexShader (VertexInput BuiltIn GPU "vertex_index" (Expr ('Primitive 'TUInt))
index) = do
  positions <- Expr ('ArrayType (DesugarExpr (Vec 2 Float)))
-> Shader
     NoMaterial (Expr ('ArrayType (DesugarExpr (Vec 2 Float))))
forall {k} (a :: Types) (m :: k).
SingI a =>
Expr a -> Shader m (Expr a)
Mat.var (Expr ('ArrayType (DesugarExpr (Vec 2 Float)))
 -> Shader
      NoMaterial (Expr ('ArrayType (DesugarExpr (Vec 2 Float)))))
-> Expr ('ArrayType (DesugarExpr (Vec 2 Float)))
-> Shader
     NoMaterial (Expr ('ArrayType (DesugarExpr (Vec 2 Float))))
forall a b. (a -> b) -> a -> b
$ forall a.
SingI (DesugarExpr a) =>
[Expr (DesugarExpr a)] -> Array a
Mat.array @(Mat.Vec 2 Mat.Float) [Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Expr ('Primitive (DesugarPrimitiveExpr Float)) -> Vec 2 Float
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
Mat.vec2 (-Float
1) (-Float
1), Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Expr ('Primitive (DesugarPrimitiveExpr Float)) -> Vec 2 Float
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
Mat.vec2 Float
Expr ('Primitive (DesugarPrimitiveExpr Float))
3 (-Float
1), Expr ('Primitive (DesugarPrimitiveExpr Float))
-> Expr ('Primitive (DesugarPrimitiveExpr Float)) -> Vec 2 Float
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
Mat.vec2 (-Float
1) Float
Expr ('Primitive (DesugarPrimitiveExpr Float))
3]
  let pos = Expr ('ArrayType (DesugarExpr (Expr ('VectorType 2 'TFloat))))
Expr ('ArrayType (DesugarExpr (Vec 2 Float)))
positions Expr ('ArrayType (DesugarExpr (Expr ('VectorType 2 'TFloat))))
-> Expr ('Primitive 'TUInt) -> Expr ('VectorType 2 'TFloat)
forall (a :: Types).
SingI a =>
Array (Expr a) -> Expr ('Primitive 'TUInt) -> Expr a
Mat.!! Expr ('Primitive 'TUInt)
BuiltIn GPU "vertex_index" (Expr ('Primitive 'TUInt))
index
  pure $
    VertexOutput
      { pos = Mat.vec4 pos.x pos.y 0 1,
        uv = Mat.vec2 (pos.x Mat.* 0.5 + 0.5) (1.0 Mat.- (pos.y Mat.* 0.5 Mat.+ 0.5))
      }