我刚刚开始使用 PyOpenGL 着色器,并且成功绘制了一个 3D 对象,但无法绘制第二个对象。我尝试制作另一个 init() 函数并执行所有 vao 和 vbo 操作两次,然后在绘制对象之间我切换到使用第二个着色器程序,但我无法绘制第二个对象。
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import numpy as np
from math import sin, cos, tan, radians
# Vertex Shader
vertex_shader = """
#version 330
in vec3 position;
in vec3 color;
out vec3 newColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0);
newColor = color;
}
"""
# Fragment Shader
fragment_shader = """
#version 330
in vec3 newColor;
out vec4 outColor;
void main()
{
outColor = vec4(newColor, 1.0);
}
"""
# Cube vertices and colors
vertices = np.array([
# Vertices Colors
[-.1, -.1, -.1], [1, 0, 0],
[.1, -.1, -.1], [0, 1, 0],
[.1, .1, -.1], [0, 0, 1],
[-.1, .1, -.1], [1, 1, 0],
[-.1, -.1, .1], [0, 1, 1],
[.1, -.1, .1], [1, 1, 1],
[.1, .1, .1], [0.5, 0.5, 0.5],
[-.1, .1, .1], [0.5, 0.5, 0.5],
], dtype=np.float32)
indices = np.array([
0, 1, 2, 2, 3, 0, # Front face
1, 5, 6, 6, 2, 1, # Right face
5, 4, 7, 7, 6, 5, # Back face
4, 0, 3, 3, 7, 4, # Left face
3, 2, 6, 6, 7, 3, # Top face
4, 5, 1, 1, 0, 4, # Bottom face
], dtype=np.uint32)
# Cube vertices and colors
vertices2 = np.array([
# Vertices Colors
[.2, -.1, -.1], [1, 0, 0],
[.4, -.1, -.1], [0, 1, 0],
[.4, .1, -.1], [0, 0, 1],
[.2, .1, -.1], [1, 1, 0],
[.2, -.1, .1], [0, 1, 1],
[.4, -.1, .1], [1, 1, 1],
[.4, .1, .1], [0.5, 0.5, 0.5],
[.2, .1, .1], [0.5, 0.5, 0.5],
], dtype=np.float32)
indices2 = np.array([
0, 1, 2, 2, 3, 0, # Front face
1, 5, 6, 6, 2, 1, # Right face
5, 4, 7, 7, 6, 5, # Back face
4, 0, 3, 3, 7, 4, # Left face
3, 2, 6, 6, 7, 3, # Top face
4, 5, 1, 1, 0, 4, # Bottom face
], dtype=np.uint32)
def init1():
# Compile shaders and create shader program
shader_program = compileProgram(compileShader(vertex_shader, GL_VERTEX_SHADER),
compileShader(fragment_shader, GL_FRAGMENT_SHADER))
# Create Vertex Array Object (VAO)
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# Create Vertex Buffer Object (VBO) and Element Buffer Object (EBO)
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
ebo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, GL_STATIC_DRAW)
# Set attribute pointers
stride = 6 * vertices.itemsize
position_offset = ctypes.c_void_p(0)
color_offset = ctypes.c_void_p(3 * vertices.itemsize)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, position_offset)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, color_offset)
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
return shader_program
def init2():
# Compile shaders and create shader program
shader_program2 = compileProgram(compileShader(vertex_shader, GL_VERTEX_SHADER),
compileShader(fragment_shader, GL_FRAGMENT_SHADER))
# Create Vertex Array Object (VAO)
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
# Create Vertex Buffer Object (VBO) and Element Buffer Object (EBO)
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, vertices2.nbytes, vertices2, GL_STATIC_DRAW)
ebo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2.nbytes, indices2, GL_STATIC_DRAW)
# Set attribute pointers
stride = 6 * vertices.itemsize
position_offset = ctypes.c_void_p(0)
color_offset = ctypes.c_void_p(3 * vertices2.itemsize)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, position_offset)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, color_offset)
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
return shader_program2
def main():
# Initialize Pygame
pygame.init()
width, height = 800, 600
pygame.display.set_mode((width, height), pygame.OPENGL | pygame.DOUBLEBUF)
pygame.display.set_caption("Shader Testing")
glViewport(0, 0, width, height)
width, height = 800, 600
shader_program = init1()
shader_program2 = init2()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
glClearColor(0.0, 0.0, 0.0, 0.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# Define the view and projection matrices (unchanged)
view = [1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, -3.0, 1.0]
aspect_ratio = width / height
near = 0.1
far = 100.0
fov = 45.0
top = near * tan(radians(fov) / 2.0)
right = top * aspect_ratio
projection = ([near / right, 0.0, 0.0, 0.0],
[0.0, near / top, 0.0, 0.0],
[0.0, 0.0, -(far + near) / (far - near), -1.0],
[0.0, 0.0, -(2 * far * near) / (far - near), 0.0])
# Define the model matrix (rotate the cube)
angle = pygame.time.get_ticks() / 1000.0 # Rotate the cube over time
model = ([cos(angle), -sin(angle), 0, 0],
[sin(angle), cos(angle), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1])
# Use the shader program
glUseProgram(shader_program)
# Set the model, view, and projection matrices in the shader
model_loc = glGetUniformLocation(shader_program, "model")
view_loc = glGetUniformLocation(shader_program, "view")
projection_loc = glGetUniformLocation(shader_program, "projection")
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(projection_loc, 1, GL_FALSE, projection)
# Draw the cube
glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None)
# Use the shader program
glUseProgram(shader_program2)
# Set the model, view, and projection matrices in the shader
model_loc = glGetUniformLocation(shader_program, "model")
view_loc = glGetUniformLocation(shader_program, "view")
projection_loc = glGetUniformLocation(shader_program, "projection")
glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)
glUniformMatrix4fv(projection_loc, 1, GL_FALSE, projection)
# Draw the cube
glDrawElements(GL_TRIANGLES, len(indices2), GL_UNSIGNED_INT, None)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()```
顶点数组对象和着色器程序没有绑定。在绘制网格之前必须绑定顶点数组对象。 OpenGL 是一个状态引擎。当前绑定的顶点数组对象是全局状态,绘制调用 (
glDraw*
) 使用存储在当前绑定的顶点数组对象中的规范来绘制网格:
def init1():
# [...]
return shader_program, vao
def init2():
# [...]
return shader_program, vao
def main():
# [...]
shader_program, vao = init1()
shader_program2, vao2 = init2()
running = True
while running:
# [...]
glBindVertexArray(vao)
glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None)
# [...]
glBindVertexArray(vao2)
glDrawElements(GL_TRIANGLES, len(indices2), GL_UNSIGNED_INT, None)
# [...]