将数据传递给 PyOpenGL 中的 glBufferData,空屏幕
passing data to glBufferData in PyOpenGL, empty screen
我正在使用 PyOpenGL 绘制一个简单的三角形。但是,我只得到一个空屏幕。我认为问题是我没有正确地将数据传递给 glBufferData。我尝试按照 this Whosebug question 中的答案进行操作,但没有结果。由于使用 glBegin() 和 glVertex() 进行绘图,因此着色器可以正常编译和工作。但是,使用 glDrawElements 或 glDrawArrays 绘图不起作用。这是我的代码(我为 OpenGL window 使用 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
对应于 integers/floats 具有不同的字节顺序(uint32、int32 和 float32 可能是多余的)。看到这个 documentation。我也尝试使用数组库中的数组对象,正如另一个 Whosebug post 中所建议的那样,也没有任何结果
我真的迷路了
问题不在于 numpy 数据类型对象,而是调用 glVertexAttribPointer
和 glDrawElements
:
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)
的第4个参数也是如此
两者都
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, ctypes.cast(0, ctypes.c_void_p))
或
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, None)
我正在使用 PyOpenGL 绘制一个简单的三角形。但是,我只得到一个空屏幕。我认为问题是我没有正确地将数据传递给 glBufferData。我尝试按照 this Whosebug question 中的答案进行操作,但没有结果。由于使用 glBegin() 和 glVertex() 进行绘图,因此着色器可以正常编译和工作。但是,使用 glDrawElements 或 glDrawArrays 绘图不起作用。这是我的代码(我为 OpenGL window 使用 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
对应于 integers/floats 具有不同的字节顺序(uint32、int32 和 float32 可能是多余的)。看到这个 documentation。我也尝试使用数组库中的数组对象,正如另一个 Whosebug post 中所建议的那样,也没有任何结果
我真的迷路了
问题不在于 numpy 数据类型对象,而是调用 glVertexAttribPointer
和 glDrawElements
:
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)
的第4个参数也是如此
两者都
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, ctypes.cast(0, ctypes.c_void_p))
或
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, None)