Как отобразить несколько шейдеров сканера в Unity
Есть шейдер топографического сканера от https://youtu.be/OKoNp2RqE9A. Вот сам код шейдера:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Hidden/ScannerEffect"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_DetailTex("Texture", 2D) = "white" {}
_ScanDistance("Scan Distance", float) = 0
_ScanWidth("Scan Width", float) = 10
_LeadSharp("Leading Edge Sharpness", float) = 10
_LeadColor("Leading Edge Color", Color) = (1, 1, 1, 0)
_MidColor("Mid Color", Color) = (1, 1, 1, 0)
_TrailColor("Trail Color", Color) = (1, 1, 1, 0)
_HBarColor("Horizontal Bar Color", Color) = (0.5, 0.5, 0.5, 0)
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct VertIn
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float4 ray : TEXCOORD1;
};
struct VertOut
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uv_depth : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
};
float4 _MainTex_TexelSize;
float4 _CameraWS;
VertOut vert(VertIn v)
{
VertOut o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv.xy;
o.uv_depth = v.uv.xy;
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
o.uv.y = 1 - o.uv.y;
#endif
o.interpolatedRay = v.ray;
return o;
}
sampler2D _MainTex;
sampler2D _DetailTex;
sampler2D_float _CameraDepthTexture;
float4 _WorldSpaceScannerPos;
float _ScanDistance;
float _ScanWidth;
float _LeadSharp;
float4 _LeadColor;
float4 _MidColor;
float4 _TrailColor;
float4 _HBarColor;
float4 horizBars(float2 p)
{
return 1 - saturate(round(abs(frac(p.y * 100) * 2)));
}
float4 horizTex(float2 p)
{
return tex2D(_DetailTex, float2(p.x * 30, p.y * 40));
}
half4 frag (VertOut i) : SV_Target
{
half4 col = tex2D(_MainTex, i.uv);
float rawDepth = DecodeFloatRG(tex2D(_CameraDepthTexture, i.uv_depth));
float linearDepth = Linear01Depth(rawDepth);
float4 wsDir = linearDepth * i.interpolatedRay;
float3 wsPos = _WorldSpaceCameraPos + wsDir;
half4 scannerCol = half4(0, 0, 0, 0);
float dist = distance(wsPos, _WorldSpaceScannerPos);
if (dist < _ScanDistance && dist > _ScanDistance - _ScanWidth && linearDepth < 1)
{
float diff = 1 - (_ScanDistance - dist) / (_ScanWidth);
half4 edge = lerp(_MidColor, _LeadColor, pow(diff, _LeadSharp));
scannerCol = lerp(_TrailColor, edge, diff) + horizBars(i.uv) * _HBarColor;
scannerCol *= diff;
}
return col + scannerCol;
}
ENDCG
}
}
}
А так же скрипт который вызывает сам эффект:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class ScannerEffectDemo : MonoBehaviour
{
public Transform ScannerOrigin;
public Material EffectMaterial;
public float ScanDistance;
public float ScanDecreaseTime;
private Camera _camera;
// Demo Code
[HideInInspector]
public bool _scanning;
public bool _canScanningObjectsCollide = true;
Scannable[] _scannables;
void Start()
{
_scannables = FindObjectsOfType<Scannable>();
}
void Update()
{
if (_scanning)
{
ScanDistance += Time.deltaTime * ScanDecreaseTime;
if (_canScanningObjectsCollide)
{
foreach (Scannable s in _scannables)
{
if (Mathf.RoundToInt(Vector3.Distance(ScannerOrigin.position, s.transform.position)) == Mathf.RoundToInt(ScanDistance))
s.Ping();
}
}
}
if (Input.GetKeyDown(KeyCode.C))
{
_canScanningObjectsCollide = true;
_scanning = true;
ScanDistance = 0;
}
if (Input.GetMouseButtonDown(0))
{
_canScanningObjectsCollide = true;
_scanning = true;
ScanDistance = 0;
}
}
// End Demo Code
void OnEnable()
{
_camera = GetComponent<Camera>();
_camera.depthTextureMode = DepthTextureMode.Depth;
}
[ImageEffectOpaque]
void OnRenderImage(RenderTexture src, RenderTexture dst)
{
EffectMaterial.SetVector("_WorldSpaceScannerPos", ScannerOrigin.position);
EffectMaterial.SetFloat("_ScanDistance", ScanDistance);
RaycastCornerBlit(src, dst, EffectMaterial);
}
void RaycastCornerBlit(RenderTexture source, RenderTexture dest, Material mat)
{
// Compute Frustum Corners
float camFar = _camera.farClipPlane;
float camFov = _camera.fieldOfView;
float camAspect = _camera.aspect;
float fovWHalf = camFov * 0.5f;
Vector3 toRight = _camera.transform.right * Mathf.Tan(fovWHalf * Mathf.Deg2Rad) * camAspect;
Vector3 toTop = _camera.transform.up * Mathf.Tan(fovWHalf * Mathf.Deg2Rad);
Vector3 topLeft = (_camera.transform.forward - toRight + toTop);
float camScale = topLeft.magnitude * camFar;
topLeft.Normalize();
topLeft *= camScale;
Vector3 topRight = (_camera.transform.forward + toRight + toTop);
topRight.Normalize();
topRight *= camScale;
Vector3 bottomRight = (_camera.transform.forward + toRight - toTop);
bottomRight.Normalize();
bottomRight *= camScale;
Vector3 bottomLeft = (_camera.transform.forward - toRight - toTop);
bottomLeft.Normalize();
bottomLeft *= camScale;
// Custom Blit, encoding Frustum Corners as additional Texture Coordinates
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();
}
}
При попытке вызвать скрипт два раза, эффект просто начинается заного, а не создаётся новый. Я очень далёк от шейдеров, и прошу помочь мне. Как сделать что бы сканер не начинался заного, а создавался новый эффект (Что бы скажем было отображено сразу 2 таких эффекта в разных точках).