I'm currently working on a simple OpenGL program using Python with the glfw and OpenGL.GL libraries. I have two triangles that I'm trying to render, but for some reason, only the second triangle is being rendered, and the first triangle is not visible.
I've narrowed down the issue to this minimal example:
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()`
In this example, I'm creating two sets of vertex data (buffer1 and buffer2) for the two triangles and binding them to separate Vertex Buffer Objects (VBOs). I'm also using two separate shader programs (p1 and p2) for rendering each triangle.
Despite setting up the data and shaders for both triangles, only the second triangle is visible on the screen. I've checked the vertex data, shader programs, and buffer bindings, but I can't seem to find the issue.
What might be causing this issue?
You must create 2 Vertex Array Objects. Changing the GL_ARRAY_BUFFER
binding has no effect on the draw call. The buffer is connected with the vertex array attribute and this connection is stored in the state vector of the VAO. The connection is created when glVertexAttribPointer
is called, then the ID of the buffer currently bound to the target GL_ARRAY_BUFFER
is stored in the VAO together with the attribute specification.
Therefore, create a VAO for each mesh and bind the VAO if you want to draw the mesh.
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()