Animated Emission Effects with Procedural Noise in GLSL

Emissive materials are commonly used in real-time graphics to simulate glowing surfaces — whether it’s a flickering sci-fi interface, a magical rune, or an energy pulse moving through a forcefield. These materials not only enhance visual appeal but also serve functional purposes, like drawing the viewer’s attention or indicating interactivity.

This article outlines how to implement a simple yet effective animated emission shader in GLSL. By combining a static base texture with procedural noise, the emission intensity can evolve over time, creating the illusion of movement and energy.

Shader Concept

The shader samples color from a base texture and alpha from an alpha map. A procedural noise function modulates the brightness of the base color, effectively animating the emission. This technique avoids relying on external video textures or sprite sheets, making it lightweight and highly customizable.

Fragment Shader Implementation

Here’s a simplified GLSL shader that demonstrates the concept:

precision highp float;

uniform sampler2D uBaseTexture;
uniform sampler2D uAlphaTexture;
uniform float time;

varying vec2 vUv;

// --- Simple pseudo-random noise function (replace with simplex or fbm for richer effects) ---
float hash(vec2 p) {
  return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}

float noise(vec2 p) {
  vec2 i = floor(p);
  vec2 f = fract(p);
  vec2 u = f * f * (3.0 - 2.0 * f);

  return mix(
    mix(hash(i + vec2(0.0, 0.0)), hash(i + vec2(1.0, 0.0)), u.x),
    mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x),
    u.y
  );
}

void main() {
  // Sample color and alpha textures
  vec4 baseColor = texture2D(uBaseTexture, vUv);
  float alpha = texture2D(uAlphaTexture, vUv).r;

  // Animate 2D noise using time
  float n = noise(vUv * 5.0 + vec2(time * 0.1));

  // Modulate base color using noise for emissive effect
  vec3 emissiveColor = baseColor.rgb * n;

  // Final output with modulated emission and alpha
  gl_FragColor = vec4(emissiveColor, alpha);
}

How It Works

  • The base texture defines the static color palette of the material — for example, a circuit trace or magical glyph.
  • A procedural noise function generates smooth variations over space and time.
  • This noise value is multiplied with the base color, making certain areas appear brighter or dimmer as the noise shifts.
  • An alpha texture controls transparency, enabling soft fades or cutouts.

By adjusting the frequency (vUv * 5.0), speed (time * 0.1), and contrast of the noise, the look can range from slow undulations to high-frequency flickering.

Integration in Three.js

In Three.js, this shader would typically be used in a ShaderMaterial, like so:

const customMaterial = new THREE.ShaderMaterial({
  vertexShader,
  fragmentShader,
  uniforms: {
    uBaseTexture: { value: baseTexture },
    uAlphaTexture: { value: alphaTexture },
    time: { value: 0 }
  },
  transparent: true
});

And inside the render loop, the time uniform would be updated:

customMaterial.uniforms.time.value = performance.now() / 1000;

Applications

This approach is widely applicable for real-time effects, including:

  • Animated sci-fi or cyberpunk panels
  • Magical symbols or enchanted objects
  • Energy cores or glowing machinery
  • Pulsating forcefields or shields

It’s ideal for stylized environments or games where procedural effects need to stay responsive and light on performance.

Summary

Animating emissive surfaces with procedural noise provides a flexible and efficient way to bring static materials to life. This GLSL-based approach allows artists and developers to generate endlessly looping, dynamic effects without relying on external assets — keeping visual fidelity high while minimizing resource overhead.

For more advanced results, the base technique can be extended with fractal noise (fBM), additional color ramps, or lighting models. But even in its simplest form, it provides a solid foundation for expressive, glowing visuals in real-time applications.

Leave a comment

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