Distortion effect

This effect consists in distorting the rendered image, which can be used to model phenomena like heat distortion, e.g. around fire and explosions.

It is pretty simple to implement. We first render the particles to a render target, which we’ll use as a mask for the effect since we don’t want to distort the whole image. Then we draw the full scene in another render target, and lastly we render a post-processing pass where we do the distortion effect and compose the final image that is presented to the screen. Three.js’ EffectComposer API is used to do this.

Distortion effect image

The fragment shader in the post-processing pass takes three textures as input: one with the scene without the distortion effect (screenTex), one with the mask, and a noise texture, which is used to offset the uv values.

Mask texture

Here is the code:

uniform float scale;

uniform sampler2D maskTex;
uniform sampler2D noiseTex;
uniform sampler2D screenTex;

varying vec2 vUv;
varying vec2 vNoiseUv;

void main()
    vec3 mask = texture2D(maskTex, vUv).rgb;
    float distortionStrength = min(1.0, dot(mask, mask));

    vec2 noise = texture2D(noiseTex, vNoiseUv).rg;
    noise = noise * scale * distortionStrength;

    vec3 distorted = texture2D(screenTex, vUv + noise).rgb;
    gl_FragColor = vec4(distorted, 1.0);

The distortion is achieved by offsetting the uv values with the noise values, which depend on the mask, so the final image is not distorted where the mask texture is black.

You can check-out the code here.