Chapter 13 · 渲染管线

深度测试

理解 XGE 中深度缓冲的作用,学习如何启用/禁用深度测试来控制图元的前后遮挡关系。

13

概念:为什么需要深度测试

在纯 2D 渲染中,绘制顺序决定了遮挡关系(后画的覆盖先画的)。但当使用透视投影或 3D 变换(如 xgeDrawQuad3D)时,仅靠绘制顺序无法正确处理遮挡——这时需要深度缓冲(Z-Buffer)。

XGE 默认关闭深度测试。开启后,每个片元在写入颜色缓冲前会与深度缓冲比较,只有"更近"的片元才能通过。

何时开启:使用透视相机(第 15 章)、3D 四边形绘制、或需要真实遮挡关系的场景。普通 2D UI 不需要深度测试。

API 速查

函数说明
void xgeDepthTestSet(int bEnabled)启用(1)或禁用(0)深度测试
int xgeDepthTestGet(void)查询当前深度测试状态(1=开启)

编译本章示例

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

示例 1:开启深度测试

static int onFrame(void* pUser) {
    xgeClear(0x081114FF);

    // 开启深度测试
    xgeDepthTestSet(1);

    // 使用透视相机(见第 15 章)
    xge_camera_t cam = xgeCameraPerspective(
        800, 600,   // 视口尺寸
        60.0f,       // FOV
        0.1f,        // 近裁剪面
        1000.0f      // 远裁剪面
    );
    xgeCameraSet(&cam);

    // 绘制 3D 四边形(深度测试确保正确遮挡)
    // xgeDrawQuad3D(...);

    // 2D 绘制前关闭深度测试
    xgeDepthTestSet(0);
    return XGE_OK;
}

示例 2:状态查询与保护

// 保存当前状态
int bWasDepth = xgeDepthTestGet();

// 临时开启
xgeDepthTestSet(1);
// ... 3D 绘制代码 ...

// 恢复原始状态
xgeDepthTestSet(bWasDepth);

深度测试 vs 绘制顺序

场景推荐方式
2D UI / HUD关闭深度测试,靠绘制顺序
2.5D 等距视角关闭深度测试,手动排序
透视 3D 场景开启深度测试
粒子系统(加法混合)关闭深度测试(避免粒子被裁切)

完整代码

将以下代码保存为 ch13_main.c,编译后运行即可观察深度测试状态切换:

#include "xge.h"

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);

    // 查询并显示当前深度测试状态
    int bDepth = xgeDepthTestGet();

    // 按空格键切换深度测试
    if (xgeKeyPressed(XGE_KEY_SPACE)) {
        xgeDepthTestSet(!bDepth);
    }

    // 绘制两个重叠矩形(观察遮挡关系)
    xgeShapeRectFill(200, 200, 250, 200, 0x4FD8C2FF);
    xgeShapeRectFill(350, 250, 250, 200, 0xFF6B5EFF);

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch13 - Depth Test";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • xgeDepthTestGet() 返回当前深度测试状态(0=关闭,1=开启)。
  • xgeDepthTestSet(!bDepth) 取反当前状态,实现一键切换。
  • 在纯 2D 场景中,深度测试的效果不明显(因为绘制顺序已决定遮挡)。它主要在透视相机 + 3D 四边形场景中有用。
  • 按空格键切换后,观察两个重叠矩形的遮挡关系变化。

要点与陷阱

  • 默认关闭——XGE 是 2D 引擎,深度测试默认禁用。大多数 2D 应用永远不需要开启。
  • 深度缓冲精度:由初始化时的帧缓冲格式决定,不可运行时更改。
  • 与混合模式的交互:开启深度测试后,被遮挡的片元不会参与混合计算。
  • 透明物体排序:深度测试不能正确处理半透明物体的叠加。半透明物体应在不透明物体之后、关闭深度写入来绘制。
  • 性能影响:深度测试增加每片元的比较开销,但在现代 GPU 上几乎可忽略。

进阶练习

  1. 开启深度测试 + 透视相机,绘制两个交叉的 3D 四边形,观察正确遮挡。
  2. 对比开启/关闭深度测试时,改变绘制顺序对结果的影响。
  3. 实现一个"深度可视化":用颜色映射深度值,近处红色、远处蓝色。
深度测试效果
图:深度测试渲染效果