Opengl常用缓冲对象功能介绍及使用示例(C++实现)

发布于:2025-02-23 ⋅ 阅读:(22) ⋅ 点赞:(0)

本文整理了常用的opengl缓冲区对象并安排了使用示例

名称 英文全称 作用简述
顶点数组对象 Vertex Array Object (VAO) 管理 VBO 和 EBO 的配置,存储顶点属性设置,简化渲染流程,避免重复设置状态
顶点缓冲区对象 Vertex Buffer Object (VBO) 存储顶点属性数据,提升渲染性能
索引缓冲区对象 Element/Index Buffer Object (EBO/IBO) 存储顶点索引,减少数据冗余
统一缓冲区对象 Uniform Buffer Object (UBO) 存储着色器统一变量,方便多着色器共享
着色器存储缓冲区对象 Shader Storage Buffer Object (SSBO) 供着色器直接读写复杂数据
像素缓冲区对象 Pixel Buffer Object (PBO) 加速像素数据在 CPU 和 GPU 间传输
变换反馈缓冲区对象 Transform Feedback Buffer Object (TFBO) 存储处理后的顶点数据用于后续渲染
原子计数器缓冲区对象 Atomic Counter Buffer Object (ACBO) 存储可并发修改的计数器
纹理缓冲区对象 Texture Buffer Object (TBO) 将缓冲区数据作为一维纹理采样
查询对象 Query Object 查询 OpenGL 操作状态和结果用于调试
帧缓冲区对象 Framebuffer Object (FBO) 自定义渲染目标实现离屏渲染
渲染缓冲区对象 Renderbuffer Object (RBO) 与 FBO 配合存储单一图像数据
命令缓冲区 Command Buffer 提前记录命令,减少 CPU - GPU 同步开销
稀疏纹理 Sparse Texture 仅为纹理实际部分分配内存,节省空间
采样器缓冲区对象 Sampler Buffer Object 结合缓冲区与采样器功能访问数据
多视图帧缓冲区对象 Multiview Framebuffer Object 支持同时渲染到多个视图用于特殊渲染

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

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(800, 600, "VAO 示例", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 创建 VAO
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    // 绑定 VAO
    glBindVertexArray(VAO);

    // 这里可以进行 VBO 和 EBO 的绑定与设置

    // 解绑 VAO
    glBindVertexArray(0);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        // 处理事件
        glfwPollEvents();

        // 绑定 VAO
        glBindVertexArray(VAO);
        // 绘制操作
        // glDrawArrays(GL_TRIANGLES, 0, 3);
        // 解绑 VAO
        glBindVertexArray(0);

        // 交换缓冲区
        glfwSwapBuffers(window);
    }

    // 清理 VAO
    glDeleteVertexArrays(1, &VAO);

    // 终止 GLFW
    glfwTerminate();
    return 0;
}

2. 顶点缓冲区对象(Vertex Buffer Object, VBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "VBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };

    // 创建 VBO
    GLuint VBO;
    glGenBuffers(1, &VBO);
    // 绑定 VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 填充数据
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 解绑 VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glfwTerminate();
    // 清理 VBO
    glDeleteBuffers(1, &VBO);
    return 0;
}

3. 索引缓冲区对象(Element Buffer Object, EBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "EBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 顶点数据
    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };
    // 索引数据
    unsigned int indices[] = {
        0, 1, 2
    };

    // 创建 EBO
    GLuint EBO;
    glGenBuffers(1, &EBO);
    // 绑定 EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    // 填充数据
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 解绑 EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glfwTerminate();
    // 清理 EBO
    glDeleteBuffers(1, &EBO);
    return 0;
}

4. 统一缓冲区对象(Uniform Buffer Object, UBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const GLuint UBO_BINDING_POINT = 0;

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "UBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 UBO
    GLuint UBO;
    glGenBuffers(1, &UBO);
    // 绑定 UBO
    glBindBuffer(GL_UNIFORM_BUFFER, UBO);
    // 分配内存
    glBufferData(GL_UNIFORM_BUFFER, 16 * sizeof(float), nullptr, GL_STATIC_DRAW);
    // 绑定到指定绑定点
    glBindBufferBase(GL_UNIFORM_BUFFER, UBO_BINDING_POINT, UBO);

    // 解绑 UBO
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glfwTerminate();
    // 清理 UBO
    glDeleteBuffers(1, &UBO);
    return 0;
}

5. 着色器存储缓冲区对象(Shader Storage Buffer Object, SSBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "SSBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 数据
    float data[] = {1.0f, 2.0f, 3.0f, 4.0f};

    // 创建 SSBO
    GLuint SSBO;
    glGenBuffers(1, &SSBO);
    // 绑定 SSBO
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);
    // 填充数据
    glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
    // 绑定到指定绑定点
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, SSBO);

    // 解绑 SSBO
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

    glfwTerminate();
    // 清理 SSBO
    glDeleteBuffers(1, &SSBO);
    return 0;
}

6. 像素缓冲区对象(Pixel Buffer Object, PBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "PBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 PBO
    GLuint PBO;
    glGenBuffers(1, &PBO);
    // 绑定 PBO
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO);
    // 分配内存
    glBufferData(GL_PIXEL_UNPACK_BUFFER, 800 * 600 * 4, nullptr, GL_STREAM_DRAW);

    // 解绑 PBO
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

    glfwTerminate();
    // 清理 PBO
    glDeleteBuffers(1, &PBO);
    return 0;
}

7. 变换反馈缓冲区对象(Transform Feedback Buffer Object, TFBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "TFBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 TFBO
    GLuint TFBO;
    glGenBuffers(1, &TFBO);
    // 绑定 TFBO
    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, TFBO);
    // 分配内存
    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
    // 绑定到变换反馈绑定点
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TFBO);

    // 解绑 TFBO
    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

    glfwTerminate();
    // 清理 TFBO
    glDeleteBuffers(1, &TFBO);
    return 0;
}

8. 原子计数器缓冲区对象(Atomic Counter Buffer Object, ACBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "ACBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 ACBO
    GLuint ACBO;
    glGenBuffers(1, &ACBO);
    // 绑定 ACBO
    glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, ACBO);
    // 分配内存
    glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), nullptr, GL_DYNAMIC_DRAW);
    // 绑定到指定绑定点
    glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, ACBO);

    // 解绑 ACBO
    glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

    glfwTerminate();
    // 清理 ACBO
    glDeleteBuffers(1, &ACBO);
    return 0;
}

9. 纹理缓冲区对象(Texture Buffer Object, TBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "TBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 数据
    float data[] = {1.0f, 2.0f, 3.0f, 4.0f};

    // 创建 TBO
    GLuint TBO;
    glGenBuffers(1, &TBO);
    // 绑定 TBO
    glBindBuffer(GL_TEXTURE_BUFFER, TBO);
    // 填充数据
    glBufferData(GL_TEXTURE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

    // 创建纹理
    GLuint texture;
    glGenTextures(1, &texture);
    // 绑定纹理
    glBindTexture(GL_TEXTURE_BUFFER, texture);
    // 将 TBO 关联到纹理
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, TBO);

    // 解绑 TBO 和纹理
    glBindBuffer(GL_TEXTURE_BUFFER, 0);
    glBindTexture(GL_TEXTURE_BUFFER, 0);

    glfwTerminate();
    // 清理 TBO 和纹理
    glDeleteBuffers(1, &TBO);
    glDeleteTextures(1, &texture);
    return 0;
}

10. 查询对象(Query Object)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "查询对象示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建查询对象
    GLuint query;
    glGenQueries(1, &query);

    // 开始查询
    glBeginQuery(GL_SAMPLES_PASSED, query);

    // 这里进行绘制操作
    // glDrawArrays(GL_TRIANGLES, 0, 3);

    // 结束查询
    glEndQuery(GL_SAMPLES_PASSED);

    // 获取查询结果
    GLuint result;
    glGetQueryObjectuiv(query, GL_QUERY_RESULT, &result);
    std::cout << "采样通过数量: " << result << std::endl;

    // 清理查询对象
    glDeleteQueries(1, &query);

    glfwTerminate();
    return 0;
}

11. 帧缓冲区对象(Framebuffer Object, FBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "FBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 FBO
    GLuint FBO;
    glGenFramebuffers(1, &FBO);
    // 绑定 FBO
    glBindFramebuffer(GL_FRAMEBUFFER, FBO);

    // 这里可以创建并附加纹理或渲染缓冲区

    // 检查 FBO 是否完整
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        std::cerr << "FBO 不完整" << std::endl;

    // 解绑 FBO
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glfwTerminate();
    // 清理 FBO
    glDeleteFramebuffers(1, &FBO);
    return 0;
}

12. 渲染缓冲区对象(Renderbuffer Object, RBO)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "RBO 示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    // 创建 RBO
    GLuint RBO;
    glGenRenderbuffers(1, &RBO);
    // 绑定 RBO
    glBindRenderbuffer(GL_RENDERBUFFER, RBO);
    // 分配内存
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);

    // 解绑 RBO
    glBindRenderbuffer(GL_RENDERBUFFER, 0);

    glfwTerminate();
    // 清理 RBO
    glDeleteRenderbuffers(1, &RBO);
    return 0;
}

13. 命令缓冲区(Command Buffer)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>

// 模拟命令结构体
struct Command {
    enum Type { DRAW_ARRAYS } type;
    GLenum mode;
    GLint first;
    GLsizei count;
};

int main() {
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "命令缓冲区示例", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewInit();

    std::vector<Command> commandBuffer;

    // 添加命令到缓冲区
    Command cmd;
    cmd.type = Command::DRAW_ARRAYS;
    cmd.mode = GL_TRIANGLES;
    cmd.first = 0;
    cmd.count = 3;
    commandBuffer.push_back(cmd);

    // 执行命令缓冲区中的命令
    for (const auto& cmd : commandBuffer) {
        if (cmd.type == Command::DRAW_ARRAYS) {
            glDrawArrays(cmd.mode, cmd.first, cmd.count);
        }
    }

    glfwTerminate();
    return 0;
}

稀疏纹理(Sparse Texture)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const int WIDTH = 800;
const int HEIGHT = 600;

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Sparse Texture Example", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 检查是否支持稀疏纹理扩展
    if (!GLEW_ARB_sparse_texture) {
        std::cerr << "不支持 ARB_sparse_texture 扩展" << std::endl;
        glfwTerminate();
        return -1;
    }

    // 创建纹理对象
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // 分配稀疏纹理存储
    GLint alignment;
    glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_SPARSE_ARB, 1, &alignment);
    glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, WIDTH, HEIGHT, GL_TRUE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SPARSE_ARB, GL_TRUE);

    // 定义一个稀疏纹理的子区域
    GLint x = 0, y = 0, z = 0;
    GLint width = WIDTH / 2, height = HEIGHT / 2, depth = 1;
    GLint level = 0;
    glTexPageCommitmentARB(GL_TEXTURE_2D, level, x, y, z, width, height, depth, GL_TRUE);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // 清屏
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 这里可以进行纹理绘制操作

        glfwSwapBuffers(window);
    }

    // 清理资源
    glDeleteTextures(1, &texture);
    glfwTerminate();
    return 0;
}

采样器缓冲区对象(Sampler Buffer Object)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const int WIDTH = 800;
const int HEIGHT = 600;

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Sampler Buffer Object Example", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 创建缓冲区对象
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_TEXTURE_BUFFER, buffer);

    // 分配缓冲区数据
    const int bufferSize = 1024;
    float* data = new float[bufferSize];
    for (int i = 0; i < bufferSize; ++i) {
        data[i] = static_cast<float>(i);
    }
    glBufferData(GL_TEXTURE_BUFFER, bufferSize * sizeof(float), data, GL_STATIC_DRAW);
    delete[] data;

    // 创建纹理对象并绑定到缓冲区
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_BUFFER, texture);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // 清屏
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 这里可以在着色器中使用采样器缓冲区对象进行采样操作

        glfwSwapBuffers(window);
    }

    // 清理资源
    glDeleteTextures(1, &texture);
    glDeleteBuffers(1, &buffer);
    glfwTerminate();
    return 0;
}

多视图帧缓冲区对象(Multiview Framebuffer Object)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>

const int WIDTH = 800;
const int HEIGHT = 600;

int main() {
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "GLFW 初始化失败" << std::endl;
        return -1;
    }

    // 创建窗口
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Multiview Framebuffer Object Example", nullptr, nullptr);
    if (!window) {
        glfwTerminate();
        std::cerr << "窗口创建失败" << std::endl;
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLEW
    if (glewInit() != GLEW_OK) {
        glfwTerminate();
        std::cerr << "GLEW 初始化失败" << std::endl;
        return -1;
    }

    // 检查是否支持多视图扩展
    if (!GLEW_NV_multiview) {
        std::cerr << "不支持 NV_multiview 扩展" << std::endl;
        glfwTerminate();
        return -1;
    }

    // 创建帧缓冲区对象
    GLuint fbo;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    // 创建纹理附件
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, WIDTH, HEIGHT, 2); // 2 个视图

    // 将纹理附件附加到帧缓冲区
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);

    // 设置多视图
    GLuint views[] = {0, 1};
    glNamedFramebufferMultiviewOVR(fbo, GL_COLOR_ATTACHMENT0, texture, 0, 0, 2, 2, views);

    // 主循环
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // 清屏
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // 这里可以进行多视图渲染操作

        glfwSwapBuffers(window);
    }

    // 清理资源
    glDeleteTextures(1, &texture);
    glDeleteFramebuffers(1, &fbo);
    glfwTerminate();
    return 0;
}