使用PyOpenGL与GLFW绘制单点时glVertexAttribPointer报1282错误求助
OpenGL glVertexAttribPointer调用错误排查与修复
问题概述
使用Python 3.10.8开发OpenGL程序,拆分为3个文件后,执行glVertexAttribPointer(main.py第70行)时出现错误,调试未定位到有效原因,参考相关解决方案后需针对性修复建议。
相关代码
main.py
import glfw import Shaders from OpenGL.GL import * from OpenGL.GLUT import * from Math_3d import Vector2f class Window: def __init__(self, width: int, height: int, title: str): if not glfw.init(): raise Exception("glfw can not be initialized") glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) self._win = glfw.create_window(width, height, title, None, None) if not self._win: glfw.terminate() raise Exception("glfw window can not be created") glfw.set_window_pos(self._win, 400, 200) glfw.make_context_current(self._win) def createshaders(self): # Request program and shader slots from the GPU program = glCreateProgram() vertex = glCreateShader(GL_VERTEX_SHADER) fragment = glCreateShader(GL_FRAGMENT_SHADER) # Set shader sources glShaderSource(vertex, Shaders.vertex_code) glShaderSource(fragment, Shaders.fragment_code) # Compile shaders glCompileShader(vertex) glCompileShader(fragment) if not glGetShaderiv(vertex, GL_COMPILE_STATUS): report_shader = glGetShaderInfoLog(vertex) print(report_shader) raise RuntimeError("Vertex shader compilation error") if not glGetShaderiv(fragment, GL_COMPILE_STATUS): report_frag = glGetShaderInfoLog(fragment) print(report_frag) raise RuntimeError("Fragment shader compilation error") # Link objects to program glAttachShader(program, vertex) glAttachShader(program, fragment) glLinkProgram(program) if not glGetProgramiv(program, GL_LINK_STATUS): print(glGetProgramInfoLog(program)) raise RuntimeError('Linking error') # Get rid of shaders glDetachShader(program, vertex) glDetachShader(program, fragment) # Make default program to run glUseProgram(program) # Vertex Buffer Object # Create point vertex data v2f_1 = Vector2f(0.0, 0.0) # Request a buffer slot from GPU buffer = glGenBuffers(1) # Make this buffer the default one glBindBuffer(GL_ARRAY_BUFFER, buffer) strides = v2f_1.data.strides[0] loc = glGetAttribLocation(program, 'position') glEnableVertexAttribArray(loc) glVertexAttribPointer(loc, 2, GL_FLOAT, False, strides, None) # glBufferData(GL_ARRAY_BUFFER, v2f_1, v2f_1, GL_DYNAMIC_DRAW) def renderscene(self): while not glfw.window_should_close(self._win): glfw.poll_events() glClear(GL_COLOR_BUFFER_BIT) glDrawArrays(GL_POINTS, 0, 1) glfw.swap_buffers(self._win) glfw.terminate() if __name__ == '__main__': win = Window(1024, 768, "GLFW Window") win.createshaders() # Create and initialize shaders and initialize Vertex Buffer Object win.renderscene() # Swap buffer and render scene
Shaders.py
vertex_code = """ attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } """ fragment_code = """ void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } """
Math_3d.py
import numpy as np class Vector2f: def __init__(self, x, y): self.data = np.array([x, y], dtype=np.float32) if __name__ == '__main__': vec2 = Vector2f(0.0, 0.0) print(vec2.data) print(type(vec2.data.strides[0])) print(vec2.data.strides[0])
错误原因分析
- 缺失VBO数据填充:代码中注释掉了
glBufferData调用,导致绑定的GL_ARRAY_BUFFER为空,glVertexAttribPointer无法找到有效数据存储位置。 - 核心模式未使用VAO:OpenGL 3.3核心配置文件要求必须绑定顶点数组对象(VAO),否则顶点属性配置无法被正确保存,会触发
glVertexAttribPointer调用错误。 - glBufferData参数错误:即使取消注释,原代码中
glBufferData的第二个和第三个参数传入的是v2f_1(Vector2f对象),而非实际的numpy数组v2f_1.data,会导致数据传递失败。
修复方案
1. 添加VAO创建与绑定
在createshaders方法中,VBO创建前添加VAO的初始化:
# 核心模式必须绑定VAO vao = glGenVertexArrays(1) glBindVertexArray(vao)
2. 修复glBufferData调用
取消注释并修正参数:
# 向VBO填充数据 glBufferData(GL_ARRAY_BUFFER, v2f_1.data.nbytes, v2f_1.data, GL_DYNAMIC_DRAW)
3. 优化strides参数
由于数据是紧密排列的,可直接传入0(OpenGL会自动计算步长),或保留原strides值(需确保正确):
# 步长设为0,或使用v2f_1.data.strides[0] glVertexAttribPointer(loc, 2, GL_FLOAT, False, 0, None)
修改后的createshaders方法关键片段
# Make default program to run glUseProgram(program) # 核心模式必须绑定VAO vao = glGenVertexArrays(1) glBindVertexArray(vao) # Vertex Buffer Object # Create point vertex data v2f_1 = Vector2f(0.0, 0.0) # Request a buffer slot from GPU buffer = glGenBuffers(1) # Make this buffer the default one glBindBuffer(GL_ARRAY_BUFFER, buffer) # 向VBO填充数据 glBufferData(GL_ARRAY_BUFFER, v2f_1.data.nbytes, v2f_1.data, GL_DYNAMIC_DRAW) loc = glGetAttribLocation(program, 'position') glEnableVertexAttribArray(loc) # 使用0作为步长(紧密排列数据) glVertexAttribPointer(loc, 2, GL_FLOAT, False, 0, None)
内容的提问来源于stack exchange,提问作者Treslav
相关产品推荐
相关产品推荐

