Vertex Shader Bounce Effect by adcimon - 2

Shaders & Effects

Vertex shader that creates a bounce effect in geometry.

Unity 2019.2.2f1Unknown LicenseUpdated 132 days agoCreated on March 19th, 2019
Go to source

Vertex Shader: Bounce Effect

Vertex shader that creates a bounce effect in geometry.


Art from the Adventure Sample Game.

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 ImpactReceiver component.

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if( Physics.Raycast(ray, out hit) )
{
  ImpactReceiver receiver = hit.transform.GetComponent<ImpactReceiver>();
  if( receiver )
  {
    receiver.Impact(hit.point, ray.direction);
  }
}

Then, the ImpactReceiver sets the material properties that the shader is going to use.

  • _ImpactPosition. Position of the impact in world space.
  • _ImpactDirection. Direction of the impact.
  • _DamageRadius. Radius of the impact.
  • _BounceAmplitude. Amplitude of the bounce effect.
  • _AnimationValue. Value from 0 to 1 used to animate, evaluated using an AnimationCurve.
  • _Bounce. Boolean flag used to play and stop the animation.
material.SetVector("_ImpactPosition", position);
material.SetVector("_ImpactDirection", direction);
material.SetFloat("_DamageRadius", damageRadius);
material.SetFloat("_BounceAmplitude", bounceAmplitude);
material.SetFloat("_AnimationValue", curve.Evaluate(currentTime / totalTime));
material.SetInt("_Bounce", 1);
currentTime = 0;
isAnimating = true;

When the animation is playing the _AnimationValue is updated every frame in the Update method.

currentTime += Time.deltaTime;
material.SetFloat("_AnimationValue", curve.Evaluate(currentTime / totalTime));

In the shadergraph a distance value is calculated from the vertex position in object space to the ImpactPosition (transformed from world space to object space). This distance is divided by the ImpactRadius, clamped (between 0 and 1) and the result is substracted from 1. Then this result is multiplied by the ImpactDirection * BounceAmplitude * AnimationValue (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

Show all projects by adcimon