Chapter 101 · 离屏渲染与 GPU 管线

Render Pass

Pass 封装了"绑定 RT → 清屏 → 绘制 → 解绑"的完整流程,是组织多 RT 渲染的核心结构。

101

概念

Render Pass 是一次完整的渲染过程:绑定目标帧缓冲、执行清屏、接收绘制命令、解绑。 一帧可以包含多个 Pass(如:阴影 Pass → 场景 Pass → UI Pass), 每个 Pass 输出到不同的 RT。

API 速查

函数说明
void xgePassInit(xge_pass pPass, xge_render_target pTarget, uint32_t iClearFlags, uint32_t iClearColor)初始化 Pass
int xgePassBegin(xge_pass pPass)开始 Pass(绑定 RT + 清屏)
int xgePassEnd(xge_pass pPass)结束 Pass(解绑 RT)

编译本章示例

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

示例:多 Pass 渲染

// Pass 1:渲染场景到离屏 RT
xge_pass_t scenePass;
xgePassInit(&scenePass, &sceneRT,
    XGE_PASS_CLEAR_COLOR,
    0x1A1A2EFF);

xgePassBegin(&scenePass);
// 绘制 3D 场景...
xgeShapeCircleFill(400, 300, 80, 0xFF6B5EFF);
xgePassEnd(&scenePass);

// Pass 2:渲染 UI 到窗口
xge_render_target_t winRT;
xgeRenderTargetWindow(&winRT);

xge_pass_t uiPass;
xgePassInit(&uiPass, &winRT,
    XGE_PASS_CLEAR_COLOR, 0x0D1117FF);

xgePassBegin(&uiPass);
// 将场景纹理绘制为背景
xgeDraw(xgeRenderTargetTexture(&sceneRT), 0, 0);
// 绘制 UI 覆盖层
xgeTextDraw(font, "HUD", 10, 10, 0xFFFFFFFF);
xgePassEnd(&uiPass);

完整代码

将以下代码保存为 ch101_main.c,编译后运行即可看到多 Pass 渲染效果:

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

static xge_render_target_t g_sceneRT;
static xge_font g_font = NULL;
static float g_time = 0.0f;

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

    // Pass 1:渲染场景到离屏 RT
    xge_pass_t scenePass;
    xgePassInit(&scenePass, &g_sceneRT,
        XGE_PASS_CLEAR_COLOR,
        0x1A1A2EFF);
    xgePassBegin(&scenePass);

    float cx = 200.0f + 120.0f * cosf(g_time);
    float cy = 150.0f + 80.0f * sinf(g_time * 1.3f);
    xgeShapeCircleFill(cx, cy, 50.0f, 0xFF6B5EFF);
    xgeShapeRectStroke((xge_rect_t){50, 50, 300, 200}, 2.0f, 0x44FFFFFF)

    xgePassEnd(&scenePass);

    // Pass 2:渲染 UI 到窗口
    xge_render_target_t winRT;
    xgeRenderTargetWindow(&winRT);

    xge_pass_t uiPass;
    xgePassInit(&uiPass, &winRT,
        XGE_PASS_CLEAR_COLOR, 0x0D1117FF);
    xgePassBegin(&uiPass);

    // 将场景纹理绘制为背景
    xgeDraw(xgeRenderTargetTexture(&g_sceneRT),
        100.0f, 50.0f);

    // HUD 覆盖层
    xgeTextDraw(g_font, "Multi-Pass: Scene + UI",
        100.0f, 400.0f, 0xFFFFFFFF)

    xgePassEnd(&uiPass);

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch101 - Multi Pass Rendering";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);
    xgeRenderTargetCreate(&g_sceneRT, 400, 300);

    xgeRun(onFrame, NULL);

    xgeRenderTargetFree(&g_sceneRT);
    xgeFontFree(g_font);
    xgeUnit();
    return 0;
}

代码讲解

  • PassInit:初始化 Pass,指定目标 RT、清除标志和清除颜色。
  • Pass 1 场景:将 3D 场景渲染到离屏 RT,与 UI 分离。
  • Pass 2 UI:将场景纹理作为背景,再绘制 HUD 覆盖层到窗口。
  • 不可嵌套:Pass 必须 End 后才能 Begin 另一个,不能嵌套使用。

要点与陷阱

  • ClearFlags:XGE_PASS_CLEAR_COLOR 清颜色;2D 渲染通道没有深度清屏标志。
  • 嵌套:Pass 不能嵌套,必须 End 后才能 Begin 另一个。
  • Init 复用:同一 Pass 可每帧 Begin/End,无需重新 Init。
  • 窗口 Pass:主帧缓冲的 Pass 通常在 xgeBegin/xgeEnd 内部自动管理。

进阶练习

  1. 实现后处理管线:场景 Pass → 模糊 Pass → 合成 Pass。
  2. 多视口:两个 Pass 分别渲染左右画面(分屏)。
Render Pass效果
图:Render Pass渲染效果