module Mischief.Materials.Sprite where import Mischief.Materials import Mischief.Materials.Time (TimeMaterial, getTime) import Mischief.Render.Camera (CameraMatrices (CameraMatrices), Matrices (..)) import Mischief.Render.Core (DefaultSampler (..)) import Mischief.Render.Image import Mischief.Render.Sprite.Common import Prelude () data SpriteData f = SpriteData { forall f. SpriteData f -> Field f (Vec 3 (Expr ('Primitive 'TFloat))) coords :: Field f (Vec 3 Float), forall f. SpriteData f -> Field f (Vec 2 (Expr ('Primitive 'TFloat))) size :: Field f (Vec 2 Float), forall f. SpriteData f -> Field f (Vec 4 (Expr ('Primitive 'TFloat))) slice :: Field f (Vec 4 Float), forall f. SpriteData f -> Field f (Vec 2 Int) flip :: Field f (Vec 2 Int), forall f. SpriteData f -> Field f (Mat 3 3) rotation :: Field f (Mat 3 3) } deriving stock ((forall x. SpriteData f -> Rep (SpriteData f) x) -> (forall x. Rep (SpriteData f) x -> SpriteData f) -> Generic (SpriteData f) forall x. Rep (SpriteData f) x -> SpriteData f forall x. SpriteData f -> Rep (SpriteData f) x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall f x. Rep (SpriteData f) x -> SpriteData f forall f x. SpriteData f -> Rep (SpriteData f) x $cfrom :: forall f x. SpriteData f -> Rep (SpriteData f) x from :: forall x. SpriteData f -> Rep (SpriteData f) x $cto :: forall f x. Rep (SpriteData f) x -> SpriteData f to :: forall x. Rep (SpriteData f) x -> SpriteData f Generic) deriving anyclass (Int [(Text, Text)] Integer -> SpriteData GPU SpriteData CPU -> Ptr Word8 -> IO Int (Integer -> SpriteData GPU) -> [(Text, Text)] -> Int -> (SpriteData CPU -> Ptr Word8 -> IO Int) -> Bufferable SpriteData forall (a :: * -> *). (Integer -> a GPU) -> [(Text, Text)] -> Int -> (a CPU -> Ptr Word8 -> IO Int) -> Bufferable a $cdummyBuffer :: Integer -> SpriteData GPU dummyBuffer :: Integer -> SpriteData GPU $cgetFields :: [(Text, Text)] getFields :: [(Text, Text)] $cgetSize :: Int getSize :: Int $cputBytes :: SpriteData CPU -> Ptr Word8 -> IO Int putBytes :: SpriteData CPU -> Ptr Word8 -> IO Int Bufferable) newtype VertexInput f = VertexInput (BuiltIn f "vertex_index" 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 ShaderParam) data VertexOutput f = VertexOutput { forall f. VertexOutput f -> BuiltIn f "position" (Vec 4 (Expr ('Primitive 'TFloat))) pos :: BuiltIn f "position" (Vec 4 Float), forall f. VertexOutput f -> Location f 0 (Vec 2 (Expr ('Primitive 'TFloat))) uv :: Location f 0 (Vec 2 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 ShaderParam) data Bindings f = Bindings { forall f. Bindings f -> Uniform f (Matrices f) matrices :: Uniform f (Matrices f), forall f. Bindings f -> Uniform f (SpriteData f) sprite :: Uniform f (SpriteData f), forall f. Bindings f -> Binding f Texture texture :: 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 => (Natural -> Proxy (Bindings Internal) -> (Bindings, Natural)) -> (Natural -> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural)) -> (Natural -> Bindings CPU -> ([WGPUBindGroupEntry], Natural)) -> (Natural -> (Bindings GPU, Natural)) -> Bindable Bindings Natural -> (Bindings GPU, Natural) Natural -> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural) Natural -> Proxy (Bindings Internal) -> (Bindings, Natural) Natural -> Bindings CPU -> ([WGPUBindGroupEntry], Natural) forall (a :: * -> *). Typeable a => (Natural -> Proxy (a Internal) -> (Bindings, Natural)) -> (Natural -> Proxy (a Internal) -> ([WGPUBindGroupLayoutEntry], Natural)) -> (Natural -> a CPU -> ([WGPUBindGroupEntry], Natural)) -> (Natural -> (a GPU, Natural)) -> Bindable a $ccollectBindings :: Natural -> Proxy (Bindings Internal) -> (Bindings, Natural) collectBindings :: Natural -> Proxy (Bindings Internal) -> (Bindings, Natural) $ccollectLayouts :: Natural -> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural) collectLayouts :: Natural -> Proxy (Bindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural) $ccollectEntries :: Natural -> Bindings CPU -> ([WGPUBindGroupEntry], Natural) collectEntries :: Natural -> Bindings CPU -> ([WGPUBindGroupEntry], Natural) $cdummyBinding :: Natural -> (Bindings GPU, Natural) dummyBinding :: Natural -> (Bindings GPU, Natural) Bindable) data SpriteMaterial instance Material SpriteMaterial where type VI SpriteMaterial = VertexInput type VO SpriteMaterial = VertexOutput type B SpriteMaterial = Bindings vertex :: VertexInput GPU -> Shader SpriteMaterial (VertexOutput GPU) vertex :: VertexInput GPU -> Shader SpriteMaterial (VertexOutput GPU) vertex (VertexInput BuiltIn GPU "vertex_index" (Expr ('Primitive 'TUInt)) index) = do b <- Shader SpriteMaterial (B SpriteMaterial GPU) Shader SpriteMaterial (Bindings GPU) forall a. Material a => Shader a (B a GPU) bindings positions <- var $ array @(Vec2 Float) [vec2 (-1) (-1), vec2 1 (-1), vec2 1 1, vec2 (-1) (-1), vec2 1 1, vec2 (-1) 1] uvs <- var $ array @(Vec2 Float) [vec2 0 1, vec2 1 1, vec2 1 0, vec2 0 1, vec2 1 0, vec2 0 0] pos <- var $ (positions !! index) * b.sprite.size * diag 0.5 pos <- var $ b.sprite.rotation !*^ (pos +: 0) pos <- var $ pos + b.sprite.coords pos <- var $ b.matrices.projection !*^ (b.matrices.view !*^ (pos +: 1)) pure VertexOutput { pos = vec3 pos.x pos.y pos.z +: 1, uv = uvs !! index } fragment :: VertexOutput GPU -> Shader SpriteMaterial (Vec 4 Float) fragment :: VertexOutput GPU -> Shader SpriteMaterial (Vec 4 (Expr ('Primitive 'TFloat))) fragment VertexOutput {Location GPU 0 (Vec 2 (Expr ('Primitive 'TFloat))) uv :: forall f. VertexOutput f -> Location f 0 (Vec 2 (Expr ('Primitive 'TFloat))) uv :: Location GPU 0 (Vec 2 (Expr ('Primitive 'TFloat))) uv} = Vec 2 (Expr ('Primitive 'TFloat)) -> Shader SpriteMaterial (Vec 4 (Expr ('Primitive 'TFloat))) sampleSprite Vec 2 (Expr ('Primitive 'TFloat)) Location GPU 0 (Vec 2 (Expr ('Primitive 'TFloat))) uv fetch :: FetchBindings (B SpriteMaterial) fetch = (CameraEntity -> Query System (Buffer Matrices, Sampler)) -> (CameraEntity -> Query System (Buffer SpriteData, TextureView)) -> ((Buffer Matrices, Sampler) -> (Buffer SpriteData, TextureView) -> Bindings CPU) -> FetchBindings Bindings forall x y (b :: * -> *). Bindable b => (CameraEntity -> Query System x) -> (CameraEntity -> Query System y) -> (x -> y -> b CPU) -> FetchBindings b FetchBindings ( \CameraEntity camera -> do (DefaultSampler sampler) <- forall c (m :: * -> *) w. (MonadSystem w m, Component c) => Query m c qres @DefaultSampler CameraMatrices matrices <- qget camera [qd|CameraMatrices|] pure (matrices, sampler) ) ( \CameraEntity sprite -> do (Sprite {image}, buffer) <- CameraEntity -> (C Sprite, C (Buffer SpriteData)) -> Query System (Sprite, Buffer SpriteData) forall w (m :: * -> *) qd out. (MonadSystem w m, Queryable qd out) => CameraEntity -> qd -> Query m out qget CameraEntity sprite [qd|Sprite, (Buffer SpriteData)|] ImageTextureView texture <- qget image [qd|ImageTextureView|] pure (buffer, texture) ) (\(Buffer Matrices matrices, Sampler sampler) (Buffer SpriteData buffer, TextureView texture) -> Bindings {Buffer Matrices Uniform CPU (Matrices CPU) matrices :: Uniform CPU (Matrices CPU) matrices :: Buffer Matrices matrices, Sampler Binding CPU Sampler sampler :: Binding CPU Sampler sampler :: Sampler sampler, sprite :: Uniform CPU (SpriteData CPU) sprite = Buffer SpriteData Uniform CPU (SpriteData CPU) buffer, TextureView Binding CPU Texture texture :: Binding CPU Texture texture :: TextureView texture}) sampleSprite :: Vec 2 Float -> Shader SpriteMaterial (Vec 4 Float) sampleSprite :: Vec 2 (Expr ('Primitive 'TFloat)) -> Shader SpriteMaterial (Vec 4 (Expr ('Primitive 'TFloat))) sampleSprite Vec 2 (Expr ('Primitive 'TFloat)) uv = do b <- Shader SpriteMaterial (B SpriteMaterial GPU) Shader SpriteMaterial (Bindings GPU) forall a. Material a => Shader a (B a GPU) bindings let uv_flipped :: Vec 2 Float = abs $ cast b.sprite.flip - uv let uv = Expr ('VectorType 2 'TFloat) Vec 2 (Expr ('Primitive 'TFloat)) uv_flipped Expr ('VectorType 2 'TFloat) -> Expr ('VectorType 2 'TFloat) -> Expr ('VectorType 2 'TFloat) forall (a :: Types). Num a => Expr a -> Expr a -> Expr a * Expr ('Primitive (DesugarPrimitiveExpr (Expr ('Primitive 'TFloat)))) -> Expr ('Primitive (DesugarPrimitiveExpr (Expr ('Primitive 'TFloat)))) -> Vec 2 (Expr ('Primitive 'TFloat)) 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 Bindings GPU b.sprite.slice.z Bindings GPU b.sprite.slice.w Expr ('VectorType 2 'TFloat) -> Expr ('VectorType 2 'TFloat) -> Expr ('VectorType 2 'TFloat) forall (a :: Types). Num a => Expr a -> Expr a -> Expr a + Bindings GPU b.sprite.slice.xy pure $ sample b.texture b.sampler uv newtype SomeColor f = SomeColor {forall f. SomeColor f -> Field f (Vec 3 (Expr ('Primitive 'TFloat))) color :: Field f (Vec 3 Float)} deriving stock ((forall x. SomeColor f -> Rep (SomeColor f) x) -> (forall x. Rep (SomeColor f) x -> SomeColor f) -> Generic (SomeColor f) forall x. Rep (SomeColor f) x -> SomeColor f forall x. SomeColor f -> Rep (SomeColor f) x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall f x. Rep (SomeColor f) x -> SomeColor f forall f x. SomeColor f -> Rep (SomeColor f) x $cfrom :: forall f x. SomeColor f -> Rep (SomeColor f) x from :: forall x. SomeColor f -> Rep (SomeColor f) x $cto :: forall f x. Rep (SomeColor f) x -> SomeColor f to :: forall x. Rep (SomeColor f) x -> SomeColor f Generic) deriving anyclass (Int [(Text, Text)] Integer -> SomeColor GPU SomeColor CPU -> Ptr Word8 -> IO Int (Integer -> SomeColor GPU) -> [(Text, Text)] -> Int -> (SomeColor CPU -> Ptr Word8 -> IO Int) -> Bufferable SomeColor forall (a :: * -> *). (Integer -> a GPU) -> [(Text, Text)] -> Int -> (a CPU -> Ptr Word8 -> IO Int) -> Bufferable a $cdummyBuffer :: Integer -> SomeColor GPU dummyBuffer :: Integer -> SomeColor GPU $cgetFields :: [(Text, Text)] getFields :: [(Text, Text)] $cgetSize :: Int getSize :: Int $cputBytes :: SomeColor CPU -> Ptr Word8 -> IO Int putBytes :: SomeColor CPU -> Ptr Word8 -> IO Int Bufferable) newtype CustomBindings f = CustomBindings (Uniform f (SomeColor f)) deriving stock ((forall x. CustomBindings f -> Rep (CustomBindings f) x) -> (forall x. Rep (CustomBindings f) x -> CustomBindings f) -> Generic (CustomBindings f) forall x. Rep (CustomBindings f) x -> CustomBindings f forall x. CustomBindings f -> Rep (CustomBindings f) x forall a. (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a forall f x. Rep (CustomBindings f) x -> CustomBindings f forall f x. CustomBindings f -> Rep (CustomBindings f) x $cfrom :: forall f x. CustomBindings f -> Rep (CustomBindings f) x from :: forall x. CustomBindings f -> Rep (CustomBindings f) x $cto :: forall f x. Rep (CustomBindings f) x -> CustomBindings f to :: forall x. Rep (CustomBindings f) x -> CustomBindings f Generic) deriving anyclass (Typeable CustomBindings Typeable CustomBindings => (Natural -> Proxy (CustomBindings Internal) -> (Bindings, Natural)) -> (Natural -> Proxy (CustomBindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural)) -> (Natural -> CustomBindings CPU -> ([WGPUBindGroupEntry], Natural)) -> (Natural -> (CustomBindings GPU, Natural)) -> Bindable CustomBindings Natural -> (CustomBindings GPU, Natural) Natural -> Proxy (CustomBindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural) Natural -> Proxy (CustomBindings Internal) -> (Bindings, Natural) Natural -> CustomBindings CPU -> ([WGPUBindGroupEntry], Natural) forall (a :: * -> *). Typeable a => (Natural -> Proxy (a Internal) -> (Bindings, Natural)) -> (Natural -> Proxy (a Internal) -> ([WGPUBindGroupLayoutEntry], Natural)) -> (Natural -> a CPU -> ([WGPUBindGroupEntry], Natural)) -> (Natural -> (a GPU, Natural)) -> Bindable a $ccollectBindings :: Natural -> Proxy (CustomBindings Internal) -> (Bindings, Natural) collectBindings :: Natural -> Proxy (CustomBindings Internal) -> (Bindings, Natural) $ccollectLayouts :: Natural -> Proxy (CustomBindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural) collectLayouts :: Natural -> Proxy (CustomBindings Internal) -> ([WGPUBindGroupLayoutEntry], Natural) $ccollectEntries :: Natural -> CustomBindings CPU -> ([WGPUBindGroupEntry], Natural) collectEntries :: Natural -> CustomBindings CPU -> ([WGPUBindGroupEntry], Natural) $cdummyBinding :: Natural -> (CustomBindings GPU, Natural) dummyBinding :: Natural -> (CustomBindings GPU, Natural) Bindable) data CustomMat instance Material CustomMat where type VI CustomMat = VI SpriteMaterial type VO CustomMat = VO SpriteMaterial type B CustomMat = CustomBindings type Extends CustomMat = '[SpriteMaterial, TimeMaterial] vertex :: VI CustomMat GPU -> Shader CustomMat (VO CustomMat GPU) vertex = Shader SpriteMaterial (VertexOutput GPU) -> Shader CustomMat (VertexOutput GPU) forall a b c. ExtensionOf b a => Shader a c -> Shader b c liftExt (Shader SpriteMaterial (VertexOutput GPU) -> Shader CustomMat (VertexOutput GPU)) -> (VertexInput GPU -> Shader SpriteMaterial (VertexOutput GPU)) -> VertexInput GPU -> Shader CustomMat (VertexOutput GPU) forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Material a => VI a GPU -> Shader a (VO a GPU) vertex @SpriteMaterial fragment :: VO CustomMat GPU -> Shader CustomMat (Vec 4 Float) fragment :: VO CustomMat GPU -> Shader CustomMat (Vec 4 (Expr ('Primitive 'TFloat))) fragment VO CustomMat GPU vo = do color <- Shader SpriteMaterial (Vec 4 (Expr ('Primitive 'TFloat))) -> Shader CustomMat (Vec 4 (Expr ('Primitive 'TFloat))) forall a b c. ExtensionOf b a => Shader a c -> Shader b c liftExt (Shader SpriteMaterial (Vec 4 (Expr ('Primitive 'TFloat))) -> Shader CustomMat (Vec 4 (Expr ('Primitive 'TFloat)))) -> Shader SpriteMaterial (Vec 4 (Expr ('Primitive 'TFloat))) -> Shader CustomMat (Vec 4 (Expr ('Primitive 'TFloat))) forall a b. (a -> b) -> a -> b $ forall a. Material a => VO a GPU -> Shader a (Vec 4 (Expr ('Primitive 'TFloat))) fragment @SpriteMaterial VO CustomMat GPU VO SpriteMaterial GPU vo time <- liftExt getTime (CustomBindings (SomeColor c)) <- bindings pure $ color * (c ^* cos time +: 1) fetch :: FetchBindings (B CustomMat) fetch = FetchBindings { camera :: CameraEntity -> Query System () camera = Query System () -> CameraEntity -> Query System () forall a b. a -> b -> a const (Query System () -> CameraEntity -> Query System ()) -> Query System () -> CameraEntity -> Query System () forall a b. (a -> b) -> a -> b $ () -> Query System () forall a. a -> Query System a forall (f :: * -> *) a. Applicative f => a -> f a pure (), mesh :: CameraEntity -> Query System (Buffer SomeColor) mesh = \CameraEntity sprite -> CameraEntity -> C (Buffer SomeColor) -> Query System (Buffer SomeColor) forall w (m :: * -> *) qd out. (MonadSystem w m, Queryable qd out) => CameraEntity -> qd -> Query m out qget CameraEntity sprite [qd|(Buffer SomeColor)|], result :: () -> Buffer SomeColor -> CustomBindings CPU result = (Buffer SomeColor -> CustomBindings CPU) -> () -> Buffer SomeColor -> CustomBindings CPU forall a b. a -> b -> a const Buffer SomeColor -> CustomBindings CPU Uniform CPU (SomeColor CPU) -> CustomBindings CPU forall f. Uniform f (SomeColor f) -> CustomBindings f CustomBindings }