Chapter 60 · ShapeEx 进阶

裁剪:模板裁剪

StencilClip 手动控制模板缓冲裁剪的 Begin/End 配对,适合自定义裁剪流程。

60

概念

  • 手动模板裁剪:Begin 写入模板缓冲 → 绘制内容 → End 恢复状态。
  • Begin/End 配对:必须严格配对调用,否则渲染状态错乱。
  • Px 版本:像素坐标版本,不经过相机变换。

API 速查

函数说明
int xgeShapeExStencilClipBegin(xge_shape_ex pClipShape, float fTolerance, const xge_shape_ex_matrix_t* pParentMatrix, int* pApplied)开始模板裁剪
int xgeShapeExStencilClipBeginPx(xge_shape_ex pClipShape, float fTolerance, const xge_shape_ex_matrix_t* pParentMatrix, int* pApplied)开始模板裁剪(像素坐标)
int xgeShapeExStencilClipEnd(int bApplied, int iRet)结束模板裁剪

编译本章示例

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

示例:手动模板裁剪

// 裁剪形状:圆角矩形
xge_shape_ex clip = NULL;
xgeShapeExCreate(&clip);
xgeShapeExAppendRect(clip, 100,100, 600,400, 30,30, 1);

int bApplied = 0;
xgeShapeExStencilClipBegin(clip, 0.25f, NULL, &bApplied);

if (bApplied) {
    // 在裁剪区域内绘制任意内容
    xgeShapeExDraw(g_content1, 0.25f);
    xgeShapeExDraw(g_content2, 0.25f);
}

xgeShapeExStencilClipEnd(bApplied, 0);

完整代码

将以下代码保存为 ch60_main.c,编译后运行即可看到手动模板裁剪效果:

#include "xge.h"

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

    // 裁剪形状:圆角矩形
    xge_shape_ex clip = NULL;
    xgeShapeExCreate(&clip);
    xgeShapeExAppendRect(clip, 100,100, 600,400, 30,30, 1);

    int bApplied = 0;
    xgeShapeExStencilClipBegin(clip, 0.25f, NULL, &bApplied);

    if (bApplied) {
        // 在裁剪区域内绘制多个图形
        xge_shape_ex c1 = NULL;
        xgeShapeExCreate(&c1);
        xgeShapeExAppendCircle(c1, 300, 300, 150, 150, 1);
        xgeShapeExFillColor(c1, 0x4FD8C2FF);
        xgeShapeExDraw(c1, 0.25f);
        xgeShapeExDestroy(c1);

        xge_shape_ex c2 = NULL;
        xgeShapeExCreate(&c2);
        xgeShapeExAppendCircle(c2, 500, 300, 150, 150, 1);
        xgeShapeExFillColor(c2, 0xFFB454FF);
        xgeShapeExDraw(c2, 0.25f);
        xgeShapeExDestroy(c2);
    }

    xgeShapeExStencilClipEnd(bApplied, 0);
    xgeShapeExDestroy(clip);
    return XGE_OK;
}

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

代码讲解

  • StencilClipBegin:手动开始模板裁剪,将裁剪形状写入模板缓冲。
  • bApplied:检查模板缓冲是否可用,为 0 时应跳过绘制。
  • Begin/End 配对:无论 bApplied 值如何,都必须调用 End。
  • 多 Shape 统一裁剪:Begin/End 之间可绘制多个 Shape,共享同一裁剪区域。

要点与陷阱

  • 必须配对:Begin 后无论是否 bApplied,都必须调用 End。
  • bApplied 检查:如果模板缓冲不可用,bApplied=0,应跳过绘制。
  • 嵌套:不建议嵌套多层 StencilClip,可能超出模板位深度。
  • vs ClipShapeAdd:ClipShapeAdd 是自动管理,StencilClip 是手动控制。

进阶练习

  1. 用 StencilClip 实现圆形头像裁剪 + 边框描边。
  2. 在 Begin/End 之间绘制多个 Shape,实现统一裁剪区域。
裁剪:模板裁剪效果
图:裁剪:模板裁剪渲染效果