OpenGL 缓存对象(Buffer Object) 解析

缓存对象(Buffer Object)简介

OpenGL Buffer Object(缓存对象,简写BO),是OpenGL管理的一段内存,为了与我们CPU的内存区分开,一般叫OpenGL管理的内存,叫显存。

为了区分内存与显存,我这里从京东上搜索了内存条与显卡,如下图,这是一张显卡的截图,显卡使用的DDR为GDDR5,就是我们的显存,这个2G就表示这个显存的大小为2G。
显存-使用的DDR叫GDDR
再看内存,内存条,下面的内存条,使用的是DDR4,这里有2根,容量大小为8GB。

在这里插入图片描述
内存,是通过PCIE插槽,插在主板上的,也就是位于主板上的DDR。CPU访问内存比较快。

显存,其实就是位于显卡内部的DDR。显卡访问显存比较快。而Buffer Object,就是由OpenGL维护的一块显存区域。比如说上面的显卡显存为2G, 我从这个2G里面,分配 32K的大小给我用,这个32K大小的区域,就叫一个Buffer Object。

那为什么需要Buffer Object呢?这个,主要就是我们的显卡,访问显存,比访问内存要快很多。正如你到隔壁邻居家,比到你远方亲戚家,要近很多,这个叫远亲不如近邻,对吧。而且显卡做运算,一般都是访问显存的数据,然后运算的结果,也都保存在显存中。所以一般,我们需要先把数据,从内存传输到显存中去。

缓存对象操作函数

  1. 分配缓存对象名字, glGenBuffers
  2. 绑定缓存对象到OpenGL的目标上, glBindBuffer
  3. 给缓存对象,分配显存,并将内存数据,传输到显存,glBufferData
  4. 删除缓冲区对象, glDeleteBuffers
  5. 缓冲区对象,映射到内存上,glMapBuffer,解除映射glUnmapBuffer
    这几个函数的具体解释,书上都有。这里就不解释了。
    但是我想说一下, glBindBuffer的目标点target。

假如target为GL_ARRAY_BUFFER,说明这个Buffer Object是用来存储顶点数据的,那么就说这个Buffer Object为 Vertex Buffer Object,也就是我们的VBO。

假如target为GL_PIXEL_PACK_BUFFER和GL_PIXEL_UNPACK_BUFFER,那么这个Buffer Object为Pixel Buffer Object,也就是我们的PBO。

所以, 这个Buffer Object,就是一块显存区域。这个显存区域,存放顶点数据,就叫VBO,存放图像数据,就叫PBO,根据它glBindBuffer的 target不同,就有不同的叫法。这样就很好理解这个BO,那个BO了。

缓存对象操作实例

下面的代码,展示了数据在内存和显存之间传输,说明了如何使用Buffer Object。

  1. 开辟了一个内存,mem,mem的大小为64,里面数据,填了64个0x18
  2. 创建了一个Buffer Object,并使用mem的内容,初始化Buffer Object
  3. 将Buffer Object的内容,映射出来,然后与我们mem的内容进行比较
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

#include <GL3/gl3w.h>
#include <GLFW/glfw3.h>


void testbo()
{
    char* mem = (char*)malloc(64);
    memset(mem, 0x18, 64);

    /*创建Buffer Object,并将内存mem里面的数据,传输到显存里面去*/
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_COPY_WRITE_BUFFER, buffer);
    glBufferData(GL_COPY_WRITE_BUFFER, 64, mem, GL_STATIC_DRAW);

    /*将显存数据,映射出来,然后跟内存数据进行比较,两者应该一致*/
    void* data = glMapBuffer(GL_COPY_WRITE_BUFFER, GL_READ_WRITE);
    printf("data = %p, mem = %p\n", data, mem);
    printf("0x%x \n", *((unsigned int*)(data)));
    int ret = memcmp(data, mem, 64);
    assert(ret == 0);
    glUnmapBuffer(GL_COPY_WRITE_BUFFER);

    free(mem);
    glDeleteBuffers(1, &buffer);

    printf("test bo succeed \n");
}

int main(int argc, char** argv)
{
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800, 600, "Triangles", NULL, NULL);
    glfwMakeContextCurrent(window);

    gl3wInit();

    testbo();

    glfwTerminate();
    return 0;
}

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值