本文分享Unity中使用模板测试模拟Mask组件效果

在上一篇文章中, 我们分享了模板测试的基础知识, 在今天的分享中, 我们会尝试使用模板测试来模拟遮罩效果.

Unity中使用模板测试模拟Mask组件效果

准备工作

首先, 我们需要准备两张图片, 一张圆形的半透图片当做遮罩, 一张头像图片. 如图两张图片:

创建两个材质和一个shader(直接复制Unity的UI-Default做修改), 如下:

  • CustomMask.shader
  • CustomMask.mat
  • Object.mat

对应的shader代码为:

# CustomMask.shader
Shader "Custom/CustomMask"
{Properties{[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}_Color ("Tint", Color) = (1,1,1,1)_Stencil ("Stencil ID", Float) = 0[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp ("Stencil Comparison", Int) = 8[Enum(UnityEngine.Rendering.StencilOp)] _StencilOp ("Stencil Operation", Int) = 0_StencilWriteMask ("Stencil Write Mask", Range(0, 255)) = 255_StencilReadMask ("Stencil Read Mask", Range(0, 255)) = 255_ColorMask ("Color Mask", Range(0, 15)) = 15[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 OffLighting OffZWrite OffZTest [unity_GUIZTestMode]Blend SrcAlpha OneMinusSrcAlphaColorMask [_ColorMask]Pass{Name "CustomMask"CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 2.0#include "UnityCG.cginc"#include "UnityUI.cginc"#pragma multi_compile __ UNITY_UI_ALPHACLIPstruct 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;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;float _OneMinusSaturability;fixed4 frag(v2f IN) : SV_Target{half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd);if (IN.color.r < 0.0001 && IN.color.g < 0.0001 && IN.color.b > 0.0001 && IN.color.b < 0.004){float gray = dot(color.rgb, float3(0.2125, 0.7154, 0.0721));color.rgb = float3(gray, gray, gray);}else{color *= IN.color;if (_OneMinusSaturability > 0.05){float gray = dot(color.rgb, float3(0.2125, 0.7154, 0.0721));color.rgb = lerp(float3(gray, gray, gray), color.rgb, 1 - _OneMinusSaturability);}}color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);#ifdef UNITY_UI_ALPHACLIPclip (color.a - 0.001);#endifreturn color;}ENDCG}}
}

shader很简单, 直接从对应版本的UGUI的默认shader复制即可, 为了方便在属性面板中查看, 可以使用一些特性来做标记:

[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp ("Stencil Comparison", Int) = 8
[Enum(UnityEngine.Rendering.StencilOp)] _StencilOp ("Stencil Operation", Int) = 0
_StencilWriteMask ("Stencil Write Mask", Range(0, 255)) = 255
_StencilReadMask ("Stencil Read Mask", Range(0, 255)) = 255

之后在属性面板上就可以直观看到信息:

然后构建三个RawImage, 一个显示原图, 一个是遮罩, 一个是头像, 如图:

它们的大小分别是,120x120, 100x100, 120x120, 此时看到的效果应该是:

好了, 现在开始正式工作, 通过调节模板参数来达到遮罩效果.

调节参数

首先来梳理一下思路.

我们的目标是将头像超出圆的部分截取掉, 只在圆的部分显示头像, 如图:

意思是我们需要在圆形的部分绘制头像, 根据模板测试的知识可以简单的得出结论, 只要在圆形的部分通过测试, 其它部分不通过即可达到目的.

首先我们绘制圆形遮罩, 指定一个参考值, 然后让其总是通过模板测试, 然后使用参考值来更新模板值, 设置如下:


此时圆形的图片所在的区域整个都会通过测试, 如图:

图中的绿色代表通过测试的区域. 此时绿色区域的模板值为参考值3.

接下来绘制头像, 指定一个相同的参考值, 然后设置为参考值相同才通过测试, 设置如下:

因为头像的大小为120x120, 而遮罩的大小为100x100, 所以超出的20x20无法通过测试, 如下:

图中红色部分代表未通过测试的区域, 此时的实际渲染结果就是超出的20x20部分被裁掉了:

那么如何裁掉圆形区域之外的部分呢?

直观的想法就是将圆形内部的参考值设置与圆形外部的不同. 但是参考值是针对整个图像来设置的, 我们无法手动指定不同区域. 另一个想法是在绘制圆形时, 过滤掉圆形之外的部分, 就是在片元处理的时候就直接丢弃, 只要那些片元不参与绘制, 当然也不参与模板测试, 对应的模板值肯定也只是0了, 这样, 模板缓存中, 圆形部分的模板值为3, 之外的部分为0. 我们继续绘制头像时, 圆形部分的模板值与头像相同, 可以绘制, 而圆形部分之外的部分与头像不同, 不能绘制, 这样就达到了我们的效果.

至于如何过滤掉圆形之外的片元, 因为那部分片元是透明的, 我们只需要使用透明度测试将其丢弃即可, 当然, 只需要简单的勾选Use Alpha Clip即可, 如图:

在片元着色器中对应的代码为:

#ifdef UNITY_UI_ALPHACLIP
clip (color.a - 0.001);
#endif

即透明度小于0.001的片元就丢弃.

顺便说一下, 如果不想显示遮罩的图片, 只需要在绘制遮罩的时候将颜色掩码Color Mask设置为0即可, 对应的是Mask组件的ShowMaskGraphic属性, 效果如下:

以上就是整个模拟过程, Unity官方的Mask组件的核心运作原理就是如此, 不同的是因为在实际场景中可能存在多个物体需要进行模板测试, 所以需要做很多额外的工作来避免互相影响.

相信使用过Mask的同学知道这个组件有一个最大的问题就是渲染出来的效果存在比较明显的锯齿现象, 我们将在下一篇文章中尝试另一个方案来实现遮罩, 从而优化锯齿问题. 希望对大家有所帮助.

Unity中使用模板测试模拟Mask组件效果相关推荐

  1. unity中实现城市夜晚汽车流水的效果

    这里着重说明unity中怎么用代码控制纹理的偏移和平铺:偏移的纹理可以实现很多流动的效果,如本例中的车流水线--: using System.Collections; using System.Col ...

  2. 【游戏开发实战】教你在Unity中实现模型消融化为灰烬飘散的效果(ShaderGraph | 消融 | 粒子系统 | 特效)

    文章目录 一.前言 二.ShaderGraph环境准备 三.模型准备:原神角色模型 四.实现思路 1.效果一的实现思路 2.效果二的实现思路 五.ShaderGraph具体实现 1.效果一 1.1.创 ...

  3. unity中areaLight的测试

    areaLight区域光,只有在烘焙时可以使用.模拟灯管的照射效果再合适不过.来两张烘焙后对比图,两次烘焙参数都是一样,一个是arealight,另一个是pointlight: 区域光: 点光: 最后 ...

  4. Unity零基础到入门 ☀️| Unity从青铜 到 王者!只差这篇让你学会Unity中最重要的部分——脚本组件✨

    Unity脚本组件

  5. Unity中使用RequireComponent,没有添加上组件

    using UnityEngine; using System.Collections;[RequireComponent(typeof(MeshFilter), typeof(MeshRendere ...

  6. 在unity中如何实现群体行为模拟步骤详解

    版权申明: 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/ ...

  7. unity中Animator的avatar是什么组件

    在组件的这个位置 是表示携带这个组件的模型对象身上是否有骨架

  8. Unity中RenderDoc的使用

    本文分享Unity中RenderDoc的使用 研究过渲染的同学想必对RenderDoc不陌生. RenderDoc是一个查看和分析渲染效果的工具, 可以查看每一帧的渲染信息, 比Unity自带的Fra ...

  9. UnityShader29:模板测试

    一.什么是模板测试 OpenGL基础30:模板测试 Unity官方文档:https://docs.unity3d.com/Manual/SL-Stencil.html 一个很经典的模板测试例子就是 U ...

最新文章

  1. NR 5G UE和5G网络功能之间的安全流程
  2. xmlns=http://schemas.xmlsoap.org/wsdl/,这是什么意思,我只知道:xmlns:xx=....,
  3. 数据中台全景架构及模块解析
  4. python面向对象还是过程_Python学习————面向对象和面向过程
  5. Windows Server 2008怎么查看远程桌面登录日志
  6. 如何 给给软件开发 添加 代理_如何与软件开发公司有效沟通
  7. java值传递和引用传递的题目_Java 值传递和引用传递
  8. 版本代码详解:Alpha,Beta,Rc,GA,RTM,OEM等简称都代码什么意义
  9. java做一个简单的银行账户演示程序_JAVA初学(七):银行账户演示程序
  10. 质性数据分析软件NVivo的编码比较查询
  11. 怎么还原计算机网络,怎么把网络协议还原为默认设置
  12. 基片集成波导原理_基片集成波导
  13. 腾讯安全2020年区块链成绩单出炉
  14. C/C++ 创建多级文件夹(mkdir)
  15. matlab tstart,ttbox25102012 一款利用matlab编写的射线追踪程序,易改易用。 238万源代码下载- www.pudn.com...
  16. NIST:生成安全密码密钥
  17. 用C#实现竖列转盘游戏
  18. 新三板挂牌和上市的区别在哪
  19. saas架构理解与设计
  20. MySQL常用函数大全(面试篇)

热门文章

  1. 虚拟服务器网络不通,VMware Workstation ping 不通的解决方法
  2. 苹果的名字测试软件,教你iOS12人脸识别测颜值捷径安装使用教程及iPhone XR修改AppleID姓名教程...
  3. 阿里云直播生成推流和播流地址类
  4. 技术经理成长复盘-激励
  5. Unity3d打地鼠
  6. java lzw_lzw在java中解压缩
  7. Bzoj4698: [Sdoi2008]Sandy的卡片
  8. 文献解读|迁徙蝗虫生理和转录水平的衰老特征
  9. matlab怎么求解多元非线性方程组,用matlab求解多元非线性方程组(多个方程组)问题...
  10. 安徽师大附中%你赛day5 T3 树上行走 解题报告