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



我正在尝试让一个基本的"在屏幕上画一个三角形"的例子工作,但在 Haskell 中使用 gl 和 GLFW-b 包。

我的代码在这里:

-- 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 coren",
    "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 coren",
    "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

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

请注意,当我编译和运行您的程序时,我收到着色器编译和程序链接错误。 具体来说,我收到错误:

Vertex Shader Compile Error:
0:1(18): error: syntax error, unexpected $end
Fragment Shader Compile Error:
0:1(18): error: syntax error, unexpected $end

当然,也有链接错误。

仔细检查,您的glShaderSource呼叫存在缺陷。 尽管它们为每个着色器传递六行的行指针和行长度数组,但行计数参数1。 如果我修改getSrcPointer的最后一行以返回行数:

return (linesPtrsPtr,lengthsPtr, (fromIntegral.length) linesLengths)

然后将此计数传递给每种情况下的glShaderSource调用:

(linesPtrsPtr,lengthsPtr,count) <- getSrcPointer vertexShaderSource
glShaderSource vertexShader count linesPtrsPtr lengthsPtr
...
(linesPtrsPtr,lengthsPtr,count) <- getSrcPointer fragmentShaderSource
glShaderSource fragmentShader count linesPtrsPtr lengthsPtr

那么你的程序工作正常。

祝三角愉快!

最新更新