使用 PyOpenGL 着色器绘制多个对象

问题描述 投票:0回答:1

我刚刚开始使用 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()```
python opengl 3d shader pyopengl
1个回答
0
投票

顶点数组对象和着色器程序没有绑定。在绘制网格之前必须绑定顶点数组对象。 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)

        # [...]
© www.soinside.com 2019 - 2024. All rights reserved.