我目前正在使用 Python 以及 glfw 和 OpenGL.GL 库开发一个简单的 OpenGL 程序。我有两个三角形正在尝试渲染,但由于某种原因,仅渲染第二个三角形,而第一个三角形不可见。
我已将问题范围缩小到这个最小的示例:
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),并将它们绑定到单独的顶点缓冲区对象 (VBO)。我还使用两个单独的着色器程序(p1 和 p2)来渲染每个三角形。
尽管为两个三角形设置了数据和着色器,但屏幕上只有第二个三角形可见。我检查了顶点数据、着色器程序和缓冲区绑定,但我似乎找不到问题。
什么可能导致此问题?
您必须创建 2 个顶点数组对象。更改
GL_ARRAY_BUFFER
绑定对绘制调用没有影响。缓冲区与顶点数组属性连接,该连接存储在 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()