1.球衰减

首先,我们将处理球衰减,鼠标或手指点中网格的点是碰撞点,越往外它所受的影响越小。我们需要从CPU中获取“_ImpactPos”这个碰撞点,获取摄像机和碰撞点的矢量,我们将对我们网格的每个顶点执行相对于撞击点的球面衰减。

 

DeformableActor.shader
1
2
3
4
5
6
void vert(inout appdata v) {
    float3 dst = _ImpactPos - v.vertex.xyz;
    dst.x = dot(dst, dst) / _Radius;
    float attenuation = 1 / (1 + dst.x);
        // To Do
}

 

2.反弹效应

  在CPU里,我们用AnimationCurve手动调好一个正弦曲线,衰减随着时间的推移,以获得预期的效果(见图2.1)。

 

 

 

 图2.1.指数阻尼正弦波(也可以自己在代码里写阻尼公式)

 

public class DeformableActor : MonoBehaviour
{
    [SerializeField]
    private float maxScale = 3f;
 
    [SerializeField]
    private float duration = 1f;
 
    [SerializeField]
    private AnimationCurve curve;
 
    private Camera mainCamera;
 
    private Material dynamicMat;
 
    private bool bIsBouncing;
 
    private float timer;
 
    private Vector3 direction,
        dampingVector;
 
    // Use this for initialization
    private void Start()
    {
        mainCamera = Camera.main;
        dynamicMat = GetComponent<MeshRenderer>().material;
    }
 
    // Update is called once per frame
    private void Update()
    {
        if (bIsBouncing)
            BounceActor();
 
        if (!Input.GetMouseButton(0))
            return;
 
        DoRayCasting();
    }
 
    // ---------------------
    private void OnDestroy()
    {
        Destroy(dynamicMat);
    }
 
    // -------------------------------------------------------------
    private void BounceActor()
    {
        timer += Time.deltaTime / duration;
 
        if (timer <= 1f)
        {
            dampingVector = curve.Evaluate(timer)
                * maxScale * direction;
 
            dynamicMat.SetVector("_DampingVector", dampingVector);
        }
        else
        {
            bIsBouncing = false;
            dynamicMat.SetVector("_DampingVector", Vector3.zero);
        }
    }
 
    // ------------------------------------------------------------------
    private void DoRayCasting()
    {
        RaycastHit hit = new RaycastHit();
 
        if (Physics.Raycast(mainCamera
            .ScreenPointToRay(Input.mousePosition), out hit))
        {
            dynamicMat.SetVector("_ImpactPos",
                transform.InverseTransformPoint(hit.point));
 
            direction = (mainCamera.transform.position
                - hit.point).normalized;
            direction = transform.InverseTransformDirection(direction);
 
            bIsBouncing = true;
            timer = 0f;
        }
    }
}

 

3.关于网格顶点变形的shader

Shader "FI/DeformableActor" {
    Properties{
        _Radius("Radius", Float) = 1
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Normal("Normal", 2D) = "bump" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        Cull Off
 
        CGPROGRAM
 
        #pragma surface surf Standard fullforwardshadows vertex:vert addshadow //在surface shader中想要进行顶点偏移,要加上vertex:vert
        #pragma target 3.0
 
        #include "UnityCG.cginc"
 
        struct appdata {
            float4 vertex : POSITION;
            float4 tangent : TANGENT;
            float3 normal : NORMAL;
            float2 texcoord : TEXCOORD0;
        };
 
      
 
        sampler2D _MainTex;
        sampler2D _Normal;
 
        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
 
        float _Radius;
        float3 _DampingVector;
        float3 _ImpactPos;
 
        struct Input {
            float2 uv_MainTex;
        };
 
        void vert(inout appdata v) {
            float3 dst = _ImpactPos - v.vertex.xyz;
            dst.x = dot(dst, dst) / _Radius;
            float attenuation = 1 / (1 + dst.x); //离hit的点越远的顶点得到的attenuation的值越小,即顶点的晃动就会越小
            v.vertex.xyz += _DampingVector * attenuation; 
        }
 
        UNITY_INSTANCING_BUFFER_START(Props)
 
        UNITY_INSTANCING_BUFFER_END(Props)
 
        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_MainTex));
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

 

类似的例子(心脏的跳动):https://blog.csdn.net/u010133610/article/details/51863887

版权声明:本文为MoFishLi原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/MoFishLi/p/13305926.html