import Codec.Picture import Codec.Picture.Types import Common import Control.Monad import Control.Monad.Except ( MonadError(..) ) import Control.Monad.IO.Class import Control.Monad.Trans.Resource import Data.Vector ( Vector, convert ) import qualified Data.Vector.Storable as S ( Vector ) import Foreign.Storable ( Storable ) import Graphics.Luminance.Batch import Graphics.Luminance.Cmd import Graphics.Luminance.Framebuffer import Graphics.Luminance.Geometry import Graphics.Luminance.RenderCmd import Graphics.Luminance.Pixel as L import Graphics.Luminance.Shader.Program import Graphics.Luminance.Shader.Stage import Graphics.Luminance.Texture import Graphics.Luminance.Vertex import Graphics.UI.GLFW import System.Environment ( getArgs ) main :: IO () main = startup $ \window -> do args <- liftIO getArgs when (null args) . throwError $ AppError "expecting a texture path as argument!" tex <- loadTexture (head args) quad <- createGeometry vertices Nothing Triangle vs <- createVertexShader vsSource fs <- createFragmentShader fsSource (program,texU) <- createProgram [vs,fs] $ \uni -> do uni $ Left "srcTex" untilM (liftIO $ windowShouldClose window) $ do void . runCmd . draw $ framebufferBatch defaultFramebuffer [anySPBatch $ shaderProgramBatch program texU tex [renderCmd Nothing True mempty () quad]] endFrame window vertices :: [V 2 Float] vertices = [ V2 (-1) 1 , V2 1 1 , V2 (-1) (-1) , V2 (-1) (-1) , V2 1 1 , V2 1 (-1) ] vsSource :: String vsSource = unlines [ "in vec2 co;" , "void main() {" , " gl_Position = vec4(co, 0., 1.);" , "}" ] fsSource :: String fsSource = unlines [ "out vec4 frag;" , "layout (bindless_sampler) uniform usampler2D srcTex;" , "void main() {" , " vec2 uv = gl_FragCoord.xy;" , " uv.y = " ++ show (windowH :: Int) ++ " - uv.y;" , " vec3 sampled = vec3(texture(srcTex, uv / vec2(" ++ show (windowW :: Int) ++ "," ++ show (windowH :: Int) ++ "), 0).rgb) / 255;" , " frag = vec4(sampled, 1.);" , "}" ] loadTexture :: (MonadError AppError m,MonadIO m,MonadResource m) => String -> m (Texture2D RGBA8UI) loadTexture path = liftIO (readImage path) >>= either (throwError . AppError) treatDynamicImage where treatDynamicImage image = case image of ImageRGBA8 img -> liftIO (putStrLn "ImageRGBA8") >> createTexture_ img ImageYCbCr8 img -> liftIO (putStrLn "ImageYCbCr8") >> createTexture_ (promoteImage $ (convertImage img :: Image PixelRGB8)) _ -> throwError $ AppError "unsupported image format" createTexture_ :: (MonadIO m,MonadResource m) => Image PixelRGBA8 -> m (Texture2D RGBA8UI) createTexture_ img = do tex <- createTexture (fromIntegral $ imageWidth img) (fromIntegral $ imageHeight img) 1 defaultSampling uploadWhole tex False (convertV $ imageData img) pure tex convertV :: (Storable a) => S.Vector a -> Vector a convertV = convert