Creating a spotlight effect in Shadertoy

spotlight circle stone with ambient

This tutorial will show you how to create a animated spotlight effect in Shadertoy. You will learn how to correct the circle size with the aspect ratio. Then you will learn how to animate the circle using time and a sine wave. So the circle moves back-and-forth across the screen. To finish off the effect you will combine the spotlight circle with a texture, then apply ambient light to brighten up the background.

I recommend checking out the last tutorial before starting this one.

Step 1: Calculate UV

Calculate the UV coordinates. We will need these for creating the circle and getting the texture pixel color.

vec2 uv = fragCoord / iResolution.xy;

Step 2: Position

Create a position variable and set it to the current UV value. Then offset it so that we can create our circle from the centre of the screen.

vec2 pos = uv;
pos -= 0.5;

Step 3: Aspect Ratio

Calculate the aspect ratio and multiply it against the position variable. We do this to create a circle, otherwise we will have an ellipse.

vec2 aspect = iResolution.xy / min(iResolution.x, iResolution.y);
pos *= aspect;
spotlight circle with no aspect ratio correction
Spotlight circle with no aspect ratio correction

Step 4: Sine wave

Use a sine wave and time to animate the position variable. This will make it move across the screen from left to right and back again repeatedly.

pos.x -= sin(iTime) * 0.5;

Step 5: Create a circle

Use this function to create a circle. It takes a position and a radius.

float circle(vec2 pos, float radius)
{
    return length(pos) - radius;
}

Create a smooth circle using the circle distance and smoothstep. Invert the distance so that the circle is white at the center. The circle distance is called ‘spotlight’.

float spotlight = circle(pos, 0.36);
spotlight = 1.0 - smoothstep(0.0, 0.1, spotlight);
spotlight circle mask
Spotlight circle mask

Step 6: Ambient light

Apply ambient light to the circle distance value. This will brighten up the background area outside the circle a little.

spotlight += 0.1f;

Step 7: Output

Select a texture for ‘iChannel0’. Then get the current texture color and save it into the output fragment color.

fragColor = texture(iChannel0, uv);

Now multiply the fragment RGB with the spotlight value. This will create the spotlight effect.

fragColor.rgb *= spotlight;
spotlight circle stone wall without ambient
Without ambient
spotlight circle stone with ambient
Ambient

Full code

float circle(vec2 pos, float radius)
{
    return length(pos) - radius;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord / iResolution.xy;

    // Calculate position
    vec2 pos = uv;
    pos -= 0.5;
    
    // Aspect ratio
    vec2 aspect = iResolution.xy / min(iResolution.x, iResolution.y);
    pos *= aspect;
    
    // Animate using a sine wave
    pos.x -= sin(iTime) * 0.5;
    
    // Create a circle
    float spotlight = circle(pos, 0.36);
    spotlight = 1.0 - smoothstep(0.0, 0.1, spotlight);
    
    // Ambient light
    spotlight += 0.1f;
    
    // Output to screen
    fragColor = texture(iChannel0, uv);
    fragColor.rgb *= spotlight;
}

Conclusion

This tutorial has shown you how to create a aspect ratio corrected circle which moves back and forth across the screen. We used this circle to create a spotlight effect by multiplying it against the texture color. We also applied some ambient light to brighten up the background.

Here are some things you can experiment with:

  • You could change the size of the circle and the smoothness.
  • You could change the amount of ambient light.
  • You could make the spotlight flicker by animating the radius.

You can also see and play with the values on Shadertoy here.

Thank you for reading this tutorial, I hope you found it useful!

2 responses to “Creating a spotlight effect in Shadertoy”

Leave a comment