在Python中向glVertexAttribPointer传递偏移指针报错求助
问题:Python OpenGL中glVertexAttribPointer偏移指针传递报错
报错信息
C:\Users\phill\PycharmProjects\texturebox\venv\Scripts\python.exe C:\Users\phill\PycharmProjects\texturebox\main.py Traceback (most recent call last): File "C:\Users\phill\PycharmProjects\texturebox\main.py", line 29, in <module> main() File "C:\Users\phill\PycharmProjects\texturebox\main.py", line 18, in main m_box = Box() ^^^^^ File "C:\Users\phill\PycharmProjects\texturebox\Box.py", line 60, in __init__ array_colors_offset(*vertices_list) IndexError: invalid index Process finished with exit code 1
需求与参考代码
需要将C语言中glVertexAttribPointer的偏移指针逻辑迁移到Python,对应的C语言实现:
// color attribute glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1);
用户编写的Box.py代码:
from OpenGL import GL as GL import ctypes class Box: def __init__(self): #3 floats for vertices x,y,z 3 floats for color R G B 2 floats for tex co-ords vertices_list = [ 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0 ] indices_list = [ 0, 1, 3, 1, 2, 3 ] self.EBO = None self.VBO = None self.VAO = None self.VAO = GL.glGenVertexArrays(1) self.VBO = GL.glGenBuffers(1) self.EBO = GL.glGenBuffers(1) GL.glBindVertexArray(self.VAO) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.VBO) array_type_vertices = (GL.GLfloat * len(vertices_list)) GL.glBufferData(GL.GL_ARRAY_BUFFER, len(vertices_list) * ctypes.sizeof(ctypes.c_float), array_type_vertices(*vertices_list), GL.GL_STATIC_DRAW) GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.EBO) array_type_indices = (GL.GLint * len(indices_list)) GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, len(indices_list) * ctypes.sizeof(ctypes.c_ulong), array_type_indices(*indices_list), GL.GL_STATIC_DRAW) GL.glVertexAttribPointer( 0, 3, GL.GL_FLOAT, False, 8 * ctypes.sizeof(ctypes.c_float), None ) GL.glEnableVertexAttribArray(0) # attempting to pass the pointer array_colors_offset = (GL.GLfloat * 3) GL.glVertexAttribPointer(1, 3, GL.GL_FLOAT, False, 8 * ctypes.sizeof(ctypes.c_float), array_colors_offset(*vertices_list) ) GL.glEnableVertexAttribArray(1) array_tex_offset = (GL.GLfloat * 6) GL.glVertexAttribPointer(2, 2, GL.GL_FLOAT, GL.GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), array_tex_offset(*vertices_list) ) print("Box()")
解决方案
错误原因
- 错误地用固定长度的
GLfloat数组类型(如GL.GLfloat *3)包装整个vertices_list,数组长度远小于列表长度,解包传入时触发索引越界。 - PyOpenGL中
glVertexAttribPointer的偏移参数不需要创建数组,需传递字节偏移量对应的void指针,和C语言(void*)(偏移字节数)逻辑一致。
正确实现步骤
- 计算各属性的字节偏移量:
- 顶点属性偏移为0(已用
None正确处理) - 颜色属性偏移:
3 * ctypes.sizeof(ctypes.c_float)(对应C语言3*sizeof(float)) - 纹理坐标属性偏移:
6 * ctypes.sizeof(ctypes.c_float)(3个顶点float + 3个颜色float的总字节数)
- 顶点属性偏移为0(已用
- 用
ctypes.c_void_p(偏移量)将字节偏移量转换为PyOpenGL可识别的void指针,传入glVertexAttribPointer最后一个参数。
修改后的完整代码
from OpenGL import GL as GL import ctypes class Box: def __init__(self): #3 floats for vertices x,y,z 3 floats for color R G B 2 floats for tex co-ords vertices_list = [ 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0 ] indices_list = [ 0, 1, 3, 1, 2, 3 ] self.EBO = None self.VBO = None self.VAO = None self.VAO = GL.glGenVertexArrays(1) self.VBO = GL.glGenBuffers(1) self.EBO = GL.glGenBuffers(1) GL.glBindVertexArray(self.VAO) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.VBO) array_type_vertices = (GL.GLfloat * len(vertices_list)) GL.glBufferData(GL.GL_ARRAY_BUFFER, len(vertices_list) * ctypes.sizeof(ctypes.c_float), array_type_vertices(*vertices_list), GL.GL_STATIC_DRAW) GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.EBO) array_type_indices = (GL.GLint * len(indices_list)) GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, len(indices_list) * ctypes.sizeof(ctypes.c_ulong), array_type_indices(*indices_list), GL.GL_STATIC_DRAW) # 顶点属性 GL.glVertexAttribPointer( 0, 3, GL.GL_FLOAT, GL.GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), None ) GL.glEnableVertexAttribArray(0) # 颜色属性(正确传递偏移) color_offset = 3 * ctypes.sizeof(ctypes.c_float) GL.glVertexAttribPointer( 1, 3, GL.GL_FLOAT, GL.GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(color_offset) ) GL.glEnableVertexAttribArray(1) # 纹理坐标属性(正确传递偏移) tex_offset = 6 * ctypes.sizeof(ctypes.c_float) GL.glVertexAttribPointer( 2, 2, GL.GL_FLOAT, GL.GL_FALSE, 8 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(tex_offset) ) GL.glEnableVertexAttribArray(2) print("Box()")
内容的提问来源于stack exchange,提问作者prusso
相关产品推荐
相关产品推荐

