Chapter 45 · ShapeEx 填充与描边

渐变坐标变换

通过矩阵变换旋转、缩放、平移渐变坐标系,实现斜向渐变、动态旋转渐变等效果。

45

概念

  • 渐变变换矩阵:独立于 Shape 变换,仅作用于渐变坐标空间。
  • 典型用途:旋转渐变方向、缩放渐变范围、偏移动画。
  • Identity:重置为单位矩阵,恢复渐变原始坐标。

API 速查

函数说明
int xgeShapeExFillGradientTransformSet(xge_shape_ex pShape, const xge_shape_ex_matrix_t* pMatrix)设置渐变变换矩阵
int xgeShapeExFillGradientTransformIdentity(xge_shape_ex pShape)重置为单位矩阵
int xgeShapeExFillGradientTransformGet(xge_shape_ex pShape, xge_shape_ex_matrix_t* pMatrix)获取当前渐变变换

编译本章示例

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

示例 1:旋转渐变 45°

xge_shape_ex_color_stop_t stops[] = {
    { 0.0f, 0x4FD8C2FF },
    { 1.0f, 0xFFB454FF },
};

xge_shape_ex shape = NULL;
xgeShapeExCreate(&shape);
xgeShapeExAppendRect(shape, 100,150, 600,300, 16,16, 1);

// 水平渐变
xgeShapeExFillLinearGradient(shape,
    0,0, 1,0,
    XGE_SHAPE_EX_GRADIENT_OBJECT_BOUNDING_BOX,
    stops, 2);

// 旋转渐变坐标系 45°
xge_shape_ex_matrix_t m;
xgeShapeExMatrixIdentity(&m);
xgeShapeExMatrixRotate(&m, 45.0f);
xgeShapeExFillGradientTransformSet(shape, &m);

xgeShapeExDraw(shape, 0.25f);

示例 2:动态旋转渐变动画

// 在帧循环中每帧更新旋转角度
static float s_fAngle = 0.0f;

void OnFrame(void) {
    s_fAngle += 1.0f;
    if (s_fAngle >= 360.0f) s_fAngle -= 360.0f;

    xge_shape_ex_matrix_t m;
    xgeShapeExMatrixIdentity(&m);
    xgeShapeExMatrixRotate(&m, s_fAngle);
    xgeShapeExFillGradientTransformSet(g_shape, &m);

    xgeShapeExDraw(g_shape, 0.25f);
}

完整代码

将以下代码保存为 ch45_main.c,编译后运行即可看到渐变坐标旋转动画效果:

#include "xge.h"

static float s_fAngle = 0.0f;

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

    s_fAngle += 1.0f;
    if (s_fAngle >= 360.0f) s_fAngle -= 360.0f;

    xge_shape_ex_color_stop_t stops[] = {
        { 0.0f, 0x4FD8C2FF },
        { 1.0f, 0xFFB454FF },
    };

    xge_shape_ex shape = NULL;
    xgeShapeExCreate(&shape);
    xgeShapeExAppendRect(shape, 100,150, 600,300, 16,16, 1);

    // 水平渐变(OBJECT_BOUNDING_BOX 模式)
    xgeShapeExFillLinearGradient(shape,
        0,0, 1,0,
        XGE_SHAPE_EX_GRADIENT_OBJECT_BOUNDING_BOX,
        stops, 2);

    // 旋转渐变坐标系
    xge_shape_ex_matrix_t m;
    xgeShapeExMatrixIdentity(&m);
    xgeShapeExMatrixRotate(&m, s_fAngle);
    xgeShapeExFillGradientTransformSet(shape, &m);

    xgeShapeExDraw(shape, 0.25f);
    xgeShapeExDestroy(shape);
    return XGE_OK;
}

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

代码讲解

  • s_fAngle:静态变量保存当前旋转角度,每帧加 1°,实现动画。
  • OBJECT_BOUNDING_BOX:渐变坐标在 0~1 归一化空间,矩阵操作此空间。
  • xgeShapeExMatrixIdentity + Rotate:先重置为单位矩阵,再旋转指定角度。
  • FillGradientTransformSet:将变换矩阵应用到填充渐变,不影响图形本身的变换。
  • 独立于 Shape 变换:ShapeExTransformSet 变换图形,GradientTransform 只变换渐变坐标。

要点与陷阱

  • 独立于 Shape 变换:ShapeExTransformSet 变换图形本身,GradientTransform 只变换渐变坐标。
  • 归一化坐标注意:OBJECT_BOUNDING_BOX 模式下,矩阵操作的是 0~1 空间。
  • 重置:调用 Identity 可恢复默认(无变换)。
  • 仅影响填充渐变:描边渐变有独立的 StrokeGradientTransform(第 50 章)。

进阶练习

  1. 用缩放矩阵让渐变只覆盖图形中心 50% 区域。
  2. 组合平移 + 旋转实现"扫描光"动画效果。
渐变坐标变换效果
图:渐变坐标变换渲染效果