使用后处理方式制作
cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GlobalScanEffect : MonoBehaviour
{
public float startScanRange = 0;
public float maxScanRange = 20;
public float scanWidth = 3;
public float scanSpeed = 1;
public Color headColor;
public Color trailColor;
private bool isInScan = false;
private Vector3 centerPos;
private float scanRadius;
private IEnumerator scanHandler = null;
public Material mat;
void OnEnable()
{
scanRadius = startScanRange;
Camera.main.depthTextureMode = DepthTextureMode.Depth;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
centerPos = hit.point;
scanRadius = 0;
if (scanRadius <= startScanRange)
{
Scan();
}
// else
// {
// ScanBack();
// }
}
}
}
protected void OnRenderImage(RenderTexture source, RenderTexture destination)
{
// if (isInScan)
if (mat != null && isInScan)
{
mat.SetVector("_ScanCenterPos", centerPos);
mat.SetFloat("_ScanRadius", scanRadius);
mat.SetFloat("_ScanWidth", scanWidth);
mat.SetColor("_HeadColor", headColor);
mat.SetColor("_TrailColor", trailColor);
RaycastCornerBlit(source, destination, mat);
}
else
{
Graphics.Blit(source, destination);
}
}
void RaycastCornerBlit(RenderTexture source, RenderTexture dest, Material mat)
{
float CameraFar = Camera.main.farClipPlane;
float CameraFov = Camera.main.fieldOfView;
float CameraAspect = Camera.main.aspect;
float fovWHalf = CameraFov * 0.5f;
Vector3 toRight = Camera.main.transform.right * Mathf.Tan(fovWHalf * Mathf.Deg2Rad) * CameraAspect;
Vector3 toTop = Camera.main.transform.up * Mathf.Tan(fovWHalf * Mathf.Deg2Rad);
Vector3 topLeft = (Camera.main.transform.forward - toRight + toTop);
float CameraScale = topLeft.magnitude * CameraFar;
topLeft.Normalize();
topLeft *= CameraScale;
Vector3 topRight = (Camera.main.transform.forward + toRight + toTop);
topRight.Normalize();
topRight *= CameraScale;
Vector3 bottomRight = (Camera.main.transform.forward + toRight - toTop);
bottomRight.Normalize();
bottomRight *= CameraScale;
Vector3 bottomLeft = (Camera.main.transform.forward - toRight - toTop);
bottomLeft.Normalize();
bottomLeft *= CameraScale;
RenderTexture.active = dest;
mat.SetTexture("_MainTex", source);
GL.PushMatrix();
GL.LoadOrtho();
mat.SetPass(0);
GL.Begin(GL.QUADS);
GL.MultiTexCoord2(0, 0.0f, 0.0f);
GL.MultiTexCoord(1, bottomLeft);
GL.Vertex3(0.0f, 0.0f, 0.0f);
GL.MultiTexCoord2(0, 1.0f, 0.0f);
GL.MultiTexCoord(1, bottomRight);
GL.Vertex3(1.0f, 0.0f, 0.0f);
GL.MultiTexCoord2(0, 1.0f, 1.0f);
GL.MultiTexCoord(1, topRight);
GL.Vertex3(1.0f, 1.0f, 0.0f);
GL.MultiTexCoord2(0, 0.0f, 1.0f);
GL.MultiTexCoord(1, topLeft);
GL.Vertex3(0.0f, 1.0f, 0.0f);
GL.End();
GL.PopMatrix();
}
void CheckAndBlock()
{
if (scanHandler != null)
{
StopCoroutine(scanHandler);
}
}
void Scan()
{
CheckAndBlock();
scanHandler = ScanCoroutine();
StartCoroutine(scanHandler);
}
void ScanBack()
{
CheckAndBlock();
scanHandler = ScanBackCoroutine();
StartCoroutine(scanHandler);
}
private IEnumerator ScanCoroutine()
{
isInScan = true;
while (scanRadius < maxScanRange)
{
scanRadius += scanSpeed;
yield return new WaitForSecondsRealtime(.01f);
}
scanRadius = maxScanRange;
isInScan = false;
}
private IEnumerator ScanBackCoroutine()
{
isInScan = true;
while (scanRadius > startScanRange)
{
scanRadius -= scanSpeed;
yield return new WaitForSecondsRealtime(.01f);
}
scanRadius = startScanRange;
isInScan = false;
}
}
shader
cs
Shader "LSQ/Screen Effect/GlobalScanEffect"
{
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"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 ray : TEXCOORD1;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float4 ray : TEXCOORD2;
};
sampler2D _MainTex;
sampler2D _CameraDepthTexture;
float3 _ScanCenterPos;
float _ScanRadius;
float _ScanWidth;
float4 _HeadColor;
float4 _TrailColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.ray = v.ray;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
//Get Pixel World Pos
float depth = Linear01Depth(DecodeFloatRG(tex2D(_CameraDepthTexture, i.uv)));
float4 toCameraVector = depth * i.ray;
float3 worldPos = _WorldSpaceCameraPos + toCameraVector;
//Get Scan Ring
float outerRing = _ScanRadius + _ScanWidth * 0.5;
float innerRing = _ScanRadius - _ScanWidth * 0.5;
float distanceToCenter = distance(_ScanCenterPos, worldPos);
float value = smoothstep(innerRing, outerRing, distanceToCenter);
//Get Color
fixed4 ringColor;
if(value >= 1 || value <= 0)
{
value = 0;
ringColor = float4(1,1,1,1);
}
else
{
ringColor = lerp(_TrailColor, _HeadColor, value);
}
return col * ringColor;
}
ENDCG
}
}
}