glDrawElements在PyOpenGL中绘制一个立方体

时间:2015-11-27 14:11:59

标签: python opengl pyopengl

我最近开始通过Python学习OpenGL,感谢几个教程(特别是Nicolas P. Rougier的一个:http://www.labri.fr/perso/nrougier/teaching/opengl/)。

我现在正在切换到3D,我正在尝试绘制一个立方体。

因此,我设法得到一些不渲染立方体的三角形(这似乎是正常的,因为我没有复制我的顶点,我使用glDrawArrays函数)。

然而,之后,我建立了一个索引" vector"进一步使用glDrawElements函数来渲染我的立方体。因此,我没有收到任何错误,但屏幕上没有任何内容。

我希望你能得到一些帮助!

这是我的代码:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import ctypes
import numpy as np
import OpenGL.GL as gl
import OpenGL.GLUT as glut

vertex_code = """

    uniform float scale;
    uniform mat4 matCam;
    attribute vec4 color;
    attribute vec3 position;
    varying vec4 v_color;
    void main()
    {
        gl_Position = matCam*vec4(scale*position, 1.0);
        v_color = color;
    } """

fragment_code = """
    varying vec4 v_color;
    void main()
    {
        gl_FragColor = v_color;
    } """

def display():
    gl.glClear(gl.GL_COLOR_BUFFER_BIT)
    #gl.glDrawArrays(gl.GL_TRIANGLES, 0, 12)

    gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, index) # render nothing (i.e. only the background color)
    glut.glutSwapBuffers()

def reshape(width,height):
    gl.glViewport(0, 0, width, height)

def keyboard( key, x, y ):
    if key == '\033':
        sys.exit( )

def timer(fps):
    global clock
    clock += 0.0005*1000.0/fps
    print(clock)
#    eye = np.array([0,0,1])
#    center = np.array([0,clock,0])
#    up = np.array([0,1,0])
#    mat = computeLookAtMatrix(eye, center, up)
    theta = clock;
    mat = np.array([[np.cos(theta), 0, np.sin(theta), 0],
                [0, 1, 0, 0],
                [-np.sin(theta), 0, np.cos(theta), 0],
                [0, 0, 0, 1]])
    loc = gl.glGetUniformLocation(program, "matCam")
    gl.glUniformMatrix4fv(loc, 1, False, mat)



    glut.glutTimerFunc(1000/fps, timer, fps)
    glut.glutPostRedisplay()


# GLUT init
# --------------------------------------
glut.glutInit()
glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGBA)
glut.glutCreateWindow('Hello world!')
glut.glutReshapeWindow(512,512)
glut.glutReshapeFunc(reshape)
glut.glutDisplayFunc(display)
glut.glutKeyboardFunc(keyboard)
glut.glutTimerFunc(1000/60, timer, 60)

# Build data
# --------------------------------------
data = np.zeros(8, [("position", np.float32, 3),
                    ("color",    np.float32, 4)])

data['color']    = [ (1,0,0,1), (0,1,0,1), (0,0,1,1), (1,1,0,1),
                    (1,0,0,1), (0,1,0,1), (0,0,1,1), (1,1,0,1) ]

data['position'] = [ (-1,-1,1),
                     (1,-1,1),
                        (1,1,1),   
                        (-1,1,1),
                        (-1,-1,-1),
                        (1,-1,-1),
                        (1,1,-1),
                        (-1,1,-1)]

index = np.array([0,1,2,
                2,3,0,
                1,5,6,
                6,2,1,
                7,6,5,
                5,4,7,
                4,0,3,
                3,7,4,
                4,5,1,
                1,0,4,
                3,2,6,
                6,7,3])

# Build & activate program
# --------------------------------------

# Request a program and shader slots from GPU
program  = gl.glCreateProgram()
vertex   = gl.glCreateShader(gl.GL_VERTEX_SHADER)
fragment = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)

# Set shaders source
gl.glShaderSource(vertex, vertex_code)
gl.glShaderSource(fragment, fragment_code)

# Compile shaders
gl.glCompileShader(vertex)
gl.glCompileShader(fragment)

# Attach shader objects to the program
gl.glAttachShader(program, vertex)
gl.glAttachShader(program, fragment)

# Build program
gl.glLinkProgram(program)

# Get rid of shaders (no more needed)
gl.glDetachShader(program, vertex)
gl.glDetachShader(program, fragment)

# Make program the default program
gl.glUseProgram(program)


# Build buffer
# --------------------------------------

# Request a buffer slot from GPU
buffer = gl.glGenBuffers(1)

# Make this buffer the default one
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)

# Upload data
gl.glBufferData(gl.GL_ARRAY_BUFFER, data.nbytes, data, gl.GL_DYNAMIC_DRAW)

# same for index buffer
buffer_index= gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, buffer_index)
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, index.nbytes, index, gl.GL_STATIC_DRAW)


# Bind attributes
# --------------------------------------
stride = data.strides[0]
offset = ctypes.c_void_p(0)
loc = gl.glGetAttribLocation(program, "position")
gl.glEnableVertexAttribArray(loc)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)

offset = ctypes.c_void_p(data.dtype["position"].itemsize)
loc = gl.glGetAttribLocation(program, "color")
gl.glEnableVertexAttribArray(loc)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
gl.glVertexAttribPointer(loc, 4, gl.GL_FLOAT, False, stride, offset)

gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, buffer_index)

# Bind uniforms
# --------------------------------------
loc = gl.glGetUniformLocation(program, "scale")
gl.glUniform1f(loc, 0.5)
clock = 0

loc = gl.glGetUniformLocation(program, "matCam")
print(loc)
gl.glUniformMatrix4fv(loc, 1, False, np.eye(4))

# Enter mainloop
# --------------------------------------
glut.glutMainLoop()

1 个答案:

答案 0 :(得分:1)

gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, index)

index参数有两种不同的含义,具体取决于ELEMENT_ARRAY_BUFFER是否绑定:

  • 如果没有绑定:则指定指向存储索引的客户机内存的指针
  • 如果绑定了ELEMENT_ARRAY_BUFFER,则index参数指定此缓冲区的偏移量。这定义了索引开始在缓冲区中的位置。

在你的情况下,绑定了一个缓冲区,所以你告诉OpenGL从缓冲区的某个地方开始。但你想要的是从缓冲区的开头开始,因此你必须将索引设置为0。

gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, ctypes.c_void_p(0))