Chapter 100 · 离屏渲染与 GPU 管线

GPU Buffer

Buffer 是 GPU 端的通用数据缓冲区(VBO/IBO/UBO),用于存储顶点、索引和 Uniform 数据。

100

概念

GPU Buffer 是显存中的数据块,对应 OpenGL 的 Buffer Object。 类型包括:顶点缓冲(VBO)、索引缓冲(IBO)、Uniform 缓冲(UBO)。 Usage 提示 GPU 数据更新频率:Static(一次写入)、Dynamic(频繁更新)。

API 速查

函数说明
int xgeBufferCreate(xge_buffer pBuffer, int iType, int iUsage, const void* pData, int iSize)创建 Buffer
int xgeBufferUpdate(xge_buffer pBuffer, int iOffset, const void* pData, int iSize)更新子区域
int xgeBufferUpload(xge_buffer pBuffer)提交到 GPU
void xgeBufferFree(xge_buffer pBuffer)释放 Buffer

编译本章示例

gcc -O2 -I. -o ch100.exe ch100_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch100.exe

示例:动态顶点缓冲

// 创建动态顶点缓冲(1000 个顶点)
xge_buffer_t vbo;
int bufSize = 1000 * sizeof(xge_vertex_t);
xgeBufferCreate(&vbo,
    XGE_BUFFER_VERTEX,
    XGE_BUFFER_DYNAMIC,
    NULL, bufSize);

// 每帧更新顶点数据
xge_vertex_t verts[1000];
// ... 填充顶点 ...

xgeBufferUpdate(&vbo, 0,
    verts, sizeof(verts));
xgeBufferUpload(&vbo);

// 程序退出时释放
xgeBufferFree(&vbo);

完整代码

将以下代码保存为 ch100_main.c,编译后运行即可看到动态顶点缓冲更新效果:

#include "xge.h"
#include <math.h>
#include <string.h>

#define VERT_COUNT 360

static xge_buffer_t g_vbo;
static xge_font g_font = NULL;
static float g_time = 0.0f;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);
    g_time += 0.016f;

    // 每帧更新顶点数据(波形动画)
    xge_vertex_t verts[VERT_COUNT];
    for (int i = 0; i < VERT_COUNT; i++) {
        float t = (float)i / VERT_COUNT;
        verts[i].x = t * 700.0f + 50.0f;
        verts[i].y = 300.0f + 100.0f *
            sinf(t * 6.28f * 3.0f + g_time * 4.0f);
        verts[i].u = t;
        verts[i].v = 0.0f;
        verts[i].color = 0x44CCFFFF;
    }

    // 更新并提交到 GPU
    xgeBufferUpdate(&g_vbo, 0,
        verts, sizeof(verts));
    xgeBufferUpload(&g_vbo);

    xgeTextDraw(g_font, "Dynamic VBO: 360 vertices updated per frame",
        50.0f, 50.0f, 0xFFFFFFFF)

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch100 - Dynamic Vertex Buffer";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);

    // 创建动态顶点缓冲
    int bufSize = VERT_COUNT * sizeof(xge_vertex_t);
    xgeBufferCreate(&g_vbo,
        XGE_BUFFER_VERTEX,
        XGE_BUFFER_DYNAMIC,
        NULL, bufSize);

    xgeRun(onFrame, NULL);

    xgeBufferFree(&g_vbo);
    xgeFontFree(g_font);
    xgeUnit();
    return 0;
}

代码讲解

  • BufferCreate:创建指定类型和用途的 GPU 缓冲,DYNAMIC 表示每帧更新。
  • BufferUpdate:更新 CPU 端缓存的子区域数据,不会立即提交 GPU。
  • BufferUpload:将 CPU 缓存提交到 GPU,之后渲染管线可使用新数据。
  • 波形动画:每帧用 sinf 计算新顶点位置,展示动态 VBO 的典型用法。

要点与陷阱

  • Type:VERTEX / INDEX / UNIFORM,决定绑定点。
  • Usage:STATIC 适合不变数据;DYNAMIC 适合每帧更新。
  • Update:只更新 CPU 端缓存,需 Upload 才提交 GPU。
  • 大小:Create 后大小固定,不能扩容。

进阶练习

  1. 实现粒子系统:Dynamic VBO 每帧更新粒子位置。
  2. Uniform Buffer:将相机矩阵通过 UBO 传递给 Shader。
GPU Buffer效果
图:GPU Buffer渲染效果