|
Unity
官方2DMask
在场景创建个UI-Panel,再创建个Image子物体
给Panel-Add Component添加Mask
则Image在Panel范围内的显示,其余不显示
Show Mask Graphic显示遮罩物体
试了下2D有效3D无效 屏幕遮罩效果
参考https://zhuanlan.zhihu.com/p/138568019
后处理效果,原理是把源像素和遮罩图形像素相乘
在Camera的OnRenderImage方法里进行处理
shader,MaskEffect
Properties
{
_MainTex("Texture", 2D) = "white" { }
}
Cull Off ZWrite Off ZTest Always
Tags { "Queue" = "Transparent" }
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 srcPos : TEXCOORD1;
};
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.srcPos = ComputeScreenPos(o.vertex);
return o;
}
sampler2D _MainTex;
float2 _Pos;
float _Size;
float _EdgeBlurLength;
// 创建圆
fixed3 createCircle(float2 pos, float radius, float2 uv)
{
//当前像素到中心点的距离
float dis = distance(pos, uv);
// smoothstep 平滑过渡
float col = smoothstep(radius + _EdgeBlurLength, radius, dis);
return fixed3(col, col, col);
}
fixed4 frag(v2f i) : SV_Target
{
// 根据屏幕比例缩放
float2 scale = float2(_ScreenParams.x / _ScreenParams.y, 1);
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 mask = createCircle(_Pos * scale, _Size, i.uv * scale);
return col * fixed4(mask, 1.0);
} C#,Mask
public class Mask : PostEffectsBase
这个PostEffectsBase的源码网上一搜很多人都在用,没法判断最早的作者是谁
using UnityEngine;
/// <summary>
/// 屏幕后处理效果基类
/// </summary>
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class PostEffectsBase : MonoBehaviour
{
private Camera mainCamera;
public Camera MainCamera { get { return mainCamera = mainCamera == null ? GetComponent<Camera>() : mainCamera; } }
public Shader targetShader;
private Material targetMaterial = null;
public Material TargetMaterial { get { return CheckShaderAndCreateMaterial(targetShader,ref targetMaterial); } }
/// <summary>
/// 检测资源,如果不支持,关闭脚本活动
/// </summary>
protected void Start()
{
if (CheckSupport() == false)
enabled = false;
}
/// <summary>
/// 检测平台是否支持图片渲染
/// </summary>
/// <returns></returns>
protected bool CheckSupport()
{
if (SystemInfo.supportsImageEffects == false)
{
Debug.LogWarning(&#34;This platform does not support image effects or render textures.&#34;);
return false;
}
return true;
}
/// <summary>
/// 检测需要渲染的Shader可用性,然后返回使用了该shader的material
/// </summary>
/// <param name=&#34;shader&#34;>指定shader</param>
/// <param name=&#34;material&#34;>创建的材质</param>
/// <returns>得到指定shader的材质</returns>
protected Material CheckShaderAndCreateMaterial(Shader shader, ref Material material)
{
if (shader == null || !shader.isSupported)
return null;
if (material && material.shader == shader)
return material;
material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
return material;
}
} C#
// shader
public Shader myShader;
//材质
private Material mat = null;
public Material material
{
get
{
// 检查着色器并创建材质
mat = CheckShaderAndCreateMaterial(myShader, ref mat);
return mat;
}
}
// 遮罩大小
[Range(0.01f, 10f), Tooltip(&#34;遮罩大小&#34;)]
public float size = 5.0f;
// 边缘模糊程度
[Range(0.0001f, 0.1f), Tooltip(&#34;边缘模糊程度&#34;)]
public float edgeBlurLength = 0.05f;
// 遮罩中心位置
private Vector2 pos = new Vector4(0.5f, 0.5f);
void Start()
{
//找到对应的Shader文件,可以注释掉直接拖动
myShader = Shader.Find(&#34;lcl/screenEffect/MaskEffect&#34;);
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (material)
{
// 把鼠标坐标传递给shader
material.SetVector(&#34;_Pos&#34;, pos);
// 遮罩大小
material.SetFloat(&#34;_Size&#34;, size);
// 模糊程度
material.SetFloat(&#34;_EdgeBlurLength&#34;, edgeBlurLength);
// 渲染
Graphics.Blit(source, destination, material);
}
else
{
Graphics.Blit(source, destination);
}
} 3D Mask
参考魔镜https://zhuanlan.zhihu.com/p/573367729
小记录:2盏灯Frame Debugger里会渲染2次,而且会造成无法合批batched
创建一个Plane以及几个Cube。
创建Plane的ASE-Surface以及Material,Cube同理
镜子Shader-Plane
Stencil Buffer=true
设置Reference=1,Comparison=Always,Pass Front=Replace
隐藏Plane,取消Blend Mode的Color Mask的RGBA
拉近后,镜子又显示出来了,解决方式:
调整渲染顺序:RenderQueue改成1999
关闭深度写入:Depth-ZWrite Mode=Off 场景shader实现mask遮罩效果
Stencil Buffer=true
设置Reference=1,Comparison=Equal
只能看到镜子里的物体,镜子外的看不到 原理:
输出合并阶段的模板测试Stencil Test->深度测试Depth Test
模板缓冲区Stencil buffer[0,255],01的集合矩阵
开启Stencil Buffer后,设置模板值Reference及规则
通过模板测试后可渲染到屏幕上(反之则无),且更新到模板缓冲区。 Plane
开启Stencil Buffer没效果
设置Reference=1,Pass Front=Replace,则他前面的物体会被隐藏,原理是这个1替换掉了其他的0
设置ZWrite Mode=Off后Plane变透明
取消Blend Mode的Color Mask的RGBA后Plane消失 Cube
开启Stencil Buffer没效果
设置Reference=1,Comparison=Greater后Plane前后的被隐藏,其他正常显示
设置Reference=1,Comparison=Equal后Plane前后的被显示,其他被隐藏 Render Queue值2500后为半透明,前为不透明,值小先渲染
Frame Debugger
UpdateDepthTexture画深度图
Drawing绘制
Camera.ImageEffetc后处理
魔镜的做法是用天空盒罩住场景,设置总是通过模板测试,来覆盖魔镜背后的现实物体 |
|