简体   繁体   中英

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()

I've been trying to figure out for a while what could be wrong with the above snippet and I don't understand what's wrong, it should drawing a green triangle but instead I'll get a black screen

What's going on?

First of all your vertex_stride is incorrect. It should be 0 not 3 . Lastly with PyOpenGL when calling glDrawElements you need to pass None or ctypes.c_void_p(0) and not 0 .

The thing is that the stride is a byte offset between each vertex attribute. So as your vertex is laid out as:

X Y Z
X Y Z
X Y Z

Then there is an offset of 0 bytes between the next pair of X, Y, Z . However if your vertex was laid out in this manner:

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

Then having the stride as 3 (or more correctly 3 * sizeof(float) ) would be correct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM