keid-render-basic-0.1.6.1: src/Render/Unlit/Sprite/Model.hs
{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}
module Render.Unlit.Sprite.Model
( InstanceAttrs(..)
, StorableAttrs
, InstanceBuffer
, fromTexture
, fromAtlas
, vkInstanceAttrs
) where
import RIO
import Foreign.Storable.Generic (GStorable)
import Geomancy (Vec2, Vec4, UVec2, withUVec2, vec2)
import Geomancy.Vec4 qualified as Vec4
import Render.Samplers qualified as Samplers
import Resource.Buffer qualified as Buffer
import Resource.Image.Atlas (Atlas)
import Resource.Image.Atlas qualified as Atlas
import RIO.Vector.Storable qualified as Storable
import Vulkan.Core10 qualified as Vk
import Vulkan.Zero (Zero(..))
type StorableAttrs = Storable.Vector InstanceAttrs
data InstanceAttrs = InstanceAttrs
{ vertRect :: Vec4
, fragRect :: Vec4
, tint :: Vec4
, outline :: Vec4
, samplerId :: Int32
, textureId :: Int32
, textureSize :: UVec2
}
deriving (Show, Generic)
instance GStorable InstanceAttrs
instance Zero InstanceAttrs where
zero = InstanceAttrs
{ vertRect = 0
, fragRect = 0
, tint = 0
, outline = 0
, samplerId = 0
, textureId = 0
, textureSize = 0
}
vkInstanceAttrs :: [Vk.Format]
vkInstanceAttrs =
[ Vk.FORMAT_R32G32B32A32_SFLOAT -- Quad scale+offset
, Vk.FORMAT_R32G32B32A32_SFLOAT -- UV scale+offset
, Vk.FORMAT_R32G32B32A32_SFLOAT -- Tint
, Vk.FORMAT_R32G32B32A32_SFLOAT -- Outline (when enabled)
, Vk.FORMAT_R32G32_SINT -- Sampler + texture IDs
, Vk.FORMAT_R32G32_UINT -- Texture size
]
type InstanceBuffer stage = Buffer.Allocated stage InstanceAttrs
fromTexture
:: Int32 -- ^ Sampler index.
-> Int32 -- ^ Texture index.
-> Vec2 -- ^ Sprite size.
-> Vec2 -- ^ Sprite position.
-> InstanceAttrs
fromTexture sampler texture wh pos =
InstanceAttrs
{ vertRect = Vec4.fromVec22 pos wh
, fragRect = Vec4.fromVec22 0 1
, tint = 1
, outline = 0
, samplerId = sampler
, textureId = texture
, textureSize = 0
}
fromAtlas
:: Int32 -- ^ Texture ID.
-> Atlas
-> Vec2 -- ^ Sprite scale, wrt. to native tile size
-> Vec2 -- ^ Tile position in atlas tiles. Can be fractional when using subgrids.
-> Vec2 -- ^ Sprite position.
-> InstanceAttrs
fromAtlas texture atlas scale atlasPos worldPos =
InstanceAttrs
{ vertRect = Vec4.fromVec22 worldPos (tileSize * scale)
, fragRect = Vec4.fromVec22 (atlasPos * uvScale) uvScale
, tint = 1
, outline = 0
, samplerId = Samplers.nearest Samplers.indices
, textureId = texture
, textureSize = Atlas.sizePx atlas
}
where
uvScale = Atlas.uvScale atlas
tileSize =
withUVec2 (Atlas.tileSizePx atlas) \tw th ->
vec2 (fromIntegral tw) (fromIntegral th)