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