Chapter 104 · 离屏渲染与 GPU 管线

Material 与 Mesh

Material 封装渲染状态(Shader + 纹理 + 混合),Mesh 管理顶点/索引数据,二者组合完成自定义几何绘制。

104

概念

Material:渲染状态容器,绑定 Shader、纹理(最多 3 张)、颜色、混合模式。 调用 MaterialDraw 时一次性设置所有状态并绘制。
Mesh:顶点 + 索引的 GPU 缓冲区封装,支持创建、更新、绘制。 适合自定义几何体(地形、粒子、3D 模型)。

API 速查

函数说明
void xgeMaterialInit(xge_material pMaterial)初始化 Material
void xgeMaterialFree(xge_material pMaterial)释放
void xgeMaterialSetShader(xge_material pMaterial, xge_shader pShader)绑定 Shader
void xgeMaterialSetTexture(xge_material pMaterial, xge_texture pTexture)绑定纹理槽 0
void xgeMaterialSetTexture2/3(...)绑定纹理槽 1/2
void xgeMaterialSetColor(xge_material pMaterial, uint32_t iColor)设置颜色
void xgeMaterialSetBlend(xge_material pMaterial, int iBlend)设置混合模式
void xgeMaterialDraw(xge_material pMaterial, const xge_draw_t* pDraw)绘制
int xgeMeshCreate(xge_mesh pMesh, const xge_vertex_t* pVertices, int iVertexCount, const uint16_t* pIndices, int iIndexCount, uint32_t iFlags)创建 Mesh
int xgeMeshUpdate(xge_mesh pMesh, ...)更新顶点/索引
void xgeMeshDraw(xge_mesh pMesh, xge_texture pTexture, uint32_t iFlags)绘制 Mesh
void xgeMeshFree(xge_mesh pMesh)释放 Mesh

编译本章示例

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

示例:自定义三角形 Mesh

// 定义三角形顶点
xge_vertex_t verts[3] = {
    { { 400, 100 }, { 0.5f, 0 }, 0xFF0000FF },
    { { 200, 400 }, { 0, 1 },   0x00FF00FF },
    { { 600, 400 }, { 1, 1 },   0x0000FFFF },
};
uint16_t indices[3] = { 0, 1, 2 };

// 创建 Mesh
xge_mesh_t mesh;
xgeMeshCreate(&mesh, verts, 3,
    indices, 3, 0);

// 每帧绘制
xgeMeshDraw(&mesh, NULL, 0);

// Material 方式绘制
xge_material_t mat;
xgeMaterialInit(&mat);
xgeMaterialSetShader(&mat, &myShader);
xgeMaterialSetTexture(&mat, &tex);
xgeMaterialSetColor(&mat, 0xFFFFFFFF);

xge_draw_t draw = { 0 };
draw.tDst = (xge_rect_t){ 0, 0, 800, 600 };
xgeMaterialDraw(&mat, &draw);

xgeMeshFree(&mesh);
xgeMaterialFree(&mat);

完整代码

将以下代码保存为 ch104_main.c,编译后运行即可看到自定义 Mesh 与 Material 绘制效果:

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

static xge_mesh_t g_mesh;
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;

    // 绘制自定义三角形 Mesh
    xgeMeshDraw(&g_mesh, NULL, 0);

    // 动态更新顶点(呼吸动画)
    float scale = 1.0f + 0.2f * sinf(g_time * 2.0f);
    xge_vertex_t verts[3] = {
        { 400, 100 * scale + 200*(1-scale),
          0.5f, 0, 0xFF0000FF },
        { 200, 400, 0, 1, 0x00FF00FF },
        { 600, 400, 1, 1, 0x0000FFFF },
    };
    xgeMeshUpdate(&g_mesh, verts, 3, NULL, 0);

    xgeTextDraw(g_font, "Custom Mesh: RGB Triangle",
        50.0f, 50.0f, 0xFFFFFFFF)

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch104 - Custom Mesh & Material";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

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

    // 定义三角形顶点
    xge_vertex_t verts[3] = {
        { 400, 100, 0.5f, 0, 0xFF0000FF },
        { 200, 400, 0, 1, 0x00FF00FF },
        { 600, 400, 1, 1, 0x0000FFFF },
    };
    uint16_t indices[3] = { 0, 1, 2 };

    // 创建 Mesh
    xgeMeshCreate(&g_mesh, verts, 3,
        indices, 3, 0);

    xgeRun(onFrame, NULL);

    xgeMeshFree(&g_mesh);
    xgeFontFree(g_font);
    xgeUnit();
    return 0;
}

代码讲解

  • MeshCreate:从顶点数组和索引数组创建 GPU Mesh,flags 控制是否动态更新。
  • MeshDraw:绘制 Mesh,可指定纹理(NULL 表示纯顶点色)。
  • MeshUpdate:更新顶点数据,顶点数不能超过 Create 时的容量。
  • 呼吸动画:用 sinf 动态缩放顶点 Y 坐标,展示 MeshUpdate 用法。

要点与陷阱

  • Material vs Mesh:Material 管状态,Mesh 管几何;可组合使用。
  • 纹理槽:最多 3 张纹理(SetTexture/2/3)。
  • MeshUpdate:顶点数不能超过 Create 时的容量。
  • Flags:MeshCreate 的 flags 控制是否动态更新。

进阶练习

  1. 实现 2D 骨骼动画:每帧 MeshUpdate 更新顶点位置。
  2. 多纹理合成:Material 绑定 3 张纹理,Shader 混合。
Material 与 Mesh效果
图:Material 与 Mesh渲染效果