openglhaskelltexture2djuicy-pixels

How to load an OpenGL texture with the JuicyPixels library in Haskell


Can you provide me with an example on how to load a texture with texImage2D (from OpenGL) and readImage (from the JuicyPixels library) in Haskell?

I know there is already a similar question here but cause I'm a newbie, I'm not been able to make that example works. I need the complete code and maybe also some explanation on how it works...


Solution

  • Sorry, I don't know how to operate with JuicyPixels, but I've done texture loading in OpenGL.

    It is a bit more complex. It does loading textures from several files, assuming they are texture atlasses (contain several images on a texture).

    You can examine what parts of this program specific to texture rendering (by cutting unnecessary parts) and figure out how to convert JuicePixels image to raw array of pixel colors (look into bindBMPTexture function in utils module)

    Good luck!

    import            Data.ByteString         ( ByteString(..) )
    import qualified  Data.ByteString  as BS
    import qualified  Data.ByteString.Unsafe as BSU
    import            Graphics.UI.GLUT
    import            Graphics.Rendering.OpenGL (($=))
    import qualified  Graphics.Rendering.OpenGL as GL
    import qualified  Codec.BMP as BMP 
    import            Foreign.ForeignPtr
    import            Foreign.Ptr
    import            Control.Monad
    import            Unsafe.Coerce
    import qualified  Graphics.UI.GLFW as GLFW
    import            Data.IORef
    import            Data.List
    import qualified  Data.Map as Map
    import            Data.Maybe
    import OpenGLUtils
    
    data TextureInfo = TextureInfo GL.TextureObject (Int, Int)
    data ImageTexture = ImageTexture String (Int, Int) (Int, Int)
    images = [ ImageTexture "data/bricks.bmp" (0, 0) (64, 16)
             , ImageTexture "data/bricks.bmp" (0, 16) (64, 16)
             , ImageTexture "data/bricks.bmp" (0, 32) (64, 16)
             , ImageTexture "data/bricks.bmp" (0, 48) (64, 16)
             ]
    
    main = do
      GLFW.initialize
      GLFW.openWindow (GL.Size (gsizei oSCREEN_WIDTH) (gsizei oSCREEN_HEIGHT)) [GLFW.DisplayAlphaBits 8] GLFW.Window
      GLFW.windowTitle $= "Texture demo"
      GL.shadeModel    $= GL.Smooth
      GL.lineSmooth    $= GL.Enabled
      GL.blend      $= GL.Enabled
      GL.blendFunc  $= (GL.SrcAlpha, GL.OneMinusSrcAlpha)
      GL.lineWidth  $= 1.5
      GL.clearColor $= Color4 0 0 0 0
    
      GLFW.windowSizeCallback $= \ size@(GL.Size w h) -> do
          GL.viewport   $= (GL.Position 0 0, size)
          GL.matrixMode $= GL.Projection
          GL.loadIdentity
    
      texturesMap <- loadTextures
      glfwStaticRender $ do
         drawTexture_ texturesMap $ images !! 0
    
      GLFW.closeWindow
      GLFW.terminate
    
    loadTextures :: IO (Map.Map String TextureInfo)
    loadTextures = do
        let paths = nub $ map (\(ImageTexture path _ _) -> path) images
        texs <- GL.genObjectNames (length paths)
        let zippedMap = zip paths texs
        sizes <- forM zippedMap $ \(path, tex) ->
            bindBMPTexture tex path
        return $ Map.fromList (zipWith (\(path,tex) size -> (path, TextureInfo tex size)) zippedMap sizes)
    
    drawTexture_ textureMap (ImageTexture path (posX, posY) (sizeX, sizeY)) = do
        let (TextureInfo tex (tSizeX, tSizeY)) = fromJust $ Map.lookup path textureMap
        drawTexture tex (tSizeX, tSizeY) (posX, posY) (sizeX, sizeY)