module Main where
import Graphics.QML
import Graphics.QML.Canvas
import Graphics.Rendering.OpenGL.GL
import Graphics.Rendering.OpenGL.GLU.Errors
import Graphics.Rendering.OpenGL.Raw.ARB.ShaderObjects (glUniformMatrix4fv)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Foreign.C.Types
import Foreign.Marshal.Array
import Foreign.Ptr
import Foreign.Storable
import Paths_hsqml_demo_samples
shaderHead :: OpenGLType -> [String]
shaderHead OpenGLDesktop = ["#version 120", "#define highp"]
shaderHead OpenGLES = ["#version 100"]
vertShaderText :: OpenGLType -> Text
vertShaderText t = T.pack $ unlines $ shaderHead t ++ [
"attribute highp vec4 position;",
"attribute highp vec4 color;",
"uniform highp mat4 matrix;",
"uniform highp float model;",
"varying highp vec4 vColor;",
"void main() {",
" gl_Position = matrix * position;",
" vColor = mix(color, vec4(1,1,1,2) - color, model);",
"}"]
fragShaderText :: OpenGLType -> Text
fragShaderText t = T.pack $ unlines $ shaderHead t ++ [
"varying highp vec4 vColor;",
"void main() {",
" gl_FragColor = vColor;",
"}"]
dataArray :: [CFloat]
dataArray = [
0.0, 1.0, 0.0, 1.0,
-1.0, -1.0, 0.0, 1.0,
1.0, -1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0]
data GLData = GLData
Program Shader Shader UniformLocation UniformLocation
AttribLocation AttribLocation BufferObject
checkErrors :: String -> IO ()
checkErrors title = do
errs <- get errors
if null errs then return () else putStrLn $ title ++ ": " ++ show errs
setupGL :: OpenGLSetup -> IO GLData
setupGL setup = do
putStrLn $ (showString "Context is " .
shows (openGLType setup) . showString " " .
shows (openGLMajor setup) . showString "." .
shows (openGLMinor setup)) ""
let ctype = openGLType setup
vertShader <- createShader VertexShader
shaderSourceBS vertShader $= (T.encodeUtf8 $ vertShaderText ctype)
compileShader vertShader
-- vsl <- get $ shaderInfoLog vertShader
-- putStrLn $ show vsl
fragShader <- createShader FragmentShader
shaderSourceBS fragShader $= (T.encodeUtf8 $ fragShaderText ctype)
compileShader fragShader
-- fsl <- get $ shaderInfoLog fragShader
-- putStrLn $ show fsl
program <- createProgram
attachShader program vertShader
attachShader program fragShader
linkProgram program
-- pl <- get $ programInfoLog program
-- putStrLn $ show pl
matLoc <- get $ uniformLocation program "matrix"
modelLoc <- get $ uniformLocation program "model"
posLoc <- get $ attribLocation program "position"
colLoc <- get $ attribLocation program "color"
buf <- genObjectName
bindBuffer ArrayBuffer $= Just buf
withArrayLen dataArray $ \len ptr ->
bufferData ArrayBuffer $=
(fromIntegral $ len * sizeOf (head dataArray),
ptr, StaticDraw)
bindBuffer ArrayBuffer $= Nothing
checkErrors "Setup"
return $ GLData
program vertShader fragShader matLoc modelLoc posLoc colLoc buf
paintGL :: OpenGLPaint GLData Double -> IO ()
paintGL paint = do
let (GLData program _ _ matLoc modelLoc posLoc colLoc buf) = setupData paint
let num = realToFrac $ modelData paint :: GLfloat
currentProgram $= Just program
let (UniformLocation matLocId) = matLoc
glUniformMatrix4fv matLocId 1 0 (
castPtr $ matrixPtr paint :: Ptr GLfloat)
uniform modelLoc $= Index1 num
bindBuffer ArrayBuffer $= Just buf
vertexAttribArray posLoc $= Enabled
vertexAttribPointer posLoc $=
(ToFloat, VertexArrayDescriptor 4 Float 0 nullPtr)
vertexAttribArray colLoc $= Enabled
vertexAttribPointer colLoc $=
(ToFloat, VertexArrayDescriptor 4 Float 0 $ plusPtr nullPtr $
length dataArray * sizeOf (head dataArray) `quot` 2)
drawArrays Triangles 0 3
vertexAttribArray posLoc $= Disabled
vertexAttribArray colLoc $= Disabled
bindBuffer ArrayBuffer $= Nothing
currentProgram $= Nothing
checkErrors "Paint"
cleanupGL :: GLData -> IO ()
cleanupGL (GLData program vertShader fragShader _ _ _ _ buf) = do
deleteObjectName buf
deleteObjectName program
deleteObjectName vertShader
deleteObjectName fragShader
checkErrors "Cleanup"
main :: IO ()
main = do
clazz <- newClass [
defPropertyConst' "myDelegate" (\_ ->
newOpenGLDelegate setupGL paintGL cleanupGL)]
ctx <- newObject clazz ()
doc <- getDataFileName "opengl1.qml"
runEngineLoop defaultEngineConfig {
initialDocument = fileDocument doc,
contextObject = Just $ anyObjRef ctx}