在PyOpenGL中将数据传递给glBufferData,空白屏幕

时间:2018-04-09 18:32:54

标签: python python-3.x opengl shader pyopengl

我正在使用PyOpenGL绘制一个简单的三角形。但是,我只得到一个空屏幕。我认为问题是我没有正确地将数据传递给glBufferData。我试着按照this stackoverflow question中的答案,但没有结果。着色器编译和工作正常,因为使用glBegin()和glVertex()工作。但是,使用glDrawElements或glDrawArrays绘图不起作用。这是我的代码(我在OpenGL窗口中使用pygame):

import numpy as np
import pygame as pg
from pygame.locals import *
from array import array
SCREEN_SIZE = (800, 600)


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

def resize(width, height):

    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(60.0, float(width)/height, .1, 1000.)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()




def create_shader(shader_type,source):
    shader = glCreateShader(shader_type)
    glShaderSource(shader,source)
    glCompileShader(shader)
    print(glGetShaderiv(shader, GL_COMPILE_STATUS, None))
    return shader

pg.init()
screen = pg.display.set_mode(SCREEN_SIZE, HWSURFACE|OPENGL|DOUBLEBUF)

resize(*SCREEN_SIZE)

#creating and compiling fragment shader
fragment = create_shader(GL_FRAGMENT_SHADER,"""

#version 130

out vec4 finalColor; 

void main()
{
    finalColor = vec4(.0,0.0,1.0,1.0);
}
""")

#creating and compiling vertex shader
vertex = create_shader(GL_VERTEX_SHADER,"""

#version 130


in vec3 pos;

void main()
{   

    gl_Position=gl_ProjectionMatrix*gl_ModelViewMatrix *vec4(pos,1.0);



}
""")

#create and link program
program = glCreateProgram()
glAttachShader(program, fragment)
glAttachShader(program, vertex)
glLinkProgram(program)
#get location of the position variable in vertex shader
posAttrib = glGetAttribLocation(program, "pos")


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

#specify the integer and float types to use in the glGenBuffer function
dtypei=np.dtype('<u4')
dtypef=np.dtype('<f4')

glBindVertexArray(vao)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, np.array([0,1,2],dtype=dtypei), GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, vbo)

vert=[-1.5, -0.5, -4.0, -0.5, -0.5, -4.0, -0.5, 0.5, -4.0]
nparray = np.array(vert,dtype=dtypef)
glBufferData(GL_ARRAY_BUFFER, nparray, GL_STATIC_DRAW)

#can also try using the array library
#ar = array("f",vert)
#glBufferData(GL_ARRAY_BUFFER, ar.tostring(), GL_STATIC_DRAW)

#specify how the variable pos gets data from the buffer data
glEnableVertexAttribArray(posAttrib)
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 3*4,0)

while 1:


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0, 1.0, 1.0, 0.0)

    glUseProgram(program)
    glBindVertexArray(vao)
    #this draw function produces NOTHING
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0)
    #can also try using glDrawArrays
    #glDrawArrays(GL_TRIANGLES, 0, 3)

    #this drawing produces a triangle
    #glBegin(GL_TRIANGLES)
    #glColor3f( 0,1,0 )
    #glVertex3f( -1.5, -0.5, -4.0 )
    #glColor3f( 0,1,1 )
    #glVertex3f( -0.5, -0.5, -4.0 )
    #glColor3f( 1,1,0 )
    #glVertex3f( -0.5, 0.5, -4.0 )    
    #glEnd()



    pg.display.flip()
    pg.time.delay(10)

您可以取消注释glBegin()... glEnd()部分,您将看到将绘制一个蓝色三角形,因此着色器工作正常。

我试图改变变量dtypei和dtypef(分别对应于传递给glGenBuffers的numpy数组的int类型的float类型),没有运气。可以尝试的不同类型是

dtypei=np.dtype('<i4')
dtypei=np.dtype('>i4')
dtypei=np.dtype('=i4')
dtypei=np.int32

dtypei=np.dtype('<u4')
dtypei=np.dtype('>u4')
dtypei=np.dtype('=u4')
dtypei=np.uint32

dtypef=np.dtype('>f4')
dtypef=np.dtype('<f4')
dtypef=np.dtype('=f4')
dtypef=np.float32

对应于具有不同字节顺序的整数/浮点数(uint32,int32和float32可能是多余的)。见documentation。我也尝试使用数组库中的数组对象,这也是在其他stackoverflow帖子中提出的,也没有任何结果

我真的迷失在这里。

1 个答案:

答案 0 :(得分:3)

问题不是numpy数据类型对象,而是调用glVertexAttribPointerglDrawElements

glVertexAttribPointer的第6个参数的数据类型必须为ctypes.c_void_p

这意味着您必须使用ctypes.cast

glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 3*4, ctypes.cast(0, ctypes.c_void_p))

None

glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 3*4, None)


glDrawElements

的第4个参数也是如此

无论

glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, ctypes.cast(0, ctypes.c_void_p))

glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, None)