826 字
4 分钟
Advanced Data
三种缓冲数据导入方式
一次性整体导入:glBufferData
直接将完整数据一次性写入显存缓冲,同时完成内存分配 + 数据填充,是最常用的基础数据加载方式。适用于数据固定、一次性初始化的场景。
局部区域填充:glBufferSubData
用于向缓冲的指定偏移区域填充数据,支持局部更新缓冲内容。
前置要求:必须提前调用 glBufferData 为缓冲分配足够的显存内存,否则无法使用局部填充。
核心优势:无需覆盖全部缓冲数据,可精准更新局部数据,适合动态局部修改场景。
指针映射拷贝:glMapBuffer + memcpy
通过内存映射方式操作缓冲数据,流程如下:
- 调用
glMapBuffer获取显存缓冲的内存指针; - 通过
memcpy直接将内存数据拷贝至显存缓冲; - 数据拷贝完成后,调用
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:只写目标缓冲类型,用于绑定数据写入的目标缓冲