【问题标题】:Core-profile OpenGL not drawing anything核心配置文件 OpenGL 没有绘制任何东西
【发布时间】:2020-08-18 04:46:23
【问题描述】:

我最近接触了 OpenGL,并使用 PyOpenGL 和固定功能管道(我知道,我知道)来绘制立方体和其他东西。

不管怎样,每个人都告诉我,固定功能很糟糕而且不推荐使用,所以我刚刚进入了核心配置文件 OpenGL。我一直在关注 C++ 中的 this tutorial,只需使用基本相同的库将所有内容转换为 Python。

我已经到了想要使用 VBO 和 VAO 渲染单个 2D 三角形的地步,并且代码运行,但实际上并没有绘制任何东西。

在这里(请记住,我对此完全陌生,所以我可能在某个地方搞砸了一个基本函数调用,而且我真的不知道一切是如何工作的):

import numpy as np
import glfw
from OpenGL.GL import *

def main():

    glfw.init()
    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 5)
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    window = glfw.create_window(800, 600, "helo wold", None, None)

    glfw.make_context_current(window)


    vertices = np.array([-0.5, -0.5, 0, 0.5, -0.5, 0, 0, 0.5, 0], dtype = 'float32')

    vertexShaderSource = '''#version 450 core
    layout (location = 0) in vec3 aPos;
    void main() {
        gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    }
    '''

    vertexShader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertexShader, vertexShaderSource)
    glCompileShader(vertexShader)

    fragmentShaderSource = '''#version 450 core
    out vec4 FragColor;
    void main() {
        FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
    }
    '''

    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragmentShader, fragmentShaderSource)
    glCompileShader(fragmentShader)

    shaderProgram = glCreateProgram(1)
    glAttachShader(shaderProgram, vertexShader)
    glAttachShader(shaderProgram, fragmentShader)
    glLinkProgram(shaderProgram)

    glDeleteShader(vertexShader)
    glDeleteShader(fragmentShader)

    vbo, vao = glGenBuffers(1), glGenVertexArrays(1)

    glBindVertexArray(vao)
    glBindBuffer(GL_ARRAY_BUFFER, vbo)
    glBufferData(GL_ARRAY_BUFFER, len(vertices), vertices, GL_STATIC_DRAW)

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, 0)
    glEnableVertexAttribArray(0)

    glBindBuffer(GL_ARRAY_BUFFER, 0)
    glBindVertexArray(0)

    while not glfw.window_should_close(window):

        glClearColor(0.2, 0.3, 0.3, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)

        glUseProgram(shaderProgram)
        glBindVertexArray(vao)
        glDrawArrays(GL_TRIANGLES, 0, 3)

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.terminate()

if __name__ == '__main__':
    main()

它可以很好地打开窗口,并且具有我给它的背景颜色,但它不会以任何方式绘制三角形。

如果有人能告诉我我做错了什么,我会很高兴,谢谢!

【问题讨论】:

    标签: python opengl vbo pyopengl vao


    【解决方案1】:

    glBufferData 的第二个参数必须是字节大小,len(vertices)*4 而不是len(vertices)

    glBufferData(GL_ARRAY_BUFFER, len(vertices)*4, vertices, GL_STATIC_DRAW)
    

    由于PyOpenGL的glBufferData被重载,size参数可以省略(如果数据是ctypes数组或者numpy.array):

    glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW)
    

    glVertexAttribPointer 的最后一个参数是const GLvoid * 类型。因此它必须是Nonectypes.c_void_p(0) 而不是0:

    要么

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, None)
    

    import ctypes
    
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, ctypes.c_void_p(0))
    

    我还建议评估着色器是否编译成功 (glGetShaderiv):

    vertexShader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertexShader, vertexShaderSource)
    glCompileShader(vertexShader)
    if not glGetShaderiv(vertexShader, GL_COMPILE_STATUS ):
        print('vertex shader compile error:')
        print(glGetShaderInfoLog(vertexShader))
    
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragmentShader, fragmentShaderSource)
    glCompileShader(fragmentShader)
    if not glGetShaderiv(fragmentShader, GL_COMPILE_STATUS):
        print('fragment shader compile error:')
        print(glGetShaderInfoLog(fragmentShader))
    

    并且程序链接成功(glGetProgramiv):

    glLinkProgram(shaderProgram)
    if not glGetProgramiv(shaderProgram, GL_LINK_STATUS):
        print('link error:')
        print(glGetProgramInfoLog(shaderProgram))
    

    【讨论】:

    • 非常感谢,这对我有用!有没有办法概括glVertexAttribPointer 的步幅?只给它 12 因为我知道有 3 个 4 字节的浮点数让我处于边缘。
    • @Parashoo stride 必须以字节为单位指定。但是,由于您只有顶点,因此 stride 可以设置为 0。如果 stride 为 0,则它由元组大小 (3) 和输入 (GL_FLOAT)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多