Film Vignette Effect in Unity

Sample of a flickering (film) vignette effect for Unity.

The complete code and assets for this example can be found at https://github.com/cmroche/UnityVignetteShader

The process to doing this is fairly simple, first we create a texture and import it to unity as an Alpha 8 type texture. The alpha channel will be opaque on the outer edges and transparent on the inner area. Use this material on a quad in your camera’s view frustum and select the vignette shader.

The idea behind producing the flicker is fairly straight forward. Select a random value in a range, apply a slight bias, and blend from the current value to the next value. Once we reach our target choose a new random value and repeat the process. To make the shader look like the vignette is moving in and out of the edges of the frame we want to select intensity values that completely saturate part of the texture’s alpha.

There are a few tuneable variables we’ll use for polishing the effect:

public float IntensityBias = 0.6f;
public float MinimumIntensity = 1.0f;
public float MaximumIntensity = 1.4f;
public float BlendSpeed = 1.0f;

If you want a linear range of intensity values, set your IntensityBias to 0.5, if you would like to bias towards a more opaque frame move your IntensityBias upwards, values between 0.6 and 0.8 seem to work well.

A simple coroutine to select intensity values and blend continuously:

IEnumerator DoBlending()
{
   while (true)
   {
      float rate = 1f / BlendSpeed * BlendUpdateRate;

      if (currentValue == targetValue)
      {
         targetValue = Random.Range(MinimumIntensity, MaximumIntensity);
      }
      else
      {
         float dir = Mathf.Sign(targetValue - currentValue);
         currentValue += dir * rate;

         if (dir != Mathf.Sign(targetValue - currentValue))
         {
            currentValue = targetValue;
         }

         float intensity = Bias(IntensityBias, currentValue);
         Shader.SetGlobalFloat("_Intensity", intensity);
         //UnityEngine.Debug.Log("Current intensity " + intensity.ToString() + " target intensity " + targetValue.ToString());
      }

      yield return new WaitForSeconds(BlendUpdateRate);
   }
}

The vignette shader to apply the effect, the 0.8f here is the saturation point of the alpha channel this way we can still see through the frame at the highest intensity. You can obviously change this to your needs.

half4 frag(v2f i) : COLOR
{
   half4 c = i.color;
   c.a = clamp(tex2D(_MainTex, i.uv).a * _Intensity, 0f, 0.8f);
   return c; 
}

All the code and assets in this example are public domain. You may freely reuse or modify in any way and for any purpose (even commercial) without the need to attribute or notify me. Of course if you would like to credit me this simple work, I certainly won’t complain.

2 thoughts on “Film Vignette Effect in Unity

    1. admin Post author

      A bit, yes.. any post effects (and transparent geometry) causes a performance hit on mobile devices due to the way their tiled renderers work. But it is manageable, I used this effect on Globulous which shipped for iPhone 4 and iPad 1 and was still able to hit 27fps. The vignette wasn’t the major performance issue either. You will simply need to balance it with any other effects or transparent draws that you have to keep performance in line. The exception to this are the Tegra GPUs which are still immediate mode renderers and perform much better at this type of problem specifically.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *