Vertex shader that creates a bounce effect in geometry.
At GDC 2013, Jonathan Lindquist from Epic Games did a talk about Fornite's procedural animations. These animations were based on vertex displacements using vertex shaders. The main goal of these animations was to make hitting and destroying things fun. The technique used to create the bounce effect is simple, elegant and the final result is very engaging.
The first thing needed is the impact position on the object. In this example a ray is casted from the camera to the scene and checks if the gameobject hit has an BounceReceiver
component.
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
BounceReceiver receiver = hit.transform.GetComponent<BounceReceiver>();
if (receiver)
{
receiver.Impact(hit.point, ray.direction);
}
}
Then, the BounceReceiver
sets the material properties that the shader is going to use.
- _TargetPosition. Position of the bounce in world space.
- _Direction. Direction of the bounce.
- _Radius. Radius of the bounce.
- _Amplitude. Amplitude of the bounce.
- _Value. Value from 0 to 1 used to animate, evaluated using an AnimationCurve.
- _Bounce. Boolean flag used to play and stop the animation.
material.SetVector("_TargetPosition", position);
material.SetVector("_Direction", direction);
material.SetFloat("_Radius", radius);
material.SetFloat("_Amplitude", amplitude);
material.SetFloat("_Value", curve.Evaluate(currentTime / totalTime));
material.SetInt("_Bounce", 1);
currentTime = 0;
isAnimating = true;
When the animation is playing the _Value
is updated every frame in the Update
method.
currentTime += Time.deltaTime;
material.SetFloat("_Value", curve.Evaluate(currentTime / totalTime));
In the shadergraph a distance value is calculated from the vertex position in object space to the TargetPosition
(transformed from world space to object space). This distance is divided by the Radius
, clamped (between 0 and 1) and the result is substracted from 1. Then this result is multiplied by the Direction
* Amplitude
* Value
(the offset in the normal direction at the given animation time). The next step is to add this value to the vertex position in object space and lastly the boolean flag Bounce
is checked to output the final result (or the vertex position not displaced) to the position input of the main node.
References.
The Inner Workings of Fornite's Shader-Based Procedural Animations