OpenGL VBO in Haskell

Based on this post , I tried to figure out how to use VBO in Haskell. I tried to fill in bits that were not covered there:

data Sprite = Sprite { spriteImage :: Image
                     , spritePosition :: Position
                     } deriving (Show, Eq)

spriteBatch :: [Sprite] -> [(TextureObject, [Sprite])]
spriteBatch = (map f) . toList . (groupedBy (imageTexture . spriteImage))
    where f (t, s) = (t, s)

offset = plusPtr nullPtr

renderSprites :: [Sprite] -> IO ()
renderSprites l = (flip mapM_) (spriteBatch l) $ \(t, sps) -> do
        textureBinding Texture2D $= Just t
        let l = concat $ map sprToList sps
        vbo <- vboOfList ((length l)*4) l
        displayVbo vbo $ fromIntegral $ length sps
    where
        sprToList :: Sprite -> [GLfloat]
        sprToList (Sprite (Image _ (TexCoord2 u0 v0) (TexCoord2 u1 v1) (Size w h) _) (Position x y)) = 
            [fromIntegral x, fromIntegral y, u0, v0
            ,fromIntegral (x+w), fromIntegral y, u1, v0
            ,fromIntegral (x+w), fromIntegral (y+h), u1, v1
            ,fromIntegral x, fromIntegral (y+h), u0, v1
            ]

vboOfList :: Int -> [GLfloat] -> IO BufferObject
vboOfList size elems = do
    let ptrsize = toEnum $ size * 4
        arrayType = ElementArrayBuffer
    (array:_) <- genObjectNames 1
    bindBuffer arrayType $= Just array
    arr <- newListArray (0, size - 1) elems
    withStorableArray arr $ \ptr -> bufferData arrayType $= (ptrsize, ptr, StaticDraw)
    bindBuffer ArrayBuffer $= Nothing
    return array

displayVbo buff size = do
    let stride = 2*(2*4)
        vxDesc = VertexArrayDescriptor 2 Float stride $ offset 0
        texCoo = VertexArrayDescriptor 2 Float stride $ offset 8
    bindBuffer ArrayBuffer $= Just buff

    arrayPointer VertexArray $= vxDesc
    arrayPointer TextureCoordArray $= texCoo

    clientState VertexArray $= Enabled
    clientState TextureCoordArray $= Enabled

    drawArrays Quads 0 size
    bindBuffer ArrayBuffer $= Nothing

Here you can find the full code here if you need to.

In the main branch, this same function uses regular vertexdrawing calls Sprites, and it works great. But using VBO, the sprite simply does not exist; I get a blank screen.

Can someone explain to me what I did wrong here?

+5
source share
1 answer

You use one buffer for vertices and uv. Use two buffers, one for vertices and one for uvs.

+1
source

All Articles