描画するたびに頂点属性をメモリからGPUのメモリに転送するのを避けるには頂点バッファオブジェクトを使います。頂点バッファオブジェクトを使うと、頂点属性をGPUのメモリに置きっぱなしにできます。
作成するには、genObjectNamesで名前を作り、bindBufferでバインドし、bufferDataでデータを書き込みます。
使用するときには、bindBufferでバインドした状態で、VertexArrayDescriptorの最後の引数にバッファへのポインタの代わりに頂点バッファオブジェクト内でのオフセットを指定します。オフセットの指定には、IntPtrが使えます。
前回と変わったところだけ。
main =
do (progName, _) <- getArgsAndInitialize
initialDisplayMode $= [RGBAMode]
window <- createWindow "Window"
clearColor $= Color4 1.0 1.0 1.0 0.0
program <- join $ liftM2 createProgram (createShader vertexShaderSource)
(createShader fragmentShaderSource)
positionLoc <- get $ attribLocation program "a_position"
colorLoc <- get $ attribLocation program "a_color"
buffer <- createBuffer ([ 0.0, 0.9, 1.0, 0.0, 0.0,
-0.9, -0.9, 0.0, 1.0, 0.0,
0.9, -0.9, 0.0, 0.0, 1.0] :: [GLfloat])
displayCallback $= display program positionLoc colorLoc buffer
mainLoop
display program positionLoc colorLoc buffer =
do clear [ColorBuffer]
currentProgram $= Just program
bindBuffer ArrayBuffer $= Just buffer
vertexAttribPointer positionLoc $= (ToFloat, VertexArrayDescriptor 2 Float (toEnum (5*sizeOf(0 :: GLfloat))) (intPtrToPtr 0))
vertexAttribArray positionLoc $= Enabled
vertexAttribPointer colorLoc $= (ToFloat, VertexArrayDescriptor 3 Float (toEnum (5*sizeOf(0 :: GLfloat))) (intPtrToPtr (toEnum (2*sizeOf(0 :: GLfloat)))))
vertexAttribArray colorLoc $= Enabled
drawArrays Triangles 0 3
flush
createBuffer l =
do [buffer] <- genObjectNames 1
bindBuffer ArrayBuffer $= Just buffer
arr <- newListArray (0, length l - 1) l
withStorableArray arr $ \ptr ->
bufferData ArrayBuffer $= (toEnum (length l*sizeOf(head l)), ptr, StaticDraw)
bindBuffer ArrayBuffer $= Nothing
return buffer