为什么这个OpenGL示例没有绘制三角形?

时间:2017-05-08 03:59:59

标签: haskell opengl

我正在尝试在屏幕上绘制一个基本的“三角形”example,但在Haskell中使用gl和GLFW-b包。

我的代码是here

-- https://learnopengl.com/#!Getting-started/Hello-Triangle

-- stuff from base
import Control.Monad (when, mapM)
import Foreign -- includes Ptr and Marshal, among other things.

-- we qualify these names so we can tell what's from GLFW
import qualified Graphics.UI.GLFW as GLFW

-- gl funcs all already have "gl" in their name
import Graphics.GL

width = 800 :: Int

height = 600 :: Int

vertexShaderSource = [
    "#version 330 core\n",
    "layout (location = 0) in vec3 position;\n",
    "void main()\n",
    "{\n",
    "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n",
    "}\n"]

fragmentShaderSource = [
    "#version 330 core\n",
    "out vec4 color;\n",
    "void main()\n",
    "{\n",
    "color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n",
    "}\n"]

getSrcPointer :: [String] -> IO (Ptr (Ptr GLchar), Ptr GLint)
getSrcPointer sourceLines = do
    let glcharLines = map (map (fromIntegral.fromEnum)) sourceLines
    let linesLengths = map (fromIntegral.length) glcharLines
    linesPtrs <- mapM newArray glcharLines
    linesPtrsPtr <- newArray linesPtrs
    lengthsPtr <- newArray linesLengths
    return (linesPtrsPtr,lengthsPtr)

-- type KeyCallback = Window -> Key -> Int -> KeyState -> ModifierKeys -> IO ()
callback :: GLFW.KeyCallback
callback window key scanCode keyState modKeys = do
    putStrLn (show key)
    when (key == GLFW.Key'Escape && keyState == GLFW.KeyState'Pressed)
        (GLFW.setWindowShouldClose window True)

main :: IO ()
main = do
    -- init GLFW and set the appropriate options
    _ <- GLFW.init
    GLFW.windowHint (GLFW.WindowHint'ContextVersionMajor 3)
    GLFW.windowHint (GLFW.WindowHint'ContextVersionMinor 3)
    GLFW.windowHint (GLFW.WindowHint'OpenGLProfile GLFW.OpenGLProfile'Core)
    GLFW.windowHint (GLFW.WindowHint'Resizable False)
    -- create our window
    maybeWindow <- GLFW.createWindow width height "Lesson 02" Nothing Nothing
    case maybeWindow of
        Nothing -> do
            -- somehow we failed. Nothing to do but report that and quit.
            putStrLn "Failed to create a GLFW window!"
            GLFW.terminate
        Just window -> do
            -- set our context and callback
            GLFW.makeContextCurrent (Just window)
            GLFW.setKeyCallback window (Just callback)

            -- define the viewport dimensions
            (frameWidth,frameHeight) <- GLFW.getFramebufferSize window
            glViewport 0 0 (fromIntegral frameWidth) (fromIntegral frameHeight)

            -- build and compile our shader program.
            successP <- malloc

            -- vertex shader
            vertexShader <- glCreateShader GL_VERTEX_SHADER
            (linesPtrsPtr,lengthsPtr) <- getSrcPointer vertexShaderSource
            glShaderSource vertexShader 1 linesPtrsPtr lengthsPtr
            glCompileShader vertexShader
            -- check for compilation errors
            glGetShaderiv vertexShader GL_COMPILE_STATUS successP
            success <- peek successP
            when (success == 0) $ do
                putStrLn "Vertex Shader Compile Error:"
                let infoLength = 512
                resultP <- malloc
                infoLog <- mallocArray (fromIntegral infoLength)
                glGetShaderInfoLog vertexShader (fromIntegral infoLength) resultP infoLog
                result <- fromIntegral <$> peek resultP
                logBytes <- peekArray result infoLog
                putStrLn (map (toEnum.fromEnum) logBytes)

            -- fragment shader
            fragmentShader <- glCreateShader GL_FRAGMENT_SHADER
            (linesPtrsPtr,lengthsPtr) <- getSrcPointer fragmentShaderSource
            glShaderSource fragmentShader 1 linesPtrsPtr lengthsPtr
            glCompileShader fragmentShader
            -- check for compilation errors
            glGetShaderiv fragmentShader GL_COMPILE_STATUS successP
            success <- peek successP
            when (success == 0) $ do
                putStrLn "Fragment Shader Compile Error:"
                let infoLength = 512
                resultP <- malloc
                infoLog <- mallocArray (fromIntegral infoLength)
                glGetShaderInfoLog fragmentShader (fromIntegral infoLength) resultP infoLog
                result <- fromIntegral <$> peek resultP
                logBytes <- peekArray result infoLog
                putStrLn (map (toEnum.fromEnum) logBytes)

            -- link up the shaders
            shaderProgram <- glCreateProgram
            glAttachShader shaderProgram vertexShader
            glAttachShader shaderProgram fragmentShader
            glLinkProgram shaderProgram
            -- check for linking errors
            glGetProgramiv shaderProgram GL_LINK_STATUS successP
            success <- peek successP
            when (success == 0) $ do
                putStrLn "Program Linking Error:"
                let infoLength = 512
                resultP <- malloc
                infoLog <- mallocArray (fromIntegral infoLength)
                glGetProgramInfoLog shaderProgram (fromIntegral infoLength) resultP infoLog
                result <- fromIntegral <$> peek resultP
                logBytes <- peekArray result infoLog
                putStrLn (map (toEnum.fromEnum) logBytes)

            -- cleanup the sub-programs now that our complete shader program is ready
            glDeleteShader vertexShader
            glDeleteShader fragmentShader

            -- setup vertex data and attribute pointers
            verticesP <- newArray ([
                -0.5, -0.5, 0.0, -- Left  
                0.5, -0.5, 0.0, -- Right 
                0.0,  0.5, 0.0  -- Top
                ] :: [GLfloat])
            let verticesSize = fromIntegral $ sizeOf (0.0 :: GLfloat) * 9
            vboP <- malloc :: IO (Ptr GLuint)
            vaoP <- malloc :: IO (Ptr GLuint)
            glGenVertexArrays 1 vaoP
            glGenBuffers 1 vboP
            -- Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
            vao <- peek vaoP
            glBindVertexArray vao
            vbo <- peek vboP
            glBindBuffer GL_ARRAY_BUFFER vbo
            glBufferData GL_ARRAY_BUFFER verticesSize (castPtr verticesP) GL_STATIC_DRAW
            let threeFloats = fromIntegral $ sizeOf (0.0::GLfloat) * 3
            glVertexAttribPointer 0 3 GL_FLOAT GL_FALSE threeFloats nullPtr
            glEnableVertexAttribArray 0
            -- Note that this is allowed, the call to glVertexAttribPointer
            -- registered VBO as the currently bound vertex buffer object so
            -- afterwards we can safely unbind
            glBindBuffer GL_ARRAY_BUFFER 0
            -- Unbind VAO (it's always a good thing to unbind any buffer/array
            -- to prevent strange bugs)
            glBindVertexArray 0

            -- "game loop"
            let loop :: IO ()
                loop = do
                    shouldClose <- GLFW.windowShouldClose window
                    if shouldClose
                        then return ()
                        else do
                            -- event poll
                            GLFW.pollEvents

                            -- clear the screen
                            glClearColor 0.2 0.3 0.3 1.0
                            glClear GL_COLOR_BUFFER_BIT
                            -- draw a triangle
                            glUseProgram shaderProgram
                            glBindVertexArray vao
                            glDrawArrays GL_TRIANGLES 0 3
                            glBindVertexArray 0

                            -- swap buffers and go again
                            GLFW.swapBuffers window
                            loop
            loop

            -- clean up the gl resources
            glDeleteVertexArrays 1 vaoP
            glDeleteBuffers 1 vboP
            -- clean up the GLFW resources
            GLFW.terminate

它编译并运行时没有任何报告错误,但它只显示清晰的颜色;根本没有绘制三角形。

0 个答案:

没有答案