OpenGL只渲染第二个三角形,第一个三角形不可见
我现在正在用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()