Unity3D Shader实现动态屏幕遮罩

屏幕可视范围跟随目标物体移动,可修改可视范围大小,边缘渐变大小、以及遮罩颜色,支持最高物体数量可在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);

}

}

以上是 Unity3D Shader实现动态屏幕遮罩 的全部内容, 来源链接: utcz.com/z/336417.html

回到顶部