在执行渲染之前,需要将各种顶点相关的数据传递到顶点着色器中,如位置、法线、UV等

顶点数据传递流程

  flowchart TB
    subgraph EBO["EBO"]
        e1["glGenBuffers"] --> e2["glBindBuffer"] --> e3["glBufferData"] --> e4["glBindBuffer(TARGET, 0)"]
    end
    subgraph VBO["VBO"]
        b1["glGenBuffers"] --> b2["glBindBuffer"] --> b3["glBufferData"]
        b4["glBindBuffer(TARGET, 0)"]
    end
    subgraph VAO["VAO"]
        a1["glGenVertexArrays"] --> a2["glBindVertexArray"] --> a3["glVertexAttribPointer"] --- a4["glEnableVertexAttribArray"] --> a5["glBindVertexArray(0)"]
    end
    subgraph delete["Delete"]
        d1["glDeleteVertexArrays"]
        d2["glDeleteBuffers"]
    end
    b3 --> a3
    a5 --> b4 --> d2
    e4 --> d2
    a5 --> d1

    style a5 stroke-width:2px,stroke-dasharray: 2
    style b4 stroke-width:2px,stroke-dasharray: 2
    style e4 stroke-width:2px,stroke-dasharray: 2

完整示例

CPP
unsigned int VAO, VBO, EBO;

struct VertexInfo {
    glm::vec3 Position; // 顶点位置
    glm::vec3 Normal; // 法线
    glm::vec2 TexCoord; // 纹理坐标
}

// @param vbi 顶点信息数据
// @param ebi 索引数据
Mesh(const std::vector<VertexInfo> &vbi, const std::vector<unsigned int> &ebi) {
    // 计算顶点信息数据大小
    const auto vbi_size = vbi.size() * sizeof(VertexInfo);
    // 计算索引数据大小
    const auto indices_size = ebi.size() * sizeof(unsigned int);
    
    /// 生成VAO
    glGenVertexArrays(1, &VAO);
    // 绑定VAO
    glBindVertexArray(VAO);
    
    // 处理顶点信息数据
    /// 生成VBO
    glGenBuffers(1, &VBO);
    // 绑定VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    /// 传入VBO数据
    glBufferData(GL_ARRAY_BUFFER, vbi_size, vbi.data(), GL_STATIC_DRAW);
    /// 设置锚定点
    //// 位置 Position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexInfo), reinterpret_cast<void *>(offsetof(VertexInfo, Position)));
    glEnableVertexAttribArray(0);
    //// 法线 Normal
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexInfo), reinterpret_cast<void *>(offsetof(VertexInfo, Normal)));
    glEnableVertexAttribArray(1);
    //// 纹理坐标 TexCoord
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexInfo), reinterpret_cast<void *>(offsetof(VertexInfo, TexCoord)));
    glEnableVertexAttribArray(2);
    // 处理顶点信息数据结束
    
    // 处理索引数据
    /// 生成EBO
    glGenBuffers(1, &EBO);
    // 绑定EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    /// 传入EBO数据
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_size * sizeof(unsigned int), ebi.data(), GL_STATIC_DRAW);
    
    // 解绑VAO
    glBindVertexArray(0);
}

~Mesh() override {
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
}
点击展开查看更多

缓冲区对象 (Buffer Object)

我们可以通过缓冲区对象将一大批数据一次性地发送到GPU上,从CPU把数据发送到GPU相对较,所以只要可能,我们都要尝试尽量一次性发送尽可能多的数据。

glGenBuffers

用于生成指定数量的缓冲区对象

C
void glGenBuffers(GLsizei n, GLuint *buffers)
点击展开查看更多

glBindBuffer

将指定的缓冲区对象绑定到当前上下文中的某个目标(Target)

C
void glBindBuffer(GLenum target, GLuint buffer)
点击展开查看更多

glBufferData / glNamedBufferData

为缓冲区对象创建一个新的数据存储,原有的数据存储会被删除

C
void glBufferData(
	GLenum target,
	GLsizeiptr size,
	const void *data,
	GLenum usage,
)
void glNamedBufferData(
	GLuint buffer,
	GLsizeiptr size,
	const void *data,
	GLenum usage,
)
点击展开查看更多

glDeleteBuffers

用于删除缓冲区对象,并释放资源注意:如果当前绑定的缓冲区对象被删除,则对应目标会自动解绑,绑定状态恢复为0

C
void glDeleteBuffers(GLsizei n, const GLuint * buffers)
点击展开查看更多

参数参考glGenBuffers


顶点数组对象 VAO(Vertex Array Object)

VAO是一个用于管理顶点属性配置的对象,它并不直接存储顶点数据(如坐标、颜色、纹理等),而是存储如何从缓冲对象中解析顶点数据的配置

glGenVertexArrays

用于生成指定数量的VAO

C
void glGenVertexArrays(GLsizei n, GLuint *arrays)
点击展开查看更多

glBindVertexArray

用于绑定并使用VAO

C
void glBindVertexArray(GLuint array);
点击展开查看更多

glVertexAttribPointer

定义一个顶点属性点(锚定点)

C
void glVertexAttribPointer(
	GLuint index,
 	GLint size,
 	GLenum type,
 	GLboolean normalized,
 	GLsizei stride,
 	const void * pointer,
);
点击展开查看更多

glEnableVertexAttribArray / glDisableVertexAttribArray

启用/禁用顶点属性所有顶点属性默认禁用;当不再需要某个顶点属性时,最好禁用以优化性能

C
void glEnableVertexArrayAttrib([GLuint vaobj], GLuint index);
void glDisableVertexArrayAttrib([GLuint vaobj], GLuint index);
点击展开查看更多

glDeleteVertexArrays

用于删除VAO,并释放资源注意:如果当前绑定的VAO被删除,则会自动解绑,绑定状态恢复为0

C
void glDeleteVertexArrays(GLsizei n, const GLuint *arrays);
点击展开查看更多

参数参考glGenVertexArrays

版权声明

作者: Chaim

链接: https://chaim.eu.org/posts/%E9%A1%B6%E7%82%B9%E6%95%B0%E6%8D%AE%E4%BC%A0%E9%80%92/

许可证: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键