今天主要利用discard进行一些效果实现。
根据对象的世界坐标,进行一定的判断,让满足条件的图元显示,其他图元用discard隐藏掉。
可以时实现类似扫描、探照灯、透视、切割等效果。
Shader "MyShader/SS_30"{
Properties{
_MainTex("MainTexture",2D) = ""{}
_BlendTex("BlendTexture",2D) = ""{}
_CutAxis("Cut Axis", Vector) = (0,1,0,0)
_CutCenter("Cut Center", Vector) = (0,1,0,0)
_CutThreshold("Cut Threshold", Float) = 0.5
}
SubShader{
CGINCLUDE
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature MASK_SPHERE MASK_PLANE
float4 _CutAxis;
float4 _CutCenter;
float _CutThreshold;
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float4 worldPos : TEXCOORD1;
};
float cutPosition(float3 pos) {
#if MASK_PLANE
return dot(pos-_CutCenter,normalize(_CutAxis.xyz));
#elif MASK_SPHERE
return distance(pos,_CutCenter)-_CutThreshold;
#else
return 0.0;
#endif
}
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
return o;
}
ENDCG
Pass{
CGPROGRAM
sampler2D _MainTex;
fixed4 frag(v2f i) : SV_Target {
if (cutPosition(i.worldPos.xyz) > 0) discard;
return tex2D(_MainTex, i.uv);
}
ENDCG
}
Pass{
CGPROGRAM
sampler2D _BlendTex;
fixed4 frag(v2f i) : SV_Target {
if (cutPosition(i.worldPos.xyz) < 0) discard;
fixed4 col=tex2D(_BlendTex, i.uv);
return col;
}
ENDCG
}
}
}
专门写了一个控制脚本:
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class SS_30 : MonoBehaviour
{
public MaskType maskType = MaskType.Plane;
public float radius;
List<Material> mats = new List<Material>();
Renderer[] renderers;
private void OnEnable()
{
renderers = FindObjectsOfType<Renderer>();
CollectMaterials();
}
void Update()
{
for (int i = 0; i < mats.Count; i++)
{
SetMaterial(mats[i]);
}
if (Application.isPlaying)
{
if (maskType == MaskType.Plane)
{
transform.Rotate(Vector3.up, Time.deltaTime * 100);
}
else if (maskType == MaskType.Sphere)
{
radius = Mathf.PingPong(Time.realtimeSinceStartup, 1)+0.5f;
}
}
else
{
radius = transform.localScale.x;
}
}
void SetMaterial(Material _mat)
{
if (maskType == MaskType.Plane)
{
_mat.DisableKeyword("MASK_SPHERE");
_mat.EnableKeyword("MASK_PLANE");
_mat.SetVector("_CutAxis", transform.forward);
_mat.SetVector("_CutCenter", transform.position);
}
else if (maskType == MaskType.Sphere)
{
_mat.DisableKeyword("MASK_PLANE");
_mat.EnableKeyword("MASK_SPHERE");
_mat.SetVector("_CutCenter", transform.position);
_mat.SetFloat("_CutThreshold", radius);
}
else
{
_mat.DisableKeyword("MASK_PLANE");
_mat.DisableKeyword("MASK_SPHERE");
}
}
void CollectMaterials()
{
for (int i = 0; i < renderers.Length; i++)
{
for (int j = 0; j < renderers[i].sharedMaterials.Length; j++)
{
if (!mats.Contains(renderers[i].sharedMaterials[j]))
mats.Add(renderers[i].sharedMaterials[j]);
}
}
}
private void OnDrawGizmos()
{
if (maskType == MaskType.Plane)
{
Gizmos.color = Color.red;
Gizmos.DrawRay(transform.position, transform.forward);
}
else if (maskType == MaskType.Sphere)
{
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(transform.position, radius);
}
}
public enum MaskType
{
None,
Plane,
Sphere,
}
}
返回目录:https://blog.csdn.net/yzy1987523/article/details/107561997