Learn How To Create Realistic Lightning Effects With Bezier Curves and Noise in JavaScript


Ever wanted to create jaw-dropping lightning effects with JavaScript? You are in the right place! In this tutorial, we are going to explore how to use Bezier curves, noise functions, and dynamic branching to bring realistic lightning to life on the HTML5 Canvas. Let’s dive in!

Prerequisites

Before we get started, make sure you have a basic understanding of HTML, CSS, and JavaScript.

  • Basic Understanding of HTML, CSS, and JavaScript: Familiarity with the fundamental concepts of HTML for structuring web pages, CSS for styling, and JavaScript for adding interactivity is essential. This tutorial assumes a basic knowledge of these languages.
  • Web Browser: Use a modern web browser like Google Chrome, Mozilla Firefox, or Microsoft Edge.

For the purpose of this tutorial, you can download the source files for the demo to help you follow along:

Note: As you test the source files, ensure that you load them within a suitable environment such that all the files are loaded. For offline use, we recommend that you use Live Server and vscode to load the files. Simply open the files in Vscode and run “index.html” using Live Server.

Demo

Here is what we are going to create.







Understanding the Basics

To achieve the lightning effect, we use three main components; vector points and math, bezier curves and a noise generator. In summary, our code is designed to dynamically generate and animate lightning using the following elements:

  • Vectors helps to deal with necessary mathematics.
  • Bezier curves to shape the lightning.
  • A noise generator for realistic jagged edges.

Setting Up the Project

Let's start by setting up the basic HTML structure for our project. Create an HTML called "index.html", with a basic HTML web format, and add a canvas element.

Creating the Canvas Element

The HTML structure consists of a <canvas> element, where the animation is rendered, and a set of range sliders that allow users to control parameters like roughness, scale, detail, and lightning branch properties.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
</head>

<body>
    <!-- Canvas element to render the effect -->
    <canvas id="canvas" width="500px" height="500px" style="background: black;"></canvas>
    
    <!-- UI controls for adjusting noise and lightning settings -->
    <span style="display:flex;flex-direction: row;gap:20px;font-family:sans-serif;">
        <div>
            <label for="roughness" style="font-weight: bold;">Noise:</label><br>
            <label for="roughness">Roughness:</label>
            <input type="range" id="roughness" min="0.1" max="1" step="0.1" value="1">
            <br>
            <label for="scale">Scale:</label>
            <input type="range" id="scale" min="0" max="5" step="0.1" value="3">
            <br>
            <label for="detail">Detail:</label>
            <input type="range" id="detail" min="0" max="10" value="10">
        </div>
        <div>
            <label for="roughness" style="font-weight: bold;">Lightning:</label><br>
            <label for="branches">Max Branches:</label>
            <input type="range" id="branches" min="0" max="100" step="1" value="3">
            <br>
            <label for="strength">Max Branch Threshold:</label>
            <input type="range" id="strength" min="0" max="10" step="1" value="3">
            <br>
            <label for="spacing">Branch Spacing</label>
            <input type="range" id="spacing" min="0" max="100" step="0.01" value="80">
        </div>
    </span>
   
</body>

</html>

Lets also add script tag just below the <span> section as shown below. Inside this tag, we shall add our JavaScript code.

<script type=text/javascript>


</script>

Lets Dive Into the Code

The JavaScript code is where the magic happens. Here’s a breakdown of its core components:

1.Setting Up the Canvas

This initializes the canvas and sets up the drawing context.

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;

// Frame rate settings
const timeout = 1000 / 60; // 60 FPS

2. Simulation Settings

To help control the settings of our simulation, we will setup some variables using a settings object. These settings will be controlled by the input controls.