PyOpenGL,无法使用两个不同的 VBO 进行绘制

PyOpenGL, can not draw using two different VBO

我在尝试使用两个不同的 VBO 并使用 glDrawArrays() 时遇到了一个奇怪的问题。然而,两个 glDrawArrays() 绘制完全相同的图形,即使 VBO 数据不同

import ctypes
import numpy as np
import pygame as pg
from pygame.locals import *
from array import array
SCREEN_SIZE = (800, 600)


from OpenGL.GL import *
from OpenGL.GLU import *

def resize(width, height):

    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(60.0, float(width)/height, .1, 1000.)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()




def create_shader(shader_type,source):
    shader = glCreateShader(shader_type)
    glShaderSource(shader,source)
    glCompileShader(shader)
    print(glGetShaderiv(shader, GL_COMPILE_STATUS, None))
    return shader

pg.init()
screen = pg.display.set_mode(SCREEN_SIZE, HWSURFACE|OPENGL|DOUBLEBUF)

resize(*SCREEN_SIZE)

#creating and compiling fragment shader
fragment = create_shader(GL_FRAGMENT_SHADER,"""

#version 130

out vec4 finalColor; 

void main()
{
    finalColor = vec4(.0,0.0,1.0,1.0);
}
""")

#creating and compiling vertex shader
vertex = create_shader(GL_VERTEX_SHADER,"""

#version 130


in vec3 pos;

void main()
{   

    gl_Position=gl_ProjectionMatrix*gl_ModelViewMatrix *vec4(pos,1.0);



}
""")

#create and link program
program = glCreateProgram()
glAttachShader(program, fragment)
glAttachShader(program, vertex)
glLinkProgram(program)
#get location of the position variable in vertex shader
posAttrib = glGetAttribLocation(program, "pos")


vbo=glGenBuffers(1)

vbo2=glGenBuffers(1)

#vao=glGenVertexArrays(1)

#glBindVertexArray(vao)

glBindBuffer(GL_ARRAY_BUFFER, vbo)
vertices=[1.5, -0.5, -4.0, 0.5, -0.5, -4.0, 0.5, 0.5, -4.0]

nparray = np.array(vertices,dtype=np.dtype('<f4'))
glBufferData(GL_ARRAY_BUFFER, nparray, GL_STATIC_DRAW)

vertices=[2., -0.5, -4.0, -0.5, -0.5, -2.0, 0.5, 0.5, -1.0]
#vertices=[1.5, -0.5, -4.0, 0.5, -0.5, -4.0, 0.5, 0.5, -4.0]
nparray = np.array(vertices,dtype=np.dtype('<f4'))
glBindBuffer(GL_ARRAY_BUFFER, vbo2)
glBufferData(GL_ARRAY_BUFFER, nparray, GL_STATIC_DRAW)

#specify how the variable pos gets data from the buffer data
glEnableVertexAttribArray(posAttrib)
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 3*4,ctypes.cast(0, ctypes.c_void_p))

while 1:

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(1.0, 1.0, 1.0, 0.0)


    glUseProgram(program)
    glBindBuffer(GL_ARRAY_BUFFER, vbo)
    print('vbo 1:',glGetInteger(GL_ARRAY_BUFFER_BINDING))
    print('vbo data 1:',glGetBufferSubData(GL_ARRAY_BUFFER,0,3*3*4,None))


#    glDrawArrays(GL_TRIANGLES, 0, 3)

    glBindBuffer(GL_ARRAY_BUFFER, vbo2)
    print('vbo 2:',glGetInteger(GL_ARRAY_BUFFER_BINDING))
    print('vbo data 2:',glGetBufferSubData(GL_ARRAY_BUFFER,0,3*3*4,None))

    glDrawArrays(GL_TRIANGLES, 0, 3)


    pg.display.flip()
    pg.time.delay(100)

代码的重要部分是我使用 glBufferData 和绘制命令 glDrawArrays 上传数据的地方。如果您尝试注释掉一个或另一个 glDrawArrays(),您将看到代码实际上绘制了完全相同的图形。但是,我向两个 VBO 上传了不同的数据(打印使用 glGetBufferSubData 获得的数据可以看出)。这很奇怪。当 VBO 数据明显不同时,为什么两个 glDrawArrays 产生相同的结果?这是 PyOpenGL 中的错误还是我在这里遗漏了一些基本的东西?

定义通用顶点属性数据数组的不是绑定顶点缓冲区对象,而是存储在默认顶点数组对象中的状态。

当您调用 glVertexAttribPointer 时,定义了通用顶点属性数据数组。如果此时绑定了一个数组buffer,那么数组定义就是引用buffer对象。

这意味着您必须在绘制对象之前切换数组定义:

# define an array of generic vertex attribute data which refers to "vbo" 
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 0,ctypes.cast(0, ctypes.c_void_p))
glEnableVertexAttribArray(posAttrib)
glDrawArrays(GL_TRIANGLES, 0, 3)

# define an array of generic vertex attribute data which refers to "vbo2" 
glBindBuffer(GL_ARRAY_BUFFER, vbo2)
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 0,ctypes.cast(0, ctypes.c_void_p))
glEnableVertexAttribArray(posAttrib)
glDrawArrays(GL_TRIANGLES, 0, 3)


作为替代方案,您可以使用 2 Vertex Array Objects:

# vertex data 1
vertices=[1.5, -0.5, -4.0, 0.5, -0.5, -4.0, 0.5, 0.5, -4.0]
nparray = np.array(vertices,dtype=np.dtype('<f4'))
vbo=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, nparray, GL_STATIC_DRAW)

# vertex data 2
vertices=[2., -0.5, -4.0, -0.5, -0.5, -2.0, 0.5, 0.5, -1.0]
nparray = np.array(vertices,dtype=np.dtype('<f4'))
vbo2=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo2)
glBufferData(GL_ARRAY_BUFFER, nparray, GL_STATIC_DRAW)

# vertex array object 1
vao=glGenVertexArrays(1)
glBindVertexArray(vao)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glEnableVertexAttribArray(posAttrib)
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 3*4,ctypes.cast(0, ctypes.c_void_p))

# vertex array object 2
vao2=glGenVertexArrays(1)
glBindVertexArray(vao2)
glBindBuffer(GL_ARRAY_BUFFER, vbo2)
glEnableVertexAttribArray(posAttrib)
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, False, 3*4,ctypes.cast(0, ctypes.c_void_p))

glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)

# draw vertex array 1
glBindVertexArray(vao)
glDrawArrays(GL_TRIANGLES, 0, 3)

# draw vertex array 2
glBindVertexArray(vao2)
glDrawArrays(GL_TRIANGLES, 0, 3)