OpenGL只渲染第二个三角形,第一个三角形不可见

1 投票
1 回答
31 浏览
提问于 2025-04-12 21:37

我现在正在用Python编写一个简单的OpenGL程序,使用了glfw和OpenGL.GL这两个库。我有两个三角形想要渲染,但奇怪的是,只有第二个三角形能显示出来,第一个三角形却看不见。

我把问题缩小到了一个简单的例子:

from OpenGL.GL import *
import numpy
import ctypes
import glfw

vssrc = '''
#version 330

layout ( location = 0 ) in vec3 aPos;
layout ( location = 1 ) in vec3 aNormal;

void main(void)
{
    gl_Position = vec4 ( aPos.x, aPos.y, aPos.z, 1.0 );
}
'''

# initialize fragment shader
fssrc = '''
#version 330

out vec4 FragColor;

void main() {
    FragColor = vec4 ( 0.0, 0.0, 1.0, 1.0 );
}
'''

glfw.init()

window=glfw.create_window(800,600,'test',None,None)
glfw.make_context_current(window)
glViewport ( 0, 0, 800, 600)

vao=glGenVertexArrays(1)
glBindVertexArray(vao)

vbo1=glGenBuffers(1)
vs=glCreateShader(GL_VERTEX_SHADER)
glShaderSource ( vs, vssrc )
glCompileShader(vs)

fs=glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource ( fs, fssrc )
glCompileShader(fs)

p1=glCreateProgram()
glAttachShader(p1, vs)
glAttachShader(p1, fs)
glLinkProgram(p1)
glUseProgram(0)

vbo2=glGenBuffers(1)

vs2=glCreateShader(GL_VERTEX_SHADER)
glShaderSource ( vs2, vssrc )
glCompileShader(vs2)

fs2=glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource ( fs2, fssrc )
glCompileShader(fs2)

p2=glCreateProgram()
glAttachShader(p2, vs2)
glAttachShader(p2, fs2)
glLinkProgram(p2)
glUseProgram(0)

glDeleteShader(vs)
glDeleteShader(fs)
glDeleteShader(vs2)
glDeleteShader(fs2)

#           vertices        normals
buffer1 = [-0.5, -0.5, 0,   0, 0, 1,
            0.5, -0.5, 0,   0, 0, 1,  
            0.5,  0.5, 0,   0, 0, 1]

#           vertices        normals
buffer2 = [ 0.5,  0.5, 0,   0, 0, 1,
           -0.5,  0.5, 0,   0, 0, 1, 
           -0.5, -0.5, 0,   0, 0, 1]

glBindBuffer(GL_ARRAY_BUFFER, vbo1)
glBufferData(GL_ARRAY_BUFFER, 72, numpy.array(buffer1, dtype=numpy.float32), GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(None))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 0)

glBindBuffer(GL_ARRAY_BUFFER, vbo2)
glBufferData(GL_ARRAY_BUFFER, 72, numpy.array(buffer2, dtype=numpy.float32), GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(None))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 0)

glBindVertexArray(0)

glClearColor(0.0, 0.0, 0.0, 1.0)
glEnable ( GL_DEPTH_TEST )

while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glBindVertexArray(vao)

    glUseProgram(p1)
    glBindBuffer(GL_ARRAY_BUFFER, vbo1)
    glDrawArrays(GL_TRIANGLES,0,3)
    glBindBuffer(GL_ARRAY_BUFFER, 0)

    glUseProgram(p2)
    glBindBuffer(GL_ARRAY_BUFFER, vbo2)
    glDrawArrays(GL_TRIANGLES,0,3)
    glBindBuffer(GL_ARRAY_BUFFER, 0)

    glUseProgram(0)

    glBindVertexArray(0)

    glfw.swap_buffers(window)
    glfw.poll_events()

glfw.terminate()`

在这个例子中,我为两个三角形创建了两组顶点数据(buffer1和buffer2),并将它们绑定到不同的顶点缓冲对象(VBOs)。我还为每个三角形使用了两个不同的着色器程序(p1和p2)来进行渲染。

尽管我为两个三角形都设置了数据和着色器,但屏幕上只有第二个三角形可见。我检查了顶点数据、着色器程序和缓冲区绑定,但就是找不到问题所在。

这可能是什么原因呢?

1 个回答

1

你需要创建两个 顶点数组对象(VAO)。更改 GL_ARRAY_BUFFER 的绑定不会影响绘制调用。这个缓冲区是和顶点数组属性连接在一起的,而这种连接信息会保存在 VAO 的状态向量中。当你调用 glVertexAttribPointer 时,就会建立这种连接,然后当前绑定到 GL_ARRAY_BUFFER 的缓冲区 ID 会和属性规格一起存储在 VAO 中。
所以,对于每个网格(mesh),你都要创建一个 VAO,并在想要绘制这个网格时绑定这个 VAO。

vao1 = glGenVertexArrays(1)
glBindVertexArray(vao1)
glBindBuffer(GL_ARRAY_BUFFER, vbo1)
glBufferData(GL_ARRAY_BUFFER, 72, numpy.array(buffer1, dtype=numpy.float32), GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(None))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)

vao2 = glGenVertexArrays(1)
glBindVertexArray(vao2)
glBindBuffer(GL_ARRAY_BUFFER, vbo2)
glBufferData(GL_ARRAY_BUFFER, 72, numpy.array(buffer2, dtype=numpy.float32), GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(None))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)

# [...]

while not glfw.window_should_close(window):
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

    glUseProgram(p1)
    glBindVertexArray(vao1)
    glDrawArrays(GL_TRIANGLES,0,3)

    glUseProgram(p2)
    glBindVertexArray(vao2)
    glDrawArrays(GL_TRIANGLES,0,3)

    glfw.swap_buffers(window)
    glfw.poll_events()

撰写回答