在 PyOpenGL 中使用 VAO 获取黑屏

Getting black screen using VAO in PyOpenGL

我正在使用 python 和 OpenGL 渲染一些 3d 图形。

虽然使用更简单的方法(没有 VAO 和复杂属性指针)成功呈现,如所述here(仅使用两次调用来绑定我的 VBO:glEnableClientState(GL_VERTEX_ARRAY); glVertexPointerf( vbo )

当尝试组合简单的 VBO(仅包含顶点位置数据)和 VAO 时,我总是出现黑屏。为了实现当前的代码版本,我发现这个 SO answer 详细描述了应该如何完成。但是我自己写这个除了黑屏什么都没有。

简化代码:

import OpenGL
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *

from OpenGL.GL import shaders
from OpenGL.arrays import vbo

import numpy as np

glutInit()
glutInitContextVersion(3, 3)
glutInitContextProfile(GLUT_CORE_PROFILE)

### Init Widow
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
glutInitWindowPosition(0, 0)
wind = glutCreateWindow("OpenGL Window")
###

### Load shaders from files and compile into program
with open("vert.glsl", "r") as f:
    vert_text = f.read()
with open("frag.glsl", "r") as f:
    frag_text = f.read()

vert_shader = shaders.compileShader(vert_text, GL_VERTEX_SHADER)
frag_shader = shaders.compileShader(frag_text, GL_FRAGMENT_SHADER)

main_shader = shaders.compileProgram(vert_shader, frag_shader)
###

### Create Vertex Buffer Object
data_arr = np.array(
    [[-1, -1, 0], [0, 1, 0], [1, -1, 0]], dtype=np.float32
)  # define vertices
vvbo = glGenBuffers(1)  # generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vvbo)  # bind buffer

glBufferData(
    GL_ARRAY_BUFFER, data_arr.nbytes, data_arr, GL_DYNAMIC_DRAW
)  # setud data for buffer
###


### Setup VAO
mvao = glGenVertexArrays(1)  # Create Vertex Array Object
glBindVertexArray(mvao)  # Bind VAO

glEnableVertexAttribArray(0)  # Enable attribute: 0
glBindBuffer(GL_ARRAY_BUFFER, vvbo)  # bind vertice's buffer
glVertexAttribPointer(
    0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, 0
)  # setup attribute layout
###

glBindVertexArray(0)  # unbind vao
glDisableVertexAttribArray(0)  # desibale attribute
glBindBuffer(GL_ARRAY_BUFFER, 0)  # unbind data buffer


def showScreen():
    global main_shader, mvao
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)  # clear screen

    glUseProgram(main_shader)  # enable main shader
    glBindVertexArray(mvao)  # bind VAO

    glDrawArrays(GL_TRIANGLES, 0, 3)  # draw

    glBindVertexArray(0)  # unbind VAO
    glUseProgram(0)  # unbind shader

    glutSwapBuffers()  # update screen


glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)

glutMainLoop()

frag.glsl:

#version 330 core
out vec4 _fragColor;
void main()
{
    _fragColor = vec4(0.5);
}

vert.glsl:

#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
    gl_Position = vec4(aPos, 1.0);
}

那么我到底做错了什么?

Python 版本 -> 3.8

如果绑定了命名缓冲区对象,则 glVertexAttribPointer 的第 6 个参数被视为缓冲区对象数据存储中的字节偏移量。但是参数的类型无论如何都是指针(c_void_p).

所以如果偏移量为0,那么第6个参数可以是None或者c_void_p(0):

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, 0)

glVertexAttribPointer(
    0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, None
)