[Shader]新手引导中的遮罩裁剪
Posted tianjiuwan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Shader]新手引导中的遮罩裁剪相关的知识,希望对你有一定的参考价值。
最近要写新手引导,记录一下
蒙黑(层级最上,蒙住整个UI,有镂空裁剪)镂空区域btn(是一个button 动态改变位置) 引导UI(做新手引导的UI) 活动UI(主动弹出的活动UI 层级位于引导UI上)
当然还有引导的小姐姐头像对话框以及镂空区域有特效提示
之前做法:蒙黑背景计算镂空区域,蒙黑镂空区域有一个btn,btn的点击可以渗透下去
但是会出现一种问题,点击镂空区域btn,可能发生异常,下面的按钮没有被渗透点击,但是这一步骤怎么办?我们也不方便记录
还有一个问题,如果在引导的时候出现一个活动UI(一种全屏UI,在活动时间主动弹出),这个时候引导UI的层级可能小于活动UI层级,当然可以在引导时候禁止UI其他UI打开,这个方法的
点击事件还是可以渗透活动UI到引导UI
之后做法:蒙黑依旧,蒙黑背景计算镂空区域,蒙黑镂空区域有一个btn
这个btn的点击事件不用渗透下去,不再挂载渗透点击脚本,而是监听点击事件
这个btn的点击事件的逻辑:调用引导步骤中按钮的点击事件 如果是button evt = button.onClick evt.Invoke() 如果是toggle tog.isOn = true
这个方法我配置的是指引按钮的路径,可能我们在Find的时候UI还没有打开,Find不到的时候我们递归调用(当然做一个CD时间)
还有一个问题是获取指引按钮的位置问题,UI刚打开的时候我们Find到了按钮,但是这个时候可能按钮还在做动画,那我们也需要持续更新位置信息(当然可以做一个CD tween做缓动)
还有一个问题是按钮的世界坐标获取,按钮的父节点有很多,父节点的锚点各种各样,我们需要把按钮的位置转到maskBg(蒙黑UI)之下
local pos = self.maskBg.gameObject.transform:InverseTransformPoint(go.transform.position)
做法可能多种多样,需求也是多种多样,有时候需要考虑需求的时候,需要改变策略,随机应变了
1<效果图>
<2>抠了个圆形
<3>属性说明(这里定义了2个变量 圆心 Type)
圆心:Vector(X Y Z W) 矩形: 如果是矩形按钮 X Y为坐标 Z W为宽高 圆形:X Y为坐标,Z为直径
Type:0为圆形裁剪 1为矩形裁剪
上面四张图已经展示得很清楚了 shader里面的计算也很简单 对比了一下uv与中心点的位置关系
<4>配置表(配置的Lua)
--之前配置格式 这种格式配置了每个步骤的位置信息 每一步开始直接做动画位移 方便;但是策划得配置这些区域 还是比较麻烦
GuideConfig ={}
--openCondition type 1=任务完成开启 v任务code 2=等级达到开启 v等级 3=系统开启时开启 v系统code
--pos x y z w x,y 坐标 z,w 宽高(圆只有Z直径)
--maskType 0 圆形裁剪 1 方形裁剪
GuideConfig[10086] = {}
GuideConfig[10086].openCondition = {type =1 , value1 = 11022}
GuideConfig[10086].step={}
GuideConfig[10086].step[1] ={maskType = 0, pos = \'597;-35;86;86\' , say = \'在这里打开技能面板\'}
GuideConfig[10086].step[2] ={ pos = \'-569.2;64.8;141.5;72.5\' , say = \'点击切换到天赋页签\'}
GuideConfig[10086].step[3] ={ pos = \'-209.6;91.9;88;88\' ,say = \'点击这里选中一个天赋\'}
GuideConfig[10086].step[4] ={ pos = \'436.9;-206.8;145;60\' ,say = \'接下来升级这个天赋吧\'}
---现在的配置格式
GuideConfig ={}
--openCondition type 1=任务完成开启 v任务code 2=等级达到开启 v等级 3=系统开启时开启 v系统code
--pos x y z w x,y 坐标 z,w 宽高(圆只有Z直径)
--maskType 0 圆形裁剪 1 方形裁剪
GuideConfig[10086] = {}
GuideConfig[10086].openCondition = {type =1 , value1 = 11022}
GuideConfig[10086].step={}
GuideConfig[10086].step[1] ={maskType = 0,path=\'UIRoot/MainUILayer/MainBottomRight/LastRightParent/LastRightPanel/SkillBtn\' , say = \'在这里打开技能面板\'}
GuideConfig[10086].step[2] ={path=\'UIRoot/ViewLayer/SkillMain/Selection/b_skillGift\', say = \'点击切换到天赋页签\'}
GuideConfig[10086].step[3] ={path=\'UIRoot/ViewLayer/SkillMain/GiftSkillPanel(Clone)/midVel/gifts/b_attackView/content/giftItem4\',say = \'点击这里选中一个天赋\'}
GuideConfig[10086].step[4] ={path=\'UIRoot/ViewLayer/SkillMain/GiftSkillPanel(Clone)/rightVel/bg/b_levelUpBtn\',say = \'接下来升级这个天赋吧\'}
<5>源码
Shader "Tang/GuideMask"
{
Properties
{
[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
_Color("Tint", Color) = (1,1,1,1)
_StencilComp("Stencil Comparison", Float) = 8
_Stencil("Stencil ID", Float) = 0
_StencilOp("Stencil Operation", Float) = 0
_StencilWriteMask("Stencil Write Mask", Float) = 255
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15
//中心
_Origin("圆心",Vector) = (0,0,0,0)
//裁剪方式 0圆形 1圆形
_MaskType("Type",Float) = 0
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Stencil
{
Ref[_Stencil]
Comp[_StencilComp]
Pass[_StencilOp]
ReadMask[_StencilReadMask]
WriteMask[_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest[unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask[_ColorMask]
Pass
{
Name "Default"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
#include "UnityUI.cginc"
#pragma multi_compile __ UNITY_UI_ALPHACLIP
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
fixed4 _Color;
fixed4 _TextureSampleAdd;
float4 _ClipRect;
float4 _Origin;
float _MaskType;
v2f vert(appdata_t IN)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
OUT.worldPosition = IN.vertex;
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
float2 uv = IN.texcoord;
half4 col = IN.color;
//开始裁剪
//外部直接给坐标 宽 高 GPU计算比率
float posX = (_Origin.x + 640) / 1280;
float posY = (_Origin.y + 360) / 720;
float2 pos = float2(posX, posY);
if (_MaskType == 0) {
posX = posX * 1280 / 720;
pos = float2(posX, posY);
float rid = _Origin.z / 720 / 2;
uv.x = uv.x * 1280 / 720;
float2 nor = uv-pos;
if (length(nor) < rid)
col.a = 0;
}
else {
float w = _Origin.z / 1280 / 2;
float h = _Origin.w / 720 / 2;
if (uv.x > pos.x - w && uv.x<pos.x + w && uv.y>pos.y - h && uv.y < pos.y + h)
col.a = 0;
}
half4 color = (tex2D(_MainTex,uv) + _TextureSampleAdd) * col;
color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
clip(col.a);
#ifdef UNITY_UI_ALPHACLIP
clip(color.a - 0.001);
#endif
return color;
}
ENDCG
}
}
}
以上是关于[Shader]新手引导中的遮罩裁剪的主要内容,如果未能解决你的问题,请参考以下文章