python - 使用 PyOpenGL 和 PyQt5 制作 Sphere 的问题
问题描述
我正在尝试在 Python 中使用 OpenGL 制作球体,但屏幕中央只出现一个红点。我的代码如下
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
try:
glUseProgram(self.shader)
glBindVertexArray(self.vao)
glDrawArrays(GL_POINTS, 0, int(self.buff_size/3))
finally:
glBindVertexArray(0)
glUseProgram(0)
def geometry(self):
self.vao = glGenVertexArrays(1)
self.vbo = glGenBuffers(1)
lats = 180
longs = 360
r = 0.5
data = []
for i in range(lats):
lat0 = np.pi * (-0.5 + (i - 1) / lats)
z0 = np.sin(lat0)
zr0 = np.cos(lat0)
lat1 = np.pi * (-0.5 + i / lats)
z1 = np.sin(lat1)
zr1 = np.cos(lat1)
for j in range(longs):
lng = 2 * np.pi * (j - 1) / longs
x_cord = np.cos(lng)
y = np.sin(lng)
data.extend([x_cord * zr0, y * zr0, z0])
data.extend([r * x_cord * zr0, r * y * zr0, r * z0])
data.extend([x_cord * zr1, y * zr1, z1])
data.extend([r * x_cord * zr1, r * y * zr1, r * z1])
data_input = np.array(data, dtype=np.float32)
self.buff_size = len(data_input)
vertex_size = int(data_input.nbytes / self.buff_size) * 3
glUseProgram(self.shader)
glBindVertexArray(self.vao)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, data_input.nbytes, data_input, GL_DYNAMIC_DRAW)
self.vertex_position = glGetAttribLocation(self.shader, 'position')
glVertexAttribPointer(self.vertex_position, 3, GL_FLOAT, GL_FALSE, vertex_size, None)
glEnableVertexAttribArray(self.vertex_position)
glDisableVertexAttribArray(self.vertex_position)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
glUseProgram(0)
我的程序的着色器是:
self.vertex_shader = shaders.compileShader(
"""
#version 330
in vec3 pos;
uniform mat4 movement;
void main()
{
gl_Position = movement * vec4(pos, 1.0);
}
"""
, GL_VERTEX_SHADER
)
self.fragment_shader = shaders.compileShader(
"""
#version 330
out vec4 gl_FragColor;
void main()
{
gl_FragColor = vec4(1.0,0.0,0.5,1.0);
}
"""
, GL_FRAGMENT_SHADER
)
self.shader = shaders.compileProgram(self.vertex_shader, self.fragment_shader)
我不知道我哪里有问题。我也尝试使用带有GL_ELEMENT_ARRAY_BUFFER
和glDrawElements
as 的索引,GL_QUAD_STRIP
但没有成功。如果您知道我如何解决此问题,请分享。谢谢
解决方案
顶点属性的名称是 pos
:
in vec3 pos;
所以参数glGetAttribLocation
必须是'pos'而不是'position':
self.vertex_position = glGetAttribLocation(self.shader, 'position')
self.vertex_position = glGetAttribLocation(self.shader, 'pos')
如果规范和启用状态存储在Vertex Array Object中。如果你glDisableVertexAttribArray(self.vertex_position)
,这个状态被存储到了self.vao
。去掉它:
glBindVertexArray(self.vao)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, data_input.nbytes, data_input, GL_DYNAMIC_DRAW)
self.vertex_position = glGetAttribLocation(self.shader, 'pos')
glVertexAttribPointer(self.vertex_position, 3, GL_FLOAT, GL_FALSE, vertex_size, None)
glEnableVertexAttribArray(self.vertex_position)
#glDisableVertexAttribArray(self.vertex_position) # <--- DELETE
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
默认情况下的矩阵 unfiorm 使用所有字段 0 进行初始化。
uniform mat4 movement;
如果您不需要制服,则将其取下。或者通过Identity matrix对其进行初始化。
glUseProgram(self.shader)
ident4x4 = np.identity(4, np.float32)
self.movement_loc = glGetUniformLocation(self.shader, 'movement')
glUniformMatrix4fv(self.movement_loc, 1, GL_FALSE, ident4x4)
或者,您可以使用视图和透视投影矩阵(self.width
并且self.height
是窗口的宽度和高度):
# projection matrix
aspect, ta, near, far = self.width/self.height, np.tan(np.radians(90.0) / 2), 0.1, 10
proj = np.matrix(((1/ta/aspect, 0, 0, 0), (0, 1/ta, 0, 0), (0, 0, -(far+near)/(far-near), -1), (0, 0, -2*far*near/(far-near), 0)), np.float32)
# view matrix
view = np.matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, -3, 1)), np.float32)
glUniformMatrix4fv(self.movement_loc, 1, GL_FALSE, view * proj)
推荐阅读
- html - 您是否有任何功能或工具可以将简单的 html 转换为我喜欢的特殊代码?
- android-studio - android studio中未使用的导入
- css - WordPress 表格(使用 TablePress)将列字体设置为斜体
- regex - 捕获多达三种不同类型的日期?
- java - 提高从 oracle 数据库获取数据时的性能
- google-api-nodejs-client - 创建支付请求 API
- javascript - 单个数组中的 Json 对象,需要使用键 meta_value 拆分键上的值
- hybris - 自适应搜索 Hybris 1808 中未提供产品信息
- c# - 如何对动态生成的列中所有行的值求和?
- mysql - 如何忽略 MySQL 中的重复值?