使用Python OpenGL代码时,集成显卡与1050Ti渲染点数组结果不同的原因?
OpenGL渲染点数组在GTX1050Ti与集成显卡表现不一致问题
本人使用华硕TUF FX505G笔记本(搭载集成显卡与GTX1050Ti),用Python 3.10.8编写OpenGL代码渲染点数组时,发现不同显卡渲染结果有差异:GTX1050Ti下渲染不符合预期,集成显卡表现正常。


以下是相关代码:
Main.py
import glfw import Shader from OpenGL.GL import * from Math_3d import Vector3f class Window: def __init__(self, width: int, height: int, title: str): # Exit keyboard flag self.exitNow = False # Vertex Buffer Object # Create point vertex data self.v3f = Vector3f.data if not glfw.init(): raise Exception("glfw can not be initialized") # OpenGL 4.0 version for shader subroutines and Dynamically uniform expression support glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2) 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) # Enable key events # glfw.set_input_mode(self._win, glfw.STICKY_KEYS, GL_TRUE) # Enable key event callback from keyboard # glfw.set_key_callback(self._win, self.onKeyboard) self.program = glCreateProgram() self.buffer = glGenBuffers(1) def initialize(self): # Request program and shader slots from the GPU vertex = glCreateShader(GL_VERTEX_SHADER) fragment = glCreateShader(GL_FRAGMENT_SHADER) # Set shader sources glShaderSource(vertex, Shader.vertex_code) glShaderSource(fragment, Shader.fragment_code) # Compile shaders and check that they have compiled 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 shaders to program glAttachShader(self.program, vertex) glAttachShader(self.program, fragment) glLinkProgram(self.program) if not glGetProgramiv(self.program, GL_LINK_STATUS): print(glGetProgramInfoLog(self.program)) raise RuntimeError('Linking error') # Get rid of shaders glDetachShader(self.program, vertex) glDetachShader(self.program, fragment) # Make default program to run glUseProgram(self.program) # Request a buffer slot from GPU # buffer = glGenBuffers(1) # Make this buffer the default one glBindBuffer(GL_ARRAY_BUFFER, self.buffer) # Vertex Array Buffer vao = glGenVertexArrays(1) glBindVertexArray(vao) loc = glGetAttribLocation(self.program, 'position') glEnableVertexAttribArray(loc) glVertexAttribPointer(loc, self.v3f.itemsize, GL_FLOAT, False, self.v3f.data.strides[0], None) glBufferData(GL_ARRAY_BUFFER, self.v3f.data.nbytes, self.v3f.data, GL_DYNAMIC_DRAW) def renderscene(self): while not glfw.window_should_close(self._win) and not self.exitNow: glClear(GL_COLOR_BUFFER_BIT) glPointSize(30) glDrawArrays(GL_POINTS, 0, self.v3f.itemsize) glfw.swap_buffers(self._win) # Do not refresh screen before receiving event glfw.wait_events() glDisableVertexAttribArray(0) glUseProgram(0) glfw.terminate() if __name__ == '__main__': win = Window(1024, 768, "GLFW Window - Rotate glPoints") win.initialize() # Create and initialize shaders and initialize Vertex Buffer Object win.renderscene() # Swap buffer and render scene
Shader.py
vertex_code = """ attribute vec3 position; void main() { gl_Position = vec4(position, 1.0); } """ fragment_code = """ void main() { gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0); } """
Math_3d.py
from OpenGL.GL import * import numpy as np np.set_printoptions(precision=3, suppress=True) class Vector3f: data = np.array([[0.5, 0.5, 0], [-0.5, 0.5, 0], [-0.5, -0.5, 0], [0.5, -0.5, 0]], dtype=np.float32) def Rotate(self): pass if __name__ == '__main__': vec3 = Vector3f print(vec3.data) print("Item size: ", vec3.data.itemsize) print("Strides: ", vec3.data.strides[0]) print("Bytes:", vec3.data.nbytes)
本人在两种显卡环境下都运行了代码,认为不存在明显的缓冲区溢出问题。
问题原因与修复方案
代码存在两个关键错误,这是导致显卡表现差异的核心原因:
glVertexAttribPointer参数错误
该函数第二个参数是顶点属性的分量数,你传入的self.v3f.itemsize是单个float32元素的字节数(4),但你的顶点是vec3类型,正确值应为3。glDrawArrays顶点数量参数错误
该函数第三个参数是要渲染的顶点总数,你用了self.v3f.itemsize(数值碰巧为4),但逻辑上应该用数组的行数self.v3f.shape[0]来表示顶点数量,避免后续数组修改时出现错误。
修正后的关键代码片段:
在initialize方法中:
# 修正顶点属性分量数为3,对应vec3类型 glVertexAttribPointer(loc, 3, GL_FLOAT, False, self.v3f.data.strides[0], None)
在renderscene方法中:
# 用数组行数作为顶点数量,逻辑更准确 glDrawArrays(GL_POINTS, 0, self.v3f.shape[0])
不同显卡对错误参数的容错性不同:集成显卡可能自动兼容了错误参数,而GTX1050Ti严格按照参数解析数据,导致顶点数据读取异常,最终渲染出错误结果。
内容的提问来源于stack exchange,提问作者Treslav
相关产品推荐
相关产品推荐

