Have you ever wondered why rendered images feel too straight or stiff compared to real pictures? Well, there might be two reasons for this.
Firstly, real-world images and videos have some distortion due to curved camera lenses. This results in straight lines along the edges of a photograph curving inwards or outwards. This effect is known as Lens Distortion.
Another common effect is Chromatic Aberration. In some older photographs, we can see that the light gets split into different colours, resulting in a rainbow-like effect at the corners.
These effects are common in many real-world cameras, binoculars, scopes, mirrors, etc. So today, we will learn how to create these effects in Unity using shaders.
In this part of this series, we will only be looking at Lens Distortion.
Lens Distortion Types
Lens distortion is usually classified into two types: Barrel Distortion and Pincushion Distortion. In barrel distortion, corners converse towards the centre of the image, while in pincushion distortion, they diverge away.
Today, we will learn how to create both types of distortion.
Creating Lens Distortion
Let's start by creating a shader and adding material for it. This shader can be applied to an image to distort it or the camera itself to distort everything the camera renders.
Let us first start by creating an unlit shader. We will be using an unlit shader because we don't want it to be affected by lighting.
Step 1: Remapping UV
In the shader we created, we have a
frag function. This will be called once for every pixel in each frame. Each
i of type
v2f will be passed to it as a parameter. The
i will then interact with the
uv position of the current pixel.
uv variable is a
float2 variable that has values in the range of
(0,1). We will now convert
uv_centered, so that the domain for the values increase to
(-1,1). We set
(0,0) as the centre point and
1 as the corner of
uv_centered. This change will give us the direction of distortion.
uv, we need to get
distortionMagnitude. This is the magnitude of distortion applied at any
uv position. On a real picture, we can notice that there is no distortion at the centre of the image, and the distortion gradually increases as we get closer to a corner.
To achieve this effect, we need to multiply
y components of
uv_centered. The closer we get to the centre, the lower our multiplication number. This makes it so that the centre has a 0 and the corners have a 1 multiplication factor.
Also, we use abstract values as we only need the magnitude, and direction is not important.
Step 2: Smoothing Distortion Map
We can't use this map yet because the change in magnitude is linear. Using it will create a distortion effect with a straight line broken at the centre.
To make it smooth, lets pass
distortedMagnitude through the exponential function
x = smoothed value. Let's call it
y = exponent of function. This determines the tightness of the curve. Let us declare it as
_LensDistortionStrength. We will expose this as a 'property' to modify it from the editor when desired.
We could also use other functions such as
) . Using these will yield different types of curvature.
Step 3: Distorting Original UV
Now, since we have the distortion magnitude, we just need to distort the original
i.uv with this magnitude. This distortion vector is obtained by multiplying
To get more control over distortion strength, let's multiply it by
_LensDistortionStrength which we will expose as a 'property'. Setting
LensDistortionStrength to a positive value will create a barrel distortion, and setting it to a negative value will make a pincushion distortion.
uvDistorted is out of bound, i.e., when it is not in between 0 and 1, some artefacts can be created. So to avoid those, let's add some colour to those spaces. The colour added will be exposed as a 'property' so that it can be modified from the editor.
Step 4: Using the Shader
Our shader is now ready for use. We simply create a material, link this shader to it, and use this material per our needs.
To use it in an image, we can simply drag and drop this material to the material property of the image. The same can also be done to the camera to show the effect everywhere while playing the game. Examples of this effect in-game are shown below.
We will use this material with a camera and create the Chromatic Aberration effect in part 2. Stay tuned! Edit: Part 2 is here!