826 字
4 分钟
Advanced Data

三种缓冲数据导入方式#

一次性整体导入:glBufferData#

直接将完整数据一次性写入显存缓冲,同时完成内存分配 + 数据填充,是最常用的基础数据加载方式。适用于数据固定、一次性初始化的场景。

局部区域填充:glBufferSubData#

用于向缓冲的指定偏移区域填充数据,支持局部更新缓冲内容。 前置要求:必须提前调用 glBufferData 为缓冲分配足够的显存内存,否则无法使用局部填充。 核心优势:无需覆盖全部缓冲数据,可精准更新局部数据,适合动态局部修改场景。

指针映射拷贝:glMapBuffer + memcpy#

通过内存映射方式操作缓冲数据,流程如下:

  1. 调用 glMapBuffer 获取显存缓冲的内存指针;
  2. 通过 memcpy 直接将内存数据拷贝至显存缓冲;
  3. 数据拷贝完成后,调用 glUnmapBuffer 释放映射指针。 适合大批量、高频动态更新数据的场景,内存读写效率更高。

顶点属性分批存储#

存储方式区别#

  • 传统交错存储:单个顶点的所有属性交叉连续存放,顺序为:顶点1位置、法线、纹理坐标 → 顶点2位置、法线、纹理坐标 ……
  • 分批存储(非交错存储):将所有顶点的同类属性集中存放,拆分独立数组,顺序为:所有顶点位置数组、所有顶点法线数组、所有顶点纹理坐标数组。

数据加载方式#

分批存储的顶点属性,需配合 glBufferSubData 按偏移量分批次写入同一 VBO 缓冲的不同区域。

步长计算规则#

分批存储模式下,stride 为相邻两个顶点同一属性的间隔字节数。 以顶点位置属性为例:所有顶点位置数据连续排布,相邻两个顶点的位置数据间隔为 3 * sizeof(float),因此 stride 取值为该数值。

顶点存储方式优劣#

优先使用交错存储,不推荐分批非交错存储。 核心原因:交错存储将同一个顶点的所有属性连续存放。GPU 绘制单个顶点时,只需一次性读取连续内存,缓存命中率高、内存读取开销小、渲染效率更高。 分批存储属性分散,GPU 需要多次跳转读取内存,效率更低,仅适用于特殊局部数据更新场景。

缓冲数据复制操作#

核心函数#

glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size) 功能:实现显存缓冲之间的数据直接拷贝,无需经过 CPU 内存中转,效率极高。 参数说明:

  • readTarget:源缓冲绑定目标类型
  • writeTarget:目标缓冲绑定目标类型
  • readOffset:源缓冲读取起始偏移量
  • writeOffset:目标缓冲写入起始偏移量
  • size:拷贝数据字节大小

同缓冲拷贝专用目标类型#

当源缓冲与目标缓冲为同一个缓冲(readTarget = writeTarget)时,需使用专属目标类型区分读写身份,避免冲突:

  • GL_COPY_READ_BUFFER:只读源缓冲类型,用于绑定待拷贝的源缓冲
  • GL_COPY_WRITE_BUFFER:只写目标缓冲类型,用于绑定数据写入的目标缓冲
Advanced Data
https://fuwari.vercel.app/posts/notes/opengl/advanceddata/
作者
Ruby
发布于
2026-06-27
许可协议
CC BY-NC-SA 4.0