Chapter 32 · 基础图元

渲染模式切换:AA-Mesh vs SDF

XGE 提供两种图元渲染算法:AA-Mesh(抗锯齿网格)和 SDF(有向距离场)。本章学习如何切换及各自适用场景。

32

概念:两种渲染算法

  • AA-Mesh(默认):将图形细分为三角形网格,边缘通过多采样或覆盖率实现抗锯齿。适合大多数场景,性能稳定。
  • SDF(有向距离场):用数学距离函数描述形状,片元着色器根据距离值决定像素透明度。边缘极度平滑,缩放无损,适合大尺寸/高 DPI。
  • 全局切换:一次设置影响后续所有 Shape 绘制调用。

API 速查

函数 / 常量说明
#define XGE_SHAPE_RENDER_AA_MESH 0抗锯齿网格模式(默认)
#define XGE_SHAPE_RENDER_SDF 1SDF 距离场模式
void xgeShapeRenderModeSet(int iMode)设置全局图元渲染模式
int xgeShapeRenderModeGet(void)获取当前渲染模式

编译本章示例

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

示例 1:对比两种模式

// 上半屏:AA-Mesh 模式
xgeShapeRenderModeSet(XGE_SHAPE_RENDER_AA_MESH);
xgeShapeCircleFill(200, 200, 80, 0x4FD8C2FF);
xgeShapeRoundRectFill((xge_rect_t){350,140,160,120}, 20, 0xFFB454FF);

// 下半屏:SDF 模式
xgeShapeRenderModeSet(XGE_SHAPE_RENDER_SDF);
xgeShapeCircleFill(200, 450, 80, 0x4FD8C2FF);
xgeShapeRoundRectFill((xge_rect_t){350,390,160,120}, 20, 0xFFB454FF);

// 恢复默认
xgeShapeRenderModeSet(XGE_SHAPE_RENDER_AA_MESH);

示例 2:查询当前模式

int mode = xgeShapeRenderModeGet();
if (mode == XGE_SHAPE_RENDER_SDF) {
    xgeLogWrite(XGE_LOG_INFO, "当前使用 SDF 渲染");
} else {
    xgeLogWrite(XGE_LOG_INFO, "当前使用 AA-Mesh 渲染");
}

示例 3:高 DPI 场景自动切换

// 高 DPI 屏幕使用 SDF 获得更锐利的边缘
float dpi = xgePlatformRuntimeGet()->fContentScale;
if (dpi > 1.5f) {
    xgeShapeRenderModeSet(XGE_SHAPE_RENDER_SDF);
} else {
    xgeShapeRenderModeSet(XGE_SHAPE_RENDER_AA_MESH);
}

完整代码

将以下代码保存为 ch32_main.c,编译后运行即可对比 AA-Mesh 与 SDF 两种渲染模式的边缘质量:

#include "xge.h"

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

    // 上半屏:AA-Mesh 模式
    xgeShapeRenderModeSet(XGE_SHAPE_RENDER_AA_MESH);
    xgeShapeCircleFill(200, 180, 80, 0x4FD8C2FF);
    xge_rect_t r1 = { 350, 120, 180, 120 };
    xgeShapeRoundRectFill(r1, 24.0f, 0xFFB454FF);

    // 下半屏:SDF 模式
    xgeShapeRenderModeSet(XGE_SHAPE_RENDER_SDF);
    xgeShapeCircleFill(200, 430, 80, 0x4FD8C2FF);
    xge_rect_t r2 = { 350, 370, 180, 120 };
    xgeShapeRoundRectFill(r2, 24.0f, 0xFFB454FF);

    // 恢复默认
    xgeShapeRenderModeSet(XGE_SHAPE_RENDER_AA_MESH);

    // 查询当前模式
    int mode = xgeShapeRenderModeGet();
    (void)mode;

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch32 - AA-Mesh vs SDF";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • 帧内切换:同一帧内可多次调用 xgeShapeRenderModeSet,对不同图形使用不同渲染算法。
  • AA-Mesh:将图形细分为三角形网格,边缘通过覆盖率抗锯齿,性能稳定,适合大多数场景。
  • SDF:用数学距离函数描述形状,边缘极度平滑,缩放无损,适合大尺寸/高 DPI。
  • 恢复默认:演示结束后恢复 AA-Mesh,避免影响后续绘制。

要点与陷阱

  • 默认 AA-Mesh:引擎启动后默认为 AA-Mesh,无需显式设置。
  • 全局状态:切换影响后续所有 Shape* 调用(包括 Px 版本),直到再次切换。
  • SDF 优势:边缘数学级平滑、任意缩放不失真、大圆角/大尺寸表现优异。
  • SDF 代价:小尺寸图形可能比 AA-Mesh 稍慢(片元着色器计算距离)。
  • 与 RoundRectMode 独立:xgeShapeRenderModeSet 控制所有图元;xgeShapeRoundRectModeSet 仅控制圆角矩形(第 30 章)。
  • 帧内切换:可以在同一帧内多次切换,对不同图形使用不同模式。

进阶练习

  1. 在同一帧内分别用 AA-Mesh 和 SDF 绘制一个半径 200 的圆,截图放大 400% 对比边缘。
  2. 实现一个性能基准:用两种模式各绘制 10000 个圆,对比 FPS。
  3. 设计一个"渲染模式"调试面板:按键切换模式,屏幕角落实时显示当前模式名称。
渲染模式切换:AA-Mesh vs SDF效果
图:渲染模式切换:AA-Mesh vs SDF渲染效果