{-# LANGUAGE RankNTypes #-} module Data.Texture.Core ( Texture, texture,texture',readTexture,readTextures,readTextures' ) where import Definitive import Data.Serialize import Codec.Picture import Codec.Picture.Types (convertImage) import qualified Graphics.Rendering.OpenGL as GL import Data.Vertex import Data.Raster -- |The abstract Texture type data Texture = Texture GL.TextureObject deriving Show data TextureFormat = RGB | RGBA | Greyscale | GreyscaleA pixelFormats RGBA = (GL.RGBA',GL.RGBA) pixelFormats RGB = (GL.RGB',GL.RGB) pixelFormats Greyscale = (GL.SLuminance8,GL.Luminance) pixelFormats GreyscaleA = (GL.SLuminance8Alpha8,GL.LuminanceAlpha) -- |Convert a Raster to a texture texture (yb raster -> i) = by thunk $ yb _eitherT $ do let conv (ImageRGB8 (Image w h d)) = return (pixelFormats RGB,w,h,d) conv (ImageY8 (Image w h d)) = return (pixelFormats Greyscale,w,h,d) conv (ImageRGBA8 (Image w h d)) = return (pixelFormats RGBA,w,h,d) conv (ImageYA8 (Image w h d)) = return (pixelFormats GreyscaleA,w,h,d) conv (ImageYCbCr8 i) = conv (ImageRGB8 (convertImage i)) conv _ = throw "Unhandled image format" ((f,f'),w,h,d) <- by _eitherT $ pure $ conv i lift $ do [tex] <- GL.genObjectNames 1 GL.textureBinding GL.Texture2D GL.$= Just tex unsafeWith d $ GL.build2DMipmaps GL.Texture2D f (fromIntegral w) (fromIntegral h) . GL.PixelData f' GL.UnsignedByte GL.textureFilter GL.Texture2D GL.$= ((GL.Linear', Just GL.Nearest), GL.Linear') GL.textureFunction GL.$= GL.Modulate return (Texture tex) texture' = (error<|>id).texture listToEither [] = Left zero listToEither (~(_,a):_) = Right a -- |Read a texture from a file. readTexture name = (readBytes name <&> joinMap texture . listToEither . yb parser image) where image = yb jpg<$>serializable <+>yb png<$>serializable <+>yb bmp<$>serializable -- |Try to read a structure of files into a structure of textures. readTextures = map sequence . traverse readTexture -- |Read a structure of files into a structure of textures, raising an error -- if it fails. readTextures' = map2 (error<|>id) readTextures instance Graphics Texture where draw (Texture t) = GL.textureBinding GL.Texture2D GL.$= Just t