使用 glDrawElements 时出现黑屏

getting a black screen when using glDrawElements

import textwrap
import numpy as np

from ctypes import *
from OpenGL.GL import *
from OpenGL.GL.ARB.multitexture import *
from OpenGL.GLU import *
from OpenGL.GLUT import *


class TestOpenglManager():

    # -------- Magic functions --------
    def __init__(self):
        self.window_width = 800
        self.window_height = 800

    # -------- Glut stuff --------
    def reshape(self, w, h):
        self.window_width = w
        self.window_height = h

    def animate(self):
        glutPostRedisplay()

    def visible(self, vis):
        if (vis == GLUT_VISIBLE):
            glutIdleFunc(self.animate)
        else:
            glutIdleFunc(0)

    def key_pressed(self, *args):
        if args[0] == b"\x1b":
            sys.exit()

    def run(self):
        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
        glutInitWindowSize(self.window_width, self.window_height)
        glutInitWindowPosition(800, 100)
        glutCreateWindow(b'Test')

        glutDisplayFunc(self.display)
        glutReshapeFunc(self.reshape)
        glutIdleFunc(self.animate)
        glutVisibilityFunc(self.visible)
        glutKeyboardFunc(self.key_pressed)

        self.init()
        glutMainLoop()

    # -------- Resource allocation --------
    def init_shaders(self):
        def make_vs(source):
            vs = glCreateShader(GL_VERTEX_SHADER)
            glShaderSource(vs, source)
            glCompileShader(vs)

            result = glGetShaderiv(vs, GL_COMPILE_STATUS)
            if not(result):
                raise Exception("Error: {0}".format(
                    glGetShaderInfoLog(vs)
                ))
            return vs

        def make_fs(source):
            fs = glCreateShader(GL_FRAGMENT_SHADER)
            glShaderSource(fs, source)
            glCompileShader(fs)

            result = glGetShaderiv(fs, GL_COMPILE_STATUS)
            if not(result):
                raise Exception("Error: {0}".format(
                    glGetShaderInfoLog(fs)
                ))
            return fs

        def make_program(vs, fs):
            program = glCreateProgram()
            glAttachShader(program, vs)
            glAttachShader(program, fs)
            glLinkProgram(program)
            return program

        vs = textwrap.dedent("""
            #version 130
            in vec3 position;

            void main()
            {
                gl_Position = vec4(position, 1.0f);
            }
        """)
        fs = textwrap.dedent("""
            #version 130

            out vec4 frag_color;

            uniform vec3 color;

            void main() {
                frag_color = vec4(color,1.0);
            }
        """)
        self.prog = make_program(make_vs(vs), make_fs(fs))

    def init_vbos(self):
        vertices = np.array([
            # Positions
            0.5,  0.5, 0.0,
            0.5, -0.5, 0.0,
            -0.5, -0.5, 0.0,
            -0.5,  0.5, 0.0,
        ], dtype=np.float32)

        indices = np.array([
            0, 1, 3,
            1, 2, 3
        ], dtype=np.int32)

        vao_id = glGenVertexArrays(1)
        vbo_id = glGenBuffers(1)
        ebo_id = glGenBuffers(1)

        glBindVertexArray(vao_id)

        print("Vertices: Uploading {0} bytes".format(
            ArrayDatatype.arrayByteCount(vertices)))
        glBindBuffer(GL_ARRAY_BUFFER, vbo_id)
        glBufferData(
            GL_ARRAY_BUFFER,
            ArrayDatatype.arrayByteCount(vertices),
            vertices, GL_STATIC_DRAW
        )

        print("Indices: Uploading {0} bytes".format(
            ArrayDatatype.arrayByteCount(indices)))
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_id)
        glBufferData(
            GL_ELEMENT_ARRAY_BUFFER,
            ArrayDatatype.arrayByteCount(indices),
            indices, GL_STATIC_DRAW
        )

        print("Position: Location {0}".format(
            glGetAttribLocation(self.prog, "position")))
        vertex_stride = 3
        glEnableVertexAttribArray(glGetAttribLocation(self.prog, "position"))
        glVertexAttribPointer(glGetAttribLocation(self.prog, "position"),
                              3, GL_FLOAT, GL_FALSE, vertex_stride, c_void_p(0)
                              )

        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.obj_metadata = {
            "vao_id": vao_id,
            "vbo_id": vbo_id,
            "ebo_id": ebo_id,
            "type": "3v3c3t",
            "stride": vertex_stride,
            "indices": len(indices),
            "vertices": vertices,
            "num_triangles": int(len(vertices) / vertex_stride),
            "num_vertices": len(vertices)
        }

    def init(self):
        glClearColor(0.0, 0.0, 0.0, 0.0)
        # glEnable(GL_MULTISAMPLE)
        # glEnable(GL_DEPTH_TEST)
        # glEnable(GL_TEXTURE_2D)

        self.init_shaders()
        self.init_vbos()

    def display(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glBindVertexArray(self.obj_metadata["vao_id"])

        glUseProgram(self.prog)
        glUniform3f(glGetUniformLocation(self.prog, "color"), 0.0, 1.0, 0.0)
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)

        glBindVertexArray(0)
        glUseProgram(0)
        glBindVertexArray(0)
        glutSwapBuffers()


if __name__ == "__main__":
    TestOpenglManager().run()

一段时间以来,我一直在试图弄清楚上面的代码片段可能出了什么问题,但我不明白出了什么问题,它应该绘制一个绿色三角形,但我会得到一个黑屏

怎么回事?

首先你的vertex_stride是不正确的。应该是 0 而不是 3。最后使用 PyOpenGL 在调用 glDrawElements 时需要传递 Nonectypes.c_void_p(0) 而不是 0.

关键是步幅是每个顶点属性之间的字节偏移量。因此,由于您的顶点布局为:

X Y Z
X Y Z
X Y Z

然后在下一对X, Y, Z之间有0个字节的偏移量。但是,如果您的顶点是以这种方式布置的:

X Y Z R G B
X Y Z R G B
X Y Z R G B

那么步幅为 3(或更准确地说 3 * sizeof(float))是正确的。