使用裁剪节点实现蒙版效果
在游戏开发和图形渲染中,蒙版效果是一种常见的技术,用于控制图像或场景的可见区域。在 Dora SSR 中,我们可以使用 ClipNode
类轻松实现各种蒙版效果。本教程将通过示例代码,指导您如何使用 ClipNode
来实现基于形状和图像的蒙版效果。
1. 什么是 ClipNode
ClipNode
是 Dora SSR 中的一个场景节点类,用于设置裁剪蒙版,从而控 制子节点的可见区域。通过指定一个蒙版节点(stencil
),ClipNode
会根据蒙版的形状或透明度来裁剪其子节点的渲染内容。
1.1 ClipNode 的主要属性
- stencil: 定义裁剪形状的蒙版节点。
- alphaThreshold: 生效的用于裁剪的蒙版像素的 alpha 阈值(0 到 1 之间)。只有当蒙版像素的 alpha 值大于该阈值时,裁剪才会生效。
- inverted: 是否翻转裁剪区域。当设置为
true
时,裁剪区域和非裁剪区域互换。
2. 示例 A:使用任意形状作为蒙版
在第一个示例中,我们将使用一个五角星形状作为蒙版,裁剪一个动画模型的显示区域。
2.1 步骤解析
- 创建五角星形状的顶点数据
- Lua
- Teal
- TypeScript
- YueScript
local function StarVertices(radius, line)
-- 计算五角星的顶点坐标
local a = math.rad(36)
local c = math.rad(72)
local f = math.sin(a) * math.tan(c) + math.cos(a)
local R = radius
local r = R / f
local vecs = {}
local count = 1
for i = 9, line and -1 or 0, -1 do
local angle = i * a
local cr = i % 2 == 1 and r or R
vecs[count] = Vec2(cr * math.sin(angle), cr * math.cos(angle))
count = count + 1
end
-- 返回顶点数组
return vecs
end
local function StarVertices(radius: number, line: integer): {Vec2.Type}
-- 计算五角星的顶点坐标
local a = math.rad(36)
local c = math.rad(72)
local f = math.sin(a) * math.tan(c) + math.cos(a)
local R = radius
local r = R / f
local vecs: {Vec2.Type} = {}
local count = 1
for i = 9, line and -1 or 0, -1 do
local angle = i * a
local cr = i % 2 == 1 and r or R
vecs[count] = Vec2(cr * math.sin(angle), cr * math.cos(angle))
count = count + 1
end
-- 返回顶点数组
return vecs
end
function StarVertices(radius: number, line: number) {
// 计算五角星的顶点坐标
const a = math.rad(36);
const c = math.rad(72);
const f = math.sin(a) * math.tan(c) + math.cos(a);
const R = radius;
const r = R / f;
const vecs: Vec2.Type[] = []
for (let i = 9; line ? -1 : 0; i--) {
const angle = i * a;
const cr = i % 2 == 1 ? r : R
vecs.push(Vec2(cr * math.sin(angle), cr * math.cos(angle)));
}
// 返回顶点数组
return vecs;
}
StarVertices = (radius, line) ->
-- 计算五角星的顶点坐标
a = math.rad 36
c = math.rad 72
f = math.sin(a) * math.tan(c) + math.cos a
R = radius
r = R / f
vecs = []
for i = 9, line and -1 or 0, -1
angle = i * a
cr = i % 2 == 1 and r or R
vecs[] = Vec2 cr * math.sin(angle), cr * math.cos angle
-- 返回顶点数组
vecs
- 绘制蒙版形状
- Lua
- Teal
- TypeScript
- YueScript
local maskA = DrawNode()
maskA:drawPolygon(StarVertices(160, false))
local maskA = DrawNode()
maskA:drawPolygon(StarVertices(160, false))
const maskA = DrawNode();
maskA.drawPolygon(StarVertices(160, false));
maskA = DrawNode()
maskA.drawPolygon StarVertices(160, false)
这里,我们使用 DrawNode
绘制一个五角星形状,作为蒙版节点。
- 创建动画模型
- Lua
- Teal
- TypeScript
- YueScript
local targetA = Model("Model/xiaoli.model")
targetA.look = "happy"
targetA.fliped = true
-- 设置模型的动画和移动路径
targetA:play("walk", true)
targetA:runAction(
Sequence(
X(1.5, -200, 200), Event("Turn"),
X(1.5, 200, -200), Event("Turn")
), true
)
targetA:slot("Turn", function()
targetA.fliped = not targetA.fliped
end)
local targetA = Model("Model/xiaoli.model")
if not targetA is nil then
targetA.look = "happy"
targetA.fliped = true
-- 设置模型的动画和移动路径
targetA:play("walk", true)
targetA:runAction(
Sequence(
X(1.5, -200, 200), Event("Turn"),
X(1.5, 200, -200), Event("Turn")
), true
)
targetA:slot("Turn", function()
targetA.fliped = not targetA.fliped
end)
end
const targetA = Model("Model/xiaoli.model");
if (targetA) {
targetA.look = "happy";
targetA.fliped = true;
// 设置模型的动画和移动路径
targetA.play("walk", true);
targetA.runAction(
Sequence(
X(1.5, -200, 200), Event("Turn"),
X(1.5, 200, -200), Event("Turn")
), true
);
targetA.slot("Turn", () => {
targetA.fliped = !targetA.fliped;
});
}
targetA = with Model "Model/xiaoli.model"
.look = "happy"
.fliped = true
-- 设置模型的动画和移动路径
.play "walk", true
\runAction Sequence(
X 1.5, -200, 200, Event "Turn",
X 1.5, 200, -200, Event "Turn"
), true
\slot "Turn", ->
targetA.fliped = not targetA.fliped
- 创建 ClipNode 并添加子节点
- Lua
- Teal
- TypeScript
- YueScript
local clipNodeA = ClipNode(maskA)
clipNodeA:addChild(targetA)
clipNodeA.inverted = true
local clipNodeA = ClipNode(maskA)
clipNodeA:addChild(targetA)
clipNodeA.inverted = true
const clipNodeA = ClipNode(maskA);
clipNodeA.addChild(targetA);
clipNodeA.inverted = true;
clipNodeA = with ClipNode maskA
\addChild targetA
.inverted = true
我们将蒙版节点 maskA
传递给 ClipNode
,并将动画模型 targetA
添加为其子节点。
- 添加到场景中
- Lua
- Teal
- TypeScript
- YueScript
local exampleA = Node()
exampleA:addChild(clipNodeA)
local exampleA = Node()
exampleA:addChild(clipNodeA)
const exampleA = Node();
exampleA.addChild(clipNodeA);
exampleA = with Node!
\addChild clipNodeA
运行效果
运行上述代码后,您会看到模型仅在五角星形状内可见,而在五角星外部的部分被裁剪掉。
3. 示例 B:使用图像及 alphaThreshold 实现蒙版效果
在第二个示例中,我们将使用一个具有透明度的模型作为蒙版,并利用 alphaThreshold
属性来控制裁剪效果。
3.1 步骤解析
- 创建蒙版模型
- Lua
- Teal
- TypeScript
- YueScript
local maskB = Model("Model/xiaoli.model")
maskB.look = "happy"
maskB.fliped = true
maskB:play("walk", true)
local maskB = Model("Model/xiaoli.model")
if not maskB is nil then
maskB.look = "happy"
maskB.fliped = true
maskB:play("walk", true)
end
const maskB = Model("Model/xiaoli.model");
if (maskB) {
maskB.look = "happy";
maskB.fliped = true;
maskB.play("walk", true);
}
maskB = with Model "Model/xiaoli.model"
.look = "happy"
.fliped = true
.play "walk", true
这里,我们使用一个模型作为蒙版节点。
- 创建目标形状
- Lua
- Teal
- TypeScript
- YueScript
local targetB = DrawNode()
targetB:drawPolygon(StarVertices(160, false))
-- 设置目标形状的移动路径
targetB:runAction(
Sequence(
X(1.5, -200, 200),
X(1.5, 200, -200)
), true
)
local targetB = DrawNode()
targetB:drawPolygon(StarVertices(160, false))
-- 设置目标形状的移动路径
targetB:runAction(
Sequence(
X(1.5, -200, 200),
X(1.5, 200, -200)
), true
)
const targetB = DrawNode();
targetB.drawPolygon(StarVertices(160, false));
// 设置目标形状的移动路径
targetB.runAction(
Sequence(
X(1.5, -200, 200),
X(1.5, 200, -200)
), true
);
targetB = with DrawNode!
\drawPolygon StarVertices 160, false
-- 设置目标形状的移动路径
\runAction Sequence(
X 1.5, -200, 200,
X 1.5, 200, -200
), true
- 创建 ClipNode 并设置 alphaThreshold
- Lua
- Teal
- TypeScript
- YueScript
local clipNodeB = ClipNode(maskB)
clipNodeB:addChild(targetB)
clipNodeB.inverted = true
clipNodeB.alphaThreshold = 0.3
local clipNodeB = ClipNode(maskB)
clipNodeB:addChild(targetB)
clipNodeB.inverted = true
clipNodeB.alphaThreshold = 0.3
const clipNodeB = ClipNode(maskB);
clipNodeB.addChild(targetB);
clipNodeB.inverted = true;
clipNodeB.alphaThreshold = 0.3;
clipNodeB = with ClipNode maskB
\addChild targetB
.inverted = true
.alphaThreshold = 0.3
通过设置 alphaThreshold = 0.3
,只有当蒙版模型的像素 alpha 值大于 0.3 时,裁剪才会生效。
- 添加到场景中
- Lua
- Teal
- TypeScript
- YueScript
local exampleB = Node()
exampleB:addChild(clipNodeB)
local exampleB = Node()
exampleB:addChild(clipNodeB)
const exampleB = Node();
exampleB.addChild(clipNodeB);
exampleB = with Node!
\addChild clipNodeB
3.2 运行效果
运行代码后,您会发现目标形状仅在蒙版模型的非透明部分可见,实现了基于透明度的蒙版效果。
4. 总结
通过以上两个示例,我们学习了如何在 Dora SSR 中使用 ClipNode
实现不同的蒙版效果:
- 示例 A 展示了如何使用任意绘制的形状作为蒙版,裁剪子节点的显示区域。
- 示例 B 演示了如何利用
alphaThreshold
属性,使用具有透明度的图像或模型进行裁剪。
4.1 小贴士
- alphaThreshold 的使用:当蒙版节点包含半透明区域时,
alphaThreshold
非常有用。它允许您精细控制哪些像素参与裁剪。 - inverted 属性:通过切换
inverted
,您可以方便地反转裁剪区域,达到不同的视觉效果。
希望本教程能帮助您更好地理解和应用 Dora SSR 的 ClipNode
,创造出丰富多彩的蒙版效果。如有任何疑问,欢迎查阅官方文档或参与社区讨论。