[CG从零开始] 4. pyopengl 绘制一个正方形( 二 )

3. 封装 VAO、VBO、EBOVBO 一般用来存储顶点数据之类的信息 , EBO 一般用来存储索引信息,VBO 和 EBO 都表现为 buffer,只不过类型不一样 。OpenGL 是个巨大的状态机,需要各种设置状态,每次渲染前都要正确的 bind VBO、EBO 等等,这个时候 可以用 VAO 可以用来管理 VBO 和 EBO 等的信息,在后续绘制中,只要 bind VAO 即可,不用再 bind VBO、EBO 等,比较方便 。关于 VAO、VBO、EBO 的详细说明,这里就不过多的解释了 , 网上有很多的资料,这里只是想展示它们的基本用法 。
基本的操作顺序:

  1. 创建 VAO,bind VAO;
  2. 创建 VBO,bind VBO,传送 VBO 数据,设置顶点属性,启用顶点属性;
  3. 创建 EBO,bind EBO , 传送 EBO 数据;
  4. unbind VAO、VBO、EBO
from OpenGL import GL as glimport logging, ctypeslog = logging.getLogger(__name__)# 用来管理 VAO、VBO、EBOclass RendererData:def __init__(self) -> None:self.vao: VAO = Noneself.vbo: VBO = Noneself.ebo: VBO = Nonedef use(self):self.vao.bind()def unuse(self):self.vao.unbind()def draw(self):self.use()gl.glDrawElements(gl.GL_TRIANGLES, len(self.ebo.indices), gl.GL_UNSIGNED_INT, None)self.unuse()def build_data(self, desp:list, vertices:list, indices:list):# create vertex array objectself.vao = VAO()self.vao.create_vertex_array_object()self.vao.bind()# create vertex buffer objectself.vbo = VBO()self.vbo.vertex_attrib_desps = despself.vbo.vertex_data = https://www.huyubaike.com/biancheng/verticesself.vbo.create_vertex_array_object()self.vbo.bind()self.vbo.gen_buffer_data()# create element buffer objectself.ebo = EBO()self.ebo.indices = indicesself.ebo.create_index_array_object()self.ebo.bind()self.ebo.gen_buffer_data()# unbind allself.vao.unbind()self.vbo.unbind()self.ebo.unbind()def clean(self):self.vao.clean()self.vbo.clean()self.ebo.clean()class VAO:def __init__(self) -> None:self.vao_id = -1def clean(self):log.debug('cleaning up vertex array')gl.glDeleteVertexArrays(1, [self.vao_id])def create_vertex_array_object(self):log.debug('creating and binding the vertex array (VAO)')self.vao_id = gl.glGenVertexArrays(1)def bind(self):gl.glBindVertexArray(self.vao_id)def unbind(self):gl.glBindVertexArray(0)# 描述顶点数据的布局信息class VertexAttribDesp:def __init__(self) -> None:self.attr_id = 0self.comp_count = 3self.comp_type = gl.GL_FLOATself.need_nor = Falseself.stride = 0self.offset = 0class EBO:def __init__(self) -> None:self.indices = []self.buffer_id = -1def create_index_array_object(self):self.buffer_id = gl.glGenBuffers(1)def bind(self):gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.buffer_id)def unbind(self):gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0)def gen_buffer_data(self):array_type = (gl.GLuint * len(self.indices))gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,len(self.indices) * ctypes.sizeof(ctypes.c_uint),array_type(*self.indices),gl.GL_STATIC_DRAW)def clean(self):log.debug('cleaning up buffer')gl.glDeleteBuffers(1, [self.buffer_id])class VBO:def __init__(self) -> None:self.vertex_data = https://www.huyubaike.com/biancheng/[]self.vertex_attrib_desps = []self.buffer_id = -1def clean(self):log.debug('cleaning up buffer')for desp in self.vertex_attrib_desps:gl.glDisableVertexAttribArray(desp.attr_id)gl.glDeleteBuffers(1, [self.buffer_id])def create_vertex_array_object(self):self.buffer_id = gl.glGenBuffers(1)def bind(self):gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffer_id)def unbind(self):gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)def gen_buffer_data(self):array_type = (gl.GLfloat * len(self.vertex_data))gl.glBufferData(gl.GL_ARRAY_BUFFER,len(self.vertex_data) * ctypes.sizeof(ctypes.c_float),array_type(*self.vertex_data),gl.GL_STATIC_DRAW)log.debug('setting the vertex attributes')for desp in self.vertex_attrib_desps:gl.glVertexAttribPointer(desp.attr_id,desp.comp_count,desp.comp_type,desp.need_nor,desp.stride,desp.offset)gl.glEnableVertexAttribArray(desp.attr_id)4. 完成主函数进行绘制from base import shader, window_helperfrom OpenGL import GL as glfrom base.gl_render_data import *import glfw# ----- 创建窗口window_config = window_helper.Window.Config(bgcolor = (0.5,0.5,0.5))window = window_helper.Window(window_config)# ----- # ----- 创建着色器,从文件中读取# base.vert"""#version 330 corelayout(location = 0) in vec3 aPos;void main(){gl_Position.xyz = aPos;gl_Position.w = 1.0;}"""# base.frag"""#version 330 coreout vec3 color;void main(){color = vec3(1,0,0);}"""mshader = shader.Shader()mshader.load_shader_source_from_path(shader.ShaderType.VERTEX, "shader/base.vert")mshader.load_shader_source_from_path(shader.ShaderType.FRAGMENT, "shader/base.frag")mshader.create_program()mshader.use_program()# -----# ---- 创建 VAO、VBO、EBO , 设置顶点属性data = https://www.huyubaike.com/biancheng/RendererData()desp = VertexAttribDesp()desp.attr_id = 0desp.comp_count = 3desp.stride = 3 * 4desp.offset = Nonedesp.need_nor = Falsedesp.comp_type = gl.GL_FLOATvert = [-0.5, 0.5, 0,0.5, 0.5, 0,0.5, -0.5, 0,-0.5, -0.5 ,0 ]inde = [3,1,0,3,2,1]data.build_data([desp],vert,inde)data.use()# ---------# ----- 渲染循环while (glfw.get_key(window.native_window, glfw.KEY_ESCAPE) != glfw.PRESS andnot glfw.window_should_close(window.native_window)):gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)data.draw()glfw.swap_buffers(window.native_window)glfw.poll_events()# -----

推荐阅读