2010-02-08 [長年日記]

[Haskell] HaskellでOpenGL (13)

少し趣を変えてGLSLを使って書いたシェーダーを使う方法です。

OpenGL

シェーダーを使うには、頂点シェーダーとフラグメントシェーダーをコンパイルしてから、プログラムオブジェクトにアタッチし、そのプログラムオブジェクトをリンクして使います。実際に描く時には、vertexAttribPointerで頂点の属性を設定して頂点シェーダに情報を渡します。頂点の属性は、StorableArrayを使って配列へのポインタにして渡します。

以下の例では、フラグメントシェーダーは赤を返すように固定してあります。


import Control.Monad
import Data.Array.Storable
import Foreign.Ptr
import Graphics.Rendering.OpenGL
import Graphics.UI.GLUT

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)
     displayCallback $= display program
     mainLoop

display program =
  do clear [ColorBuffer]
     currentProgram $= Just program
     loc <- get $ attribLocation program "a_position"
     positions <- newListArray (0, 5) ([0.0, 0.9, -0.9, -0.9, 0.9, -0.9] :: [GLfloat])
     withStorableArray positions $ \ptr ->
       do vertexAttribPointer loc $= (ToFloat, VertexArrayDescriptor 2 Float 0 ptr)
          vertexAttribArray loc $= Enabled
          drawArrays Triangles 0 3
     flush

vertexShaderSource = "attribute vec4 a_position;  \
                     \void main() {               \
                     \  gl_Position = a_position; \
                     \}"

fragmentShaderSource = "void main() {                              \
                       \  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \
                       \}"

createShader source =
  do [shader] <- genObjectNames 1
     shaderSource shader $= [source]
     compileShader shader
     return shader

createProgram vertexShader fragmentShader =
  do [program] <- genObjectNames 1
     attachedShaders program $= ([vertexShader], [fragmentShader])
     linkProgram program
     return program
[]

トップ «前の日記(2010-01-31) 最新 次の日記(2010-02-09)»