Learn how to create mesmerizing animated plasma effects in Go with Ebiten

What is a Plasma Effect?
A plasma effect is a classic demoscene visual effect that creates flowing, organic patterns using mathematical functions. It combines multiple sine waves to generate smooth, colorful animations that look like liquid plasma flowing across the screen.
📚 What you’ll learn:
- How to use sine waves to create organic patterns
- Working with Ebiten’s pixel rendering system
- Converting mathematical values to colors
- Creating smooth animations with time-based updates
Step-by-Step Implementation
1Set Up the Basic Structure
Here is the full code if you want to skip the steps below: plasma.go
First, creat…
Learn how to create mesmerizing animated plasma effects in Go with Ebiten

What is a Plasma Effect?
A plasma effect is a classic demoscene visual effect that creates flowing, organic patterns using mathematical functions. It combines multiple sine waves to generate smooth, colorful animations that look like liquid plasma flowing across the screen.
📚 What you’ll learn:
- How to use sine waves to create organic patterns
- Working with Ebiten’s pixel rendering system
- Converting mathematical values to colors
- Creating smooth animations with time-based updates
Step-by-Step Implementation
1Set Up the Basic Structure
Here is the full code if you want to skip the steps below: plasma.go
First, create the main package and import the necessary libraries:
package main
import (
"image/color"
"math"
"github.com/hajimehoshi/ebiten/v2"
)
const (
screenWidth = 640
screenHeight = 480
)
💡 Tip: Start with a reasonable screen size like 640x480. You can always change it later!
2Create the Game Structure
Ebiten requires a game struct that implements the Game interface:
type Game struct {
time float64 // Animation time counter
pixels []byte // Pixel buffer for the screen
}
func NewGame() *Game {
return &Game{
pixels: make([]byte, screenWidth*screenHeight*4),
}
}
🔍 Why multiply by 4? Each pixel needs 4 bytes: Red, Green, Blue, and Alpha (RGBA format).
3The Plasma Function - The Heart of the Effect
This is where the magic happens! The plasma function combines multiple sine waves to create organic patterns:
func plasma(x, y, t float64) float64 {
// Wave 1: Horizontal wave
v := math.Sin(x*0.04 + t)
// Wave 2: Vertical wave (different speed)
v += math.Sin(y*0.03 + t*1.3)
// Wave 3: Diagonal wave
v += math.Sin((x+y)*0.03 + t*0.7)
// Wave 4: Circular wave from center
v += math.Sin(math.Sqrt(x*x+y*y)*0.02 + t*1.5)
// Average the waves (divide by number of waves)
return v / 4.0
}
📊 Understanding the parameters:
- x * 0.04 - Controls horizontal wave frequency (smaller = wider waves)
- t * 1.3 - Controls animation speed for that wave
- math.Sqrt(x*x+y*y) - Distance from center (creates circular patterns)
- Combining all waves creates complex, organic motion
4Converting Values to Colors
Transform the plasma values (-1 to 1) into beautiful RGB colors:
func getColor(value float64) color.RGBA {
// Normalize from [-1, 1] to [0, 1]
normalized := (value + 1) / 2
// Use sine waves with phase shifts for RGB
r := uint8(math.Sin(normalized*math.Pi*2) * 127 + 128)
g := uint8(math.Sin(normalized*math.Pi*2+2*math.Pi/3) * 127 + 128)
b := uint8(math.Sin(normalized*math.Pi*2+4*math.Pi/3) * 127 + 128)
return color.RGBA{r, g, b, 255}
}
🎨 Color Theory: The phase shifts (2π/3 and 4π/3) create complementary colors. Try different values to get different color schemes!
5The Update Function
This runs every frame to advance the animation:
func (g *Game) Update() error {
g.time += 0.05 // Increment time for animation
return nil
}
⚠️ Performance Note: Smaller time increments = slower animation. Adjust this value to control speed!
6The Draw Function - Rendering the Magic
This is where we generate and display the plasma effect:
func (g *Game) Draw(screen *ebiten.Image) {
// Loop through every pixel on the screen
for y := 0; y < screenHeight; y++ {
for x := 0; x < screenWidth; x++ {
// Center the coordinates (0,0 at center of screen)
cx := float64(x - screenWidth/2)
cy := float64(y - screenHeight/2)
// Calculate plasma value for this pixel
value := plasma(cx, cy, g.time)
// Convert to color
c := getColor(value)
// Write to pixel buffer (RGBA format)
idx := (y*screenWidth + x) * 4
g.pixels[idx] = c.R
g.pixels[idx+1] = c.G
g.pixels[idx+2] = c.B
g.pixels[idx+3] = c.A
}
}
// Push all pixels to screen at once
screen.WritePixels(g.pixels)
}
🎯 Why center coordinates? Centering makes the circular waves symmetric and creates more pleasing patterns.
7Layout and Main Functions
Complete the implementation with these required functions:
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Plasma Effect")
ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled)
game := NewGame()
if err := ebiten.RunGame(game); err != nil {
panic(err)
}
}
🎨 Customization Ideas
Change Colors
Modify the phase shifts in getColor():
// For warmer colors
g := uint8(math.Sin(normalized*math.Pi*2+math.Pi/2) * 127 + 128)
// For cooler colors
b := uint8(math.Sin(normalized*math.Pi*2+math.Pi) * 127 + 128)
Adjust Wave Patterns
In the plasma() function, try:
- Changing frequency multipliers (0.04, 0.03, etc.)
- Changing time multipliers (1.3, 0.7, 1.5)
- Adding more waves for more complexity
- Removing waves for simpler patterns
Speed Control
In Update(), adjust the time increment:
g.time += 0.1 // Faster animation
g.time += 0.02 // Slower animation
🚀 Running Your Plasma Effect
Save your code as plasma.go and run:
go run plasma.go
🎉 Success! You should see a window with flowing, colorful plasma patterns. Press the window close button to exit.
📚 How It Works - The Math Behind It
The plasma effect works by:
- Layering sine waves - Each wave contributes to the final pattern
- Using coordinates as input - Position determines the wave phase
- Adding time - Makes the waves move and flow
- Averaging results - Keeps values in a predictable range
- Mapping to colors - Converts numbers to visual output
💪 Challenges to Try
- Add mouse interaction - make the plasma react to cursor position
- Create a color picker to change the palette in real-time
- Add keyboard controls to adjust speed and frequency
- Combine with other effects like blur or distortion
- Make it fullscreen
- Add sound reactivity using audio input
🎓 What You Learned
Congratulations! You now know how to:
- Use Ebiten to create graphical applications in Go
- Generate procedural patterns with mathematical functions
- Work with pixel buffers for efficient rendering
- Create smooth animations using time-based updates
- Convert mathematical values to colors