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

790 views Asked by At

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...

1

There are 1 answers

1
danbst On BEST ANSWER

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)