xfangfang / borealis

Hardware accelerated, Nintendo Switch inspired UI library for PC, Android, iOS, PSV, PS4 and Nintendo Switch
Apache License 2.0
31 stars 21 forks source link

nanovg supports setting custom stencil #40

Closed xfangfang closed 10 months ago

xfangfang commented 11 months ago

支持自定义模板测试,添加了两个新的接口:

// Work like nvgFill, but only supports drawing image with alpha channels.
// The image is used to create a stencil buffer, which will be used for subsequent drawing operations,
// and only the content corresponding to the non-transparent part of the stencil buffer will be displayed.
void nvgStencil(NVGcontext* ctx);

// Clear stencil buffer and disable stencil test.
void nvgStencilClear(NVGcontext* ctx);

在需要使用模版测试的位置前后分别添加 nvgStencil (nvgStencil功能类似于 nvgFill) 和 nvgStencilClear,两条语句之间绘制的内容只显示在 nvgStencil 绘制的非透明区域。

注意1:目前 nvgStencil 只支持绘制图片用作模板缓冲区(因为没有其他需求所以nvgFill 支持的其他绘制内容暂时先不做)。 注意2:nvgStencilClear 做的是全局清空,虽然可以指定区域清空,但是考虑到实际需求(并不需要指定区域),做全局清空性能更好 。 注意3:一个更好的实现是模仿 nvgCreateImageRGBA 添加一个新的函数 nvgCreateImageA 只传递alpha通道来创建纹理,可以更节省向GPU传输数据的量 (RGBA -> A,因为RGB本身也没有用到)。

示例代码:

    // 设置遮罩
    nvgBeginPath(vg);
    auto paint = nvgImagePattern(vg, x, y, w, h, 0, tex, alpha);
    nvgRect(vg, x, y, w, h);
    nvgFillPaint(vg, paint);
    nvgStencil(vg);

    // 绘制文字/图案 等内容
    ...

    // 清空遮罩
    nvgBeginPath(vg);
    nvgRect(vg, x, y, width, height);
    nvgStencilClear(vg);

目前只在 OpenGL 下实现,对于其他不支持的图形后端,nvgStencilnvgStencilClear 将等同于 nvgFill

直接使用 nvgFill 的效果:

image

使用 nvgStencil 的效果:

image