首页 > 编程 > C# > 正文

Unity3D Shader实现动态屏幕遮罩

2020-01-24 00:08:19
字体:
来源:转载
供稿:网友

屏幕可视范围跟随目标物体移动,可修改可视范围大小,边缘渐变大小、以及遮罩颜色,支持最高物体数量可在Shader中修改,当前版本支持最多9个物体。

效果图如下:

控制面板如下:

Shader代码如下:

Shader "Peter/DarkEffect"{  Properties  {    _MainTex ("Texture", 2D) = "white" {}  }  SubShader  {    // No culling or depth    Cull Off ZWrite Off ZTest Always    Pass    {      CGPROGRAM      #pragma vertex vert      #pragma fragment frag      #include "UnityCG.cginc"      //追踪物体最多个数      #define ItemSize 9      struct appdata      {        float4 vertex : POSITION;        float2 uv : TEXCOORD0;      };      struct v2f      {        float2 uv : TEXCOORD0;        float4 vertex : SV_POSITION;      };      sampler2D _MainTex;      fixed4 _DarkColor;      float _SmoothLength;      fixed _ItemCnt;      float4 _Item[ItemSize];      v2f vert (appdata v)      {        v2f o;        o.vertex = UnityObjectToClipPos(v.vertex);        o.uv = v.uv;        return o;      }      fixed CalcAlpha(float4 vt, float4 pt)      {        if(pt.z < 0)        {          return 1;        }        float distPow2 = pow(vt.x - pt.x, 2) + pow(vt.y - pt.y, 2);        float dist = (distPow2 > 0) ? sqrt(distPow2) : 0;        float smoothLength = _SmoothLength;        if(smoothLength < 0)        {          smoothLength = 0;        }        float maxValue = pt.z;        float minValue = pt.z - smoothLength;        if(minValue < 0)        {          minValue = 0;          smoothLength = pt.z;        }        if(dist <= minValue)        {          return 0;        }        else if (dist > maxValue)        {          return 1;        }        fixed retVal = (dist - minValue) / smoothLength;        return retVal;      }      fixed4 frag (v2f i) : SV_Target      {        fixed alphaVal = 1;        fixed tmpVal = 1;        for(fixed index = 0; index < _ItemCnt; ++index)        {          tmpVal = CalcAlpha(i.vertex, _Item[index]);          if(tmpVal < alphaVal)          {            alphaVal = tmpVal;          }        }        alphaVal *= _DarkColor.a;        return tex2D(_MainTex, i.uv) * ( 1 - alphaVal) + _DarkColor * alphaVal;      }      ENDCG    }  }}

C#调用代码如下:

using System.Collections;using System.Collections.Generic;using UnityEngine;[ExecuteInEditMode][RequireComponent(typeof(Camera))]public class DarkEffect : MonoBehaviour{  [System.Serializable]  public class Item  {    [SerializeField]    public Transform target;    [SerializeField]    public int radius;    public Vector3 GetScreenPosition(Camera cam)    {      return cam.WorldToScreenPoint(target.position);    }  }  //渐变像素数量  public int _smoothLength = 20;  //遮罩混合颜色  public Color _darkColor = Color.black;  //目标物体  public List<Item> _items = new List<Item>();  protected Material _mainMaterial;  protected Camera _mainCamera;  Vector4[] _itemDatas;  Item _tmpItem;  Vector4 _tmpVt;  Vector3 _tmpPos;  int _tmpScreenHeight;  private void OnEnable()  {    _mainMaterial = new Material(Shader.Find("Peter/DarkEffect"));    _mainCamera = GetComponent<Camera>();  }  private void OnRenderImage(RenderTexture source, RenderTexture destination)  {    if (_itemDatas == null || _itemDatas.Length != _items.Count)    {      _itemDatas = new Vector4[_items.Count];    }    _tmpScreenHeight = Screen.height;    for (int i = 0; i < _items.Count; i++)    {      _tmpItem = _items[i];      _tmpPos = _tmpItem.GetScreenPosition(_mainCamera);      _tmpVt.x = _tmpPos.x;      _tmpVt.y = _tmpScreenHeight - _tmpPos.y;      _tmpVt.z = _tmpItem.radius;      _tmpVt.w = 0;      _itemDatas[i] = _tmpVt;    }    _mainMaterial.SetInt("_SmoothLength", _smoothLength);    _mainMaterial.SetColor("_DarkColor", _darkColor);    _mainMaterial.SetInt("_ItemCnt", _itemDatas.Length);    _mainMaterial.SetVectorArray("_Item", _itemDatas);    Graphics.Blit(source, destination, _mainMaterial);  }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表