一日一Shader·切除【SS_30】

今天主要利用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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值