Plasma effect: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(29 intermediate revisions by 17 users not shown)
Line 12: Line 12:
* [http://www.bidouille.org/prog/plasma Plasma (bidouille.org)]
* [http://www.bidouille.org/prog/plasma Plasma (bidouille.org)]
<br><br>
<br><br>

=={{header|AWK}}==
<syntaxhighlight lang="awk">
#!/usr/bin/awk -f

function clamp(val, a, b) { return (val<a) ? a : (val>b) ? b : val }

## return a timestamp with centisecond precision
function timex() {
getline < "/proc/uptime"
close("/proc/uptime")
return $1
}

## draw image to terminal
function draw(src, xpos, ypos, w,h, x,y, up,dn, line,screen) {
w = src["width"]
h = src["height"]

for (y=0; y<h; y+=2) {
line = sprintf("\033[%0d;%0dH", y/2+ypos+1, xpos+1)
for (x=0; x<w; x++) {
up = src[x,y+0]
dn = src[x,y+1]
line = line "\033[38;2;" palette[up] ";48;2;" palette[dn] "m▀"
}
screen = screen line "\033[0m"
}
printf("%s", screen)
}

## generate a palette
function paletteGen( i, r,g,b) {
# generate palette
for (i=0; i<256; i++) {
r = 128 + 128 * sin(3.14159265 * i / 32.0)
g = 128 + 128 * sin(3.14159265 * i / 64.0)
b = 128 + 128 * sin(3.14159265 * i / 128.0)
palette[i] = sprintf("%d;%d;%d", clamp(r,0,255), clamp(g,0,255), clamp(b,0,255))
}
}

## generate a plasma
function plasmaGen(plasma, w, h, x,y, color) {
for (y=0; y<h; y++) {
for (x=0; x<w; x++) {
color = ( \
128.0 + (128.0 * sin((x / 8.0) - cos(now/2) )) \
+ 128.0 + (128.0 * sin((y / 16.0) - sin(now)*2 )) \
+ 128.0 + (128.0 * sin(sqrt((x - w / 2.0) * (x - w / 2.0) + (y - h / 2.0) * (y - h / 2.0)) / 4.0)) \
+ 128.0 + (128.0 * sin((sqrt(x * x + y * y) / 4.0) - sin(now/4) )) \
) / 4;

plasma[x,y] = int(color)
}
}
}

BEGIN {
"stty size" | getline
buffer["height"] = h = ($1 ? $1 : 24) * 2
buffer["width"] = w = ($2 ? $2 : 80)

paletteGen()
start = timex()

while (elapsed < 30) {
elapsed = (now = timex()) - start

plasmaGen(plasma, w, h)

# copy plasma to buffer
for (y=0; y<h; y++)
for (x=0; x<w; x++)
buffer[x,y] = int(plasma[x,y] + now * 100) % 256

# draw buffer to terminal
draw(buffer)
}

printf("\n")
}
</syntaxhighlight>

=={{header|C}}==
=={{header|C}}==
===ASCII version for Windows===
===ASCII version for Windows===
If you don't want to bother with Graphics libraries, try out this nifty implementation on Windows :
If you don't want to bother with Graphics libraries, try out this nifty implementation on Windows :
<syntaxhighlight lang="c">
<lang C>
#include<windows.h>
#include<windows.h>
#include<stdlib.h>
#include<stdlib.h>
Line 53: Line 137:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>


===Graphics version===
===Graphics version===
And here's the Graphics version, requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. Prints out usage on incorrect invocation.
And here's the Graphics version, requires the [http://www.cs.colorado.edu/~main/bgi/cs1300/ WinBGIm] library. Prints out usage on incorrect invocation.
<syntaxhighlight lang="c">
<lang C>
#include<graphics.h>
#include<graphics.h>
#include<stdlib.h>
#include<stdlib.h>
Line 101: Line 185:
return 0;
return 0;
}
}
</syntaxhighlight>
</lang>


=={{header|C++}}==
=={{header|C++}}==
===Version 1 (windows.h)===
[[File:plasma.png]]
[[File:plasma.png]]


Windows version.
Windows version.
<lang cpp>
<syntaxhighlight lang="cpp">
#include <windows.h>
#include <windows.h>
#include <math.h>
#include <math.h>
Line 323: Line 408:
return myWnd.Run( hInstance );
return myWnd.Run( hInstance );
}
}
</syntaxhighlight>
</lang>

===Version 2 (SDL2)===
{{libheader|SDL2}}
<center>Take that, Paulo Jorente!</center>

====Version 2.1====
<syntaxhighlight lang="cpp" line>
// Standard C++ stuff
#include <iostream>
#include <array>
#include <cmath>
#include <numbers>

// SDL2 stuff
#include "SDL2/SDL.h"

// Compile: g++ -std=c++20 -Wall -Wextra -pedantic -Ofast SDL2Plasma.cpp -o SDL2Plasma -lSDL2 -fopenmp

struct RGB {
int Red, Green, Blue;
};

RGB HSBToRGB(const double hue, const double saturation, const double brightness) {
double Red = 0,
Green = 0,
Blue = 0;
if (hue == 1) {
Red = brightness;
} else {
double Sector = hue * 360,
Cosine = std::cos(Sector*std::numbers::pi/180),
Sine = std::sin(Sector*std::numbers::pi/180);
Red = brightness * Cosine + saturation * Sine;
Green = brightness * Cosine - saturation * Sine;
Blue = brightness - saturation * Cosine;
}
RGB Result;
Result.Red = (int)(Red * 255);
Result.Green = (int)(Green * 255);
Result.Blue = (int)(Blue * 255);
return Result;
}

template <int width_array_length, int height_array_length>
void CalculatePlasma(std::array<std::array<double, width_array_length>, height_array_length> &array) {
#pragma omp parallel for
for (unsigned long y = 0; y < array.size(); y++)
#pragma omp simd
for (unsigned long x = 0; x < array.at(0).size(); x++) {
// Calculate the hue
double Hue = std::sin(x/16.0);
Hue += std::sin(y/8.0);
Hue += std::sin((x+y)/16.0);
Hue += std::sin(std::sqrt(x*x+y*y)/8.0);
Hue += 4;
// Clamp the hue to the range of [0, 1]
Hue /= 8;
array[y][x] = Hue;
}
}

template <int width_array_length, int height_array_length>
void DrawPlasma(SDL_Renderer *r, const std::array<std::array<double, width_array_length>, height_array_length> &array, const double &hue_shift) {
for (unsigned long y = 0; y < array.size(); y++)
for (unsigned long x = 0; x < array.at(0).size(); x++) {
// Convert the HSB value to RGB value
double Hue = hue_shift + std::fmod(array[y][x], 1);
RGB CurrentColour = HSBToRGB(Hue, 1, 1);
// Draw the actual plasma
SDL_SetRenderDrawColor(r, CurrentColour.Red, CurrentColour.Green, CurrentColour.Blue, 0xff);
SDL_RenderDrawPoint(r, x, y);
}
}

int main() {
const unsigned DefaultWidth = 640,
DefaultHeight = 640;
std::array<std::array<double, DefaultWidth>, DefaultHeight> ScreenArray;
SDL_Window *Window = NULL; // Define window
SDL_Renderer *Renderer = NULL; // Define renderer
// Init everything just for sure
SDL_Init(SDL_INIT_EVERYTHING);
// Set window size to 640x640, always shown
Window = SDL_CreateWindow("Plasma effect", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, SDL_WINDOW_SHOWN);
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
// Set background colour to white
SDL_SetRenderDrawColor(Renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(Renderer);
// Create an event handler and a "quit" flag
SDL_Event e;
bool KillWindow = false;
CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
double HueShift = 0.0;
// The window runs until the "quit" flag is set to true
while (!KillWindow) {
while (SDL_PollEvent(&e) != 0) {
// Go through the events in the queue
switch (e.type) {
// Event: user hits a key
case SDL_QUIT: case SDL_KEYDOWN:
// Destroy window
KillWindow = true;
break;
}
}
// Render the plasma
DrawPlasma<DefaultWidth, DefaultHeight>(Renderer, ScreenArray, HueShift);
SDL_RenderPresent(Renderer);
if (HueShift < 1) {
HueShift = std::fmod(HueShift + 0.0025, 3);
} else {
CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
HueShift = 0.0;
}
}
// Destroy renderer and window
SDL_DestroyRenderer(Renderer);
SDL_DestroyWindow(Window);
SDL_Quit();
return 0;
}
</syntaxhighlight>

{{Output}}
<center>[[File:C++ plasma effect SDL2.gif]]</center>

====Version 2.2====
<syntaxhighlight lang="cpp" line>
// Standard C++ stuff
#include <iostream>
#include <array>
#include <cmath>
#include <numbers>

// SDL2 stuff
#include "SDL2/SDL.h"

// Compile: g++ -std=c++20 -Wall -Wextra -pedantic -Ofast SDL2Plasma.cpp -o SDL2Plasma -lSDL2 -fopenmp

struct RGB {
int Red, Green, Blue;
};

RGB HSBToRGB(const float hue, const float saturation, const float brightness) {
float Red = 0,
Green = 0,
Blue = 0;
if (hue == 1) {
Red = brightness;
} else {
float Sector = hue * 360,
Cosine = std::cos(Sector*std::numbers::pi/180),
Sine = std::sin(Sector*std::numbers::pi/180);
Red = brightness * Cosine + saturation * Sine;
Green = brightness * Cosine - saturation * Sine;
Blue = brightness - saturation * Cosine;
}
RGB Result;
Result.Red = (int)(Red * 255);
Result.Green = (int)(Green * 255);
Result.Blue = (int)(Blue * 255);
return Result;
}

template <int width_array_length, int height_array_length>
void CalculatePlasma(std::array<std::array<float, width_array_length>, height_array_length> &array) {
#pragma omp parallel for
for (unsigned long y = 0; y < array.size(); y++)
#pragma omp simd
for (unsigned long x = 0; x < array.at(0).size(); x++) {
// Calculate the hue
float Hue = std::sin(x/16.0);
Hue += std::sin(y/8.0);
Hue += std::sin((x+y)/16.0);
Hue += std::sin(std::sqrt(x*x+y*y)/8.0);
Hue += 4;
// Clamp the hue to the range of [0, 1]
Hue /= 8;
array[y][x] = Hue;
}
}

template <int width_array_length, int height_array_length>
void DrawPlasma(SDL_Renderer *r, SDL_Texture *t, const std::array<std::array<float, width_array_length>, height_array_length> &array, const float &hue_shift) {
unsigned char *Bytes = NULL;
int Pitch = 0;
float Hue;
// Lock the texture
SDL_LockTexture(t, NULL, (void**)&Bytes, &Pitch);
for (unsigned long y = 0; y < array.size(); y++)
for (unsigned long x = 0; x < array.at(0).size(); x++) {
// Convert the HSB value to RGB value
Hue = hue_shift + std::fmod(array[y][x], 1);
RGB CurrentColour = HSBToRGB(Hue, 1, 1);
// Write colour data directly to texture
Bytes[y*Pitch+x*4] = CurrentColour.Red; // Red
Bytes[y*Pitch+x*4+1] = CurrentColour.Green; // Green
Bytes[y*Pitch+x*4+2] = CurrentColour.Blue; // Blue
Bytes[y*Pitch+x*4+3] = 0xff; // Alpha
}
// Unlock the texture
SDL_UnlockTexture(t);
// Feed the finished texture to the renderer
SDL_RenderCopy(r, t, NULL, NULL);
}

int main() {
const unsigned DefaultWidth = 640,
DefaultHeight = 640;
std::array<std::array<float, DefaultWidth>, DefaultHeight> ScreenArray;
SDL_Window *Window = NULL; // Define window
SDL_Renderer *Renderer = NULL; // Define renderer
// Init everything just for sure
SDL_Init(SDL_INIT_EVERYTHING);
// Set window size to 640x640, always shown
Window = SDL_CreateWindow("Plasma effect", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, SDL_WINDOW_SHOWN);
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture *PlasmaTexture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, DefaultWidth, DefaultHeight);
// Set background colour to white
SDL_SetRenderDrawColor(Renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(Renderer);
// Create an event handler and a "quit" flag
SDL_Event e;
bool KillWindow = false;
CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
float HueShift = 0.0;
// The window runs until the "quit" flag is set to true
while (!KillWindow) {
while (SDL_PollEvent(&e) != 0) {
// Go through the events in the queue
switch (e.type) {
// Event: user hits a key
case SDL_QUIT: case SDL_KEYDOWN:
// Destroy window
KillWindow = true;
break;
}
}
// Render the plasma
DrawPlasma<DefaultWidth, DefaultHeight>(Renderer, PlasmaTexture, ScreenArray, HueShift);
SDL_RenderPresent(Renderer);
if (HueShift < 1) {
HueShift = std::fmod(HueShift + 0.0025, 3);
} else {
CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
HueShift = 0.0;
}
}
// Destroy renderer and window
SDL_DestroyRenderer(Renderer);
SDL_DestroyWindow(Window);
SDL_Quit();
return 0;
}
</syntaxhighlight>

{{Output}}
<center>[[File:C++ plasma effect SDL2 version 2.2.png|480px]]</center>


=={{header|Ceylon}}==
=={{header|Ceylon}}==
Be sure to import javafx.base, javafx.graphics and ceylon.numeric in your module file.
Be sure to import javafx.base, javafx.graphics and ceylon.numeric in your module file.
{{trans|Java}}
{{trans|Java}}
<lang ceylon>
<syntaxhighlight lang="ceylon">
import javafx.application {
import javafx.application {
Application
Application
Line 413: Line 789:
}
}


}</lang>
}</syntaxhighlight>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
Line 419: Line 795:
{{libheader|simple-rgb}}
{{libheader|simple-rgb}}
plasma_demo.lisp:
plasma_demo.lisp:
<lang lisp>(require :lispbuilder-sdl)
<syntaxhighlight lang="lisp">(require :lispbuilder-sdl)
(require :simple-rgb)
(require :simple-rgb)


Line 486: Line 862:
(:quit-event () t))))))
(:quit-event () t))))))


(demo/plasma)</lang>
(demo/plasma)</syntaxhighlight>

=={{header|Delphi}}==
{{works with|Delphi|6.0}}
[[File:DelphiPlasma.png|frame|none]]
{{libheader|SysUtils,StdCtrls}}
This code animates the plasma, which looks very nice. However, there are too many colors to render it properly with an animated GIF. As a result, I've only posted a static image of the plasma.


<syntaxhighlight lang="Delphi">

function PasmaPixel(X,Y,W,H: integer; Offset: double): TColor;
{Return pixel based on X,Y position and the size of the image}
{Offset controls the progression through the plasma for animation}
var A, B, C, Red, Green, Blue: double;
begin
A:=X + Y + Cos(Sin(Offset) * 2) * 100 + Sin(x / 100) * 1000;
B:=Y / H / 0.2 + Offset;
C:=X / W / 0.2;
Red:=abs(Sin(B + Offset) / 2 + C / 2 - B - C + Offset);
Green:=abs(Sin(Red + Sin(A / 1000 + Offset) + Sin(Y / 40 + Offset) + Sin((X + Y) / 100) * 3));
Blue:=abs(sin(Green + Cos(B + C + Green) + Cos(C) + Sin(X / 1000)));
Result := RGB(Round(255*Red), Round(255*Green), Round(255*Blue));
end;


procedure DisplayPlasma(Bmp: TBitmap; Width,Height: integer; Offset: double);
{Draw the plasma pattern on the bitmap progressed according to "Offset"}
var X,Y: integer;
var Scan: pRGBTripleArray;
begin
Bmp.PixelFormat:=pf24Bit;
for Y:=0 to Height-1 do
begin
Scan:=Bmp.ScanLine[Y];
for X:=0 to Width-1 do
begin
Scan[X]:=ColorToTriple(PasmaPixel(X,Y,Width,Height,Offset));
end;
end;
end;
var Offset: double;


procedure ShowPlasma(Image: TImage);
{Animate 10 seconds of plasma display}
var X,Y: integer;
var I,StartTime,CurTime,StopTime: integer;
const TimeLimit = 10;
begin
{setup stop time based on real-time clock}
StartTime:=GetTickCount;
StopTime:=StartTime + (TimeLimit * 1000);
{Keep display frame until stop time is reached}
for I:=0 to high(integer) do
begin
{Display one frame}
DisplayPlasma(Image.Picture.Bitmap,Image.Width,Image.Height,Offset);
{Display count-down time}
CurTime:=GetTickCount;
Image.Canvas.Brush.Style:=bsClear;
Image.Canvas.TextOut(5,5,IntToStr((CurTime-StartTime) div 1000)+' '+IntToStr(I));
Image.Repaint;
Application.ProcessMessages;
if Application.Terminated then exit;
{Exit if timed out}
if CurTime>StopTime then break;
Sleep(50);
{progress animation one step}
Offset:=Offset+0.1;
end;
end;

</syntaxhighlight>
{{out}}
<pre>
Elapsed Time: 10.127 Sec.

</pre>

=={{header|Forth}}==

{{works with|gforth|0.7.3}}
Ouputs a PPM file.
<syntaxhighlight lang="forth">: sqrt ( u -- sqrt ) ( Babylonian method )
dup 2/ ( first square root guess is half )
dup 0= if drop exit then ( sqrt[0]=0, sqrt[1]=1 )
begin dup >r 2dup / r> + 2/ ( stack: square old-guess new-guess )
2dup > while ( as long as guess is decreasing )
nip repeat ( forget old-guess and repeat )
drop nip ;

: sgn 0< if -1 else 1 then ;
: isin
256 mod 128 - \ full circle is 255 "degrees"
dup dup sgn * 128 swap - * \ second order approximation
negate 32 / ; \ amplitude is +/-128

: color-shape 256 mod 6 * 765 - abs 256 - 0 max 255 min ; \ trapezes
: hue
dup color-shape . \ red
dup 170 + color-shape . \ green
85 + color-shape . ; \ blue

: plasma
outfile-id >r
s" plasma.ppm" w/o create-file throw to outfile-id
s\" P3\n500 500\n255\n" type
500 0 do
500 0 do
i 2 * isin 128 +
j 4 * isin 128 + +
i j + isin 2 * 128 + +
i i * j j * + sqrt 4 * isin 128 + +
4 /
hue
s\" \n" type
loop
s\" \n" type
loop

outfile-id close-file throw
r> to outfile-id ;

plasma</syntaxhighlight>




=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' version 12-04-2017
<syntaxhighlight lang="freebasic">' version 12-04-2017
' compile with: fbc -s gui
' compile with: fbc -s gui
' Computer Graphics Tutorial (lodev.org), last example
' Computer Graphics Tutorial (lodev.org), last example
Line 524: Line 1,028:
End If
End If


Loop</lang>
Loop</syntaxhighlight>


=={{header|Go}}==
=={{header|Go}}==
Line 536: Line 1,040:
$ eog plasma2.gif
$ eog plasma2.gif
</pre>
</pre>
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 624: Line 1,128:
log.Fatal(err2)
log.Fatal(err2)
}
}
}</lang>
}</syntaxhighlight>


=={{header|Gosu}}==
=={{header|Gosu}}==
[[File:Gosu_plasma.png|200px|thumb|right]]
[[File:Gosu_plasma.png|200px|thumb|right]]
{{trans|Java}}
{{trans|Java}}
<lang gosu>
<syntaxhighlight lang="gosu">
uses javax.swing.*
uses javax.swing.*
uses java.awt.*
uses java.awt.*
Line 675: Line 1,179:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|J}}==
=={{header|J}}==
[[File:J-viewmat-plasma.png|200px|thumb|right]]
[[File:J-viewmat-plasma.png|200px|thumb|right]]
<lang j>require 'trig viewmat'
<syntaxhighlight lang="j">require 'trig viewmat'
plasma=: 3 :0
plasma=: 3 :0
'w h'=. y
'w h'=. y
Line 689: Line 1,193:
xy2=. sin (Y +&.*:/ X)*32
xy2=. sin (Y +&.*:/ X)*32
xy1+xy2+y1+/x1
xy1+xy2+y1+/x1
)</lang>
)</syntaxhighlight>


<lang j> viewmat plasma 256 256</lang>
<syntaxhighlight lang="j"> viewmat plasma 256 256</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
[[File:plasma_effect_java.png|200px|thumb|right]]
[[File:plasma_effect_java.png|200px|thumb|right]]
{{works with|Java|8}}
{{works with|Java|8}}
<lang java>import java.awt.*;
<syntaxhighlight lang="java">import java.awt.*;
import java.awt.event.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.image.*;
Line 777: Line 1,281:
});
});
}
}
}</lang>
}</syntaxhighlight>


=={{header|JavaScript}}==
=={{header|JavaScript}}==
{{trans|Java}}
{{trans|Java}}
<lang javascript><!DOCTYPE html>
<syntaxhighlight lang="javascript"><!DOCTYPE html>
<html lang='en'>
<html lang='en'>
<head>
<head>
Line 902: Line 1,406:


</body>
</body>
</html></lang>
</html></syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
{{trans|Perl}}
{{trans|Perl}}
<lang julia>using Luxor, Colors
<syntaxhighlight lang="julia">using Luxor, Colors


Drawing(800, 800)
Drawing(800, 800)


function plasma(wid, hei)
function plasma(wid, hei)
for x in 1:wid, y in 1:hei
for x in -wid:wid, y in -hei:hei
sethue(parse(Colorant, HSV(180 + 45sin(x/19) + 45sin(y/9) +
sethue(parse(Colorant, HSV(180 + 45sin(x/19) + 45sin(y/9) +
45sin((x+y)/25) + 45sin(sqrt(x^2 + y^2)/8), 1, 1)))
45sin((x+y)/25) + 45sin(sqrt(x^2 + y^2)/8), 1, 1)))
Line 918: Line 1,422:
end
end


@png begin plasma(800, 800) end
@png plasma(800, 800)
</syntaxhighlight>
</lang>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Java}}
{{trans|Java}}
<lang scala>// version 1.1.2
<syntaxhighlight lang="scala">// version 1.1.2


import java.awt.*
import java.awt.*
Line 993: Line 1,497:
f.isVisible = true
f.isVisible = true
}
}
}</lang>
}</syntaxhighlight>


=={{header|Lua}}==
=={{header|Lua}}==
Needs L&Ouml;VE 2D Engine
Needs L&Ouml;VE 2D Engine
{{trans|C++}}
{{trans|C++}}
<lang lua>
<syntaxhighlight lang="lua">
_ = love.graphics
_ = love.graphics
p1, p2, points = {}, {}, {}
p1, p2, points = {}, {}, {}
Line 1,039: Line 1,543:
_.points( points )
_.points( points )
end
end
</syntaxhighlight>
</lang>

=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">s = 400;
Image@Table[
hue = Sin[i/16] + Sin[j/8] + Sin[(i + j)/16] + Sin[Sqrt[i^2 + j^2]/8];
hue = (hue + 4)/8;
Hue[hue, 1, 0.75]
,
{i, 1.0, s},
{j, 1.0, s}
]</syntaxhighlight>
{{out}}
Outputs an image.

=={{header|Nim}}==
{{libheader|imageman}}
<syntaxhighlight lang="nim">import math
import imageman

const
Width = 400
Height = 400

var img = initImage[ColorRGBF](Width, Height)
for x in 0..<Width:
for y in 0..<Height:
let fx = float32(x)
let fy = float32(y)
var hue = sin(fx / 16) + sin(fy / 8) + sin((fx + fy) / 16) + sin(sqrt((fx^2 + fy^2)) / 8)
hue = (hue + 4) / 8 # Between 0 and 1.
let rgb = to(ColorHSL([hue * 360, 1, 0.5]), ColorRGBF)
img[x, y] = rgb
img.savePNG("plasma.png")</syntaxhighlight>


=={{header|Ol}}==
=={{header|Ol}}==
<lang scheme>
<syntaxhighlight lang="scheme">
; creating the "plasma" image buffer
; creating the "plasma" image buffer
(import (lib math))
(import (scheme inexact))
(define plasma
(define plasma
(fold append #null
(fold append #null
Line 1,057: Line 1,594:
(iota 256)))
(iota 256)))
(iota 256))))
(iota 256))))
</syntaxhighlight>
</lang>
<lang scheme>
<syntaxhighlight lang="scheme">
; rendering the prepared buffer (using OpenGL)
; rendering the prepared buffer (using OpenGL)
(import (lib gl))
(import (lib gl1))
(import (OpenGL version-1-1))
(gl:set-window-size 256 256)
(gl:set-window-size 256 256)


Line 1,073: Line 1,609:
(glEnable GL_TEXTURE_2D)
(glEnable GL_TEXTURE_2D)


(gl:set-renderer (lambda ()
(gl:set-renderer (lambda (_)
(glClear GL_COLOR_BUFFER_BIT)
(glClear GL_COLOR_BUFFER_BIT)
(glBegin GL_QUADS)
(glBegin GL_QUADS)
Line 1,084: Line 1,620:
(glTexCoord2f 1 0)
(glTexCoord2f 1 0)
(glVertex2f 1 -1)
(glVertex2f 1 -1)
(glEnd)
(glEnd)))
</syntaxhighlight>
#null))
</lang>

=={{header|Racket}}==

Uses `return-color-by-pos` from [[#Lisp]], because it was almost lift and shift

<lang racket>#lang racket
;; from lisp (cos I could just lift the code)
(require images/flomap
2htdp/universe
racket/flonum)

;; copied from pythagoras-triangle#racket
(define (real-remainder x q) (- x (* (floor (/ x q)) q)))

(define (HSV->RGB H S V)
(define C (* V S)) ; chroma
(define H′ (/ H 60))
(define X (* C (- 1 (abs (- (real-remainder H′ 2) 1)))))
(define-values (R1 G1 B1)
(cond
[(< H′ 1) (values C X 0.)]
[(< H′ 2) (values X C 0.)]
[(< H′ 3) (values 0. C X)]
[(< H′ 4) (values 0. X C)]
[(< H′ 5) (values X 0. C)]
[(< H′ 6) (values C 0. X)]
[else (values 0. 0. 0.)]))
(define m (- V C))
(values (+ R1 m) (+ G1 m) (+ B1 m)))


(define ((colour-component-by-pos ϕ) k x y)
(let ((rv
(/ (+ (+ 1/2 (* 1/2 (sin (+ ϕ (/ x 16.0)))))
(+ 1/2 (* 1/2 (sin (+ ϕ (/ y 8.0)))))
(+ 1/2 (* 1/2 (sin (+ ϕ (/ (+ x y) 16.0)))))
(+ 1/2 (* 1/2 (sin (+ ϕ (/ (sqrt (+ (sqr x) (sqr y))) 8.0))))))
4.0)))
rv))

(define ((plasma-flomap (ϕ 0)) w h)
(build-flomap 1 w h (colour-component-by-pos ϕ)))

(define ((plasma-image (ϕ 0)) w h)
(flomap->bitmap ((plasma-flomap ϕ) w h)))

(define ((colour-plasma plsm) t)
(let ((w (flomap-width plsm))
(h (flomap-height plsm)))
(flomap->bitmap
(build-flomap* 3 w h
(λ (x y)
(define-values (r g b)
(HSV->RGB (real-remainder
(+ (* t 5.)
(* 360 (flomap-ref plsm 0 x y)))
360.) 1. 1.))
(flvector r g b))))))

;((plasma-image) 200 200)

;((plasma-image (/ pi 32)) 200 200)

(define plsm ((plasma-flomap) 300 300))
(animate (λ (t)
((colour-plasma plsm) t)))</lang>


=={{header|Perl}}==
=={{header|Perl}}==
{{trans|Perl 6}}
{{trans|Raku}}
<lang perl>use Imager;
<syntaxhighlight lang="perl">use Imager;


sub plasma {
sub plasma {
Line 1,174: Line 1,643:


my $img = plasma(400, 400);
my $img = plasma(400, 400);
$img->write(file => 'plasma-perl.png');</lang>
$img->write(file => 'plasma-perl.png');</syntaxhighlight>
Off-site image: [https://github.com/SqrtNegInf/Rosettacode-Perl5-Smoke/blob/master/ref/plasma.png Plasma effect]
Off-site image: [https://github.com/SqrtNegInf/Rosettacode-Perl5-Smoke/blob/master/ref/plasma.png Plasma effect]

=={{header|Perl 6}}==
[[File:Plasma-perl6.png|200px|thumb|right]]
{{works with|Rakudo|2018.09}}
<lang perl6>use Image::PNG::Portable;

my ($w, $h) = 400, 400;
my $out = Image::PNG::Portable.new: :width($w), :height($h);

plasma($out);

$out.write: 'Plasma-perl6.png';

sub plasma ($png) {
(^$w).race.map: -> $x {
for ^$h -> $y {
my $hue = 4 + sin($x / 19) + sin($y / 9) + sin(($x + $y) / 25) + sin(sqrt($x² + $y²) / 8);
$png.set: $x, $y, |hsv2rgb($hue/8, 1, 1);
}
}
}

sub hsv2rgb ( $h, $s, $v ){
my $c = $v * $s;
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
my $m = $v - $c;
(do given $h {
when 0..^1/6 { $c, $x, 0 }
when 1/6..^1/3 { $x, $c, 0 }
when 1/3..^1/2 { 0, $c, $x }
when 1/2..^2/3 { 0, $x, $c }
when 2/3..^5/6 { $x, 0, $c }
when 5/6..1 { $c, 0, $x }
} ).map: ((*+$m) * 255).Int
}</lang>


=={{header|Phix}}==
=={{header|Phix}}==
{{libheader|Phix/pGUI}}
{{trans|JavaScript}}
{{trans|JavaScript}}
<syntaxhighlight lang="phix">-- demo\rosetta\plasma.exw
<lang Phix>--
-- demo\rosetta\plasma.exw
--
include pGUI.e
include pGUI.e


Line 1,307: Line 1,740:
dlg = IupDialog(canvas)
dlg = IupDialog(canvas)
IupSetAttribute(dlg, "TITLE", "Plasma")
IupSetAttribute(dlg, "TITLE", "Plasma")
IupCloseOnEscape(dlg)


IupShow(dlg)
IupShow(dlg)
Line 1,316: Line 1,748:
end procedure
end procedure


main()</lang>
main()</syntaxhighlight>
And here's a simple console ditty, similar I think to C's ASCII version for Windows, though this also works on Linux:
And here's a simple console ditty, similar I think to C's ASCII version for Windows, though this also works on Linux:
<lang Phix>sequence s = video_config()
<syntaxhighlight lang="phix">sequence s = video_config()
for i=1 to s[VC_SCRNLINES]*s[VC_SCRNCOLS]-1 do
for i=1 to s[VC_SCRNLINES]*s[VC_SCRNCOLS]-1 do
bk_color(rand(16)-1)
bk_color(rand(16)-1)
Line 1,324: Line 1,756:
puts(1,"\xDF")
puts(1,"\xDF")
end for
end for
{} = wait_key()</lang>
{} = wait_key()</syntaxhighlight>

=={{header|Processing}}==
<syntaxhighlight lang="java">/**
Plasmas with Palette Looping
https://lodev.org/cgtutor/plasma.html#Plasmas_with_Palette_Looping_
*/

int pal[] = new int[128];
int[] buffer;
float r = 42, g = 84, b = 126;
boolean rd, gd, bd;

void setup() {
size(600, 600);
frameRate(25);
buffer = new int[width*height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
buffer[x+y*width] = int(((128+(128*sin(x/32.0)))
+(128+(128*cos(y/32.0)))
+(128+(128*sin(sqrt((x*x+y*y))/32.0))))/4);
}
}
}

void draw() {
if (r > 128) rd = true;
if (!rd) r++;
else r--;
if (r < 0) rd = false;
if (g > 128) gd = true;
if (!gd) g++;
else g--;
if (r < 0) gd = false;
if (b > 128) bd = true;
if (!bd) b++;
else b--;
if (b < 0){ bd = false;}
float s_1, s_2;
for (int i = 0; i < 128; i++) {
s_1 = sin(i*PI/25);
s_2 = sin(i*PI/50+PI/4);
pal[i] = color(r+s_1*128, g+s_2*128, b+s_1*128);
}
loadPixels();
for (int i = 0; i < buffer.length; i++) {
pixels[i] = pal[(buffer[i]+frameCount)&127];
}
updatePixels();
}</syntaxhighlight>

'''It can be played on line''' :<BR> [https://www.openprocessing.org/sketch/873932/ here.]

==={{header|Processing Python mode}}===

<syntaxhighlight lang="python">"""
Plasmas with Palette Looping
https://lodev.org/cgtutor/plasma.html#Plasmas_with_Palette_Looping_
"""

pal = [0] * 128
r = 42
g = 84
b = 126
rd = gd = bd = False

def setup():
global buffer
size(600, 600)
frameRate(25)
buffer = [None] * width * height
for x in range(width):
for y in range(width):
value = int(((128 + (128 * sin(x / 32.0)))
+ (128 + (128 * cos(y / 32.0)))
+ (128 + (128 * sin(sqrt((x * x + y * y)) / 32.0)))) / 4)
buffer[x + y * width] = value

def draw():
global r, g, b, rd, gd, bd
if r > 128: rd = True
if not rd: r += 1
else: r-=1
if r < 0: rd = False
if g > 128: gd = True
if not gd: g += 1
else: g- = 1
if r < 0: gd = False
if b > 128: bd = True
if not bd: b += 1
else: b- = 1
if b < 0: bd = False
for i in range(128):
s_1 = sin(i * PI / 25)
s_2 = sin(i * PI / 50 + PI / 4)
pal[i] = color(r + s_1 * 128, g + s_2 * 128, b + s_1 * 128)

loadPixels()
for i, b in enumerate(buffer):
pixels[i] = pal[(b + frameCount) % 127]
updatePixels()
</syntaxhighlight>


=={{header|Python}}==
=={{header|Python}}==
{{trans|Perl 6}}
{{trans|Raku}}


<lang python>import math
<syntaxhighlight lang="python">import math
import colorsys
import colorsys
from PIL import Image
from PIL import Image
Line 1,346: Line 1,881:
if __name__=="__main__":
if __name__=="__main__":
im = plasma(400, 400)
im = plasma(400, 400)
im.show()</lang>
im.show()</syntaxhighlight>

=={{header|Racket}}==

Uses `return-color-by-pos` from [[#Lisp]], because it was almost lift and shift

<syntaxhighlight lang="racket">#lang racket
;; from lisp (cos I could just lift the code)
(require images/flomap
2htdp/universe
racket/flonum)

;; copied from pythagoras-triangle#racket
(define (real-remainder x q) (- x (* (floor (/ x q)) q)))

(define (HSV->RGB H S V)
(define C (* V S)) ; chroma
(define H′ (/ H 60))
(define X (* C (- 1 (abs (- (real-remainder H′ 2) 1)))))
(define-values (R1 G1 B1)
(cond
[(< H′ 1) (values C X 0.)]
[(< H′ 2) (values X C 0.)]
[(< H′ 3) (values 0. C X)]
[(< H′ 4) (values 0. X C)]
[(< H′ 5) (values X 0. C)]
[(< H′ 6) (values C 0. X)]
[else (values 0. 0. 0.)]))
(define m (- V C))
(values (+ R1 m) (+ G1 m) (+ B1 m)))


(define ((colour-component-by-pos ϕ) k x y)
(let ((rv
(/ (+ (+ 1/2 (* 1/2 (sin (+ ϕ (/ x 16.0)))))
(+ 1/2 (* 1/2 (sin (+ ϕ (/ y 8.0)))))
(+ 1/2 (* 1/2 (sin (+ ϕ (/ (+ x y) 16.0)))))
(+ 1/2 (* 1/2 (sin (+ ϕ (/ (sqrt (+ (sqr x) (sqr y))) 8.0))))))
4.0)))
rv))

(define ((plasma-flomap (ϕ 0)) w h)
(build-flomap 1 w h (colour-component-by-pos ϕ)))

(define ((plasma-image (ϕ 0)) w h)
(flomap->bitmap ((plasma-flomap ϕ) w h)))

(define ((colour-plasma plsm) t)
(let ((w (flomap-width plsm))
(h (flomap-height plsm)))
(flomap->bitmap
(build-flomap* 3 w h
(λ (x y)
(define-values (r g b)
(HSV->RGB (real-remainder
(+ (* t 5.)
(* 360 (flomap-ref plsm 0 x y)))
360.) 1. 1.))
(flvector r g b))))))

;((plasma-image) 200 200)

;((plasma-image (/ pi 32)) 200 200)

(define plsm ((plasma-flomap) 300 300))
(animate (λ (t)
((colour-plasma plsm) t)))</syntaxhighlight>

=={{header|Raku}}==
(formerly Perl 6)
[[File:Plasma-perl6.png|200px|thumb|right]]
{{works with|Rakudo|2018.09}}
<syntaxhighlight lang="raku" line>use Image::PNG::Portable;

my ($w, $h) = 400, 400;
my $out = Image::PNG::Portable.new: :width($w), :height($h);

plasma($out);

$out.write: 'Plasma-perl6.png';

sub plasma ($png) {
(^$w).race.map: -> $x {
for ^$h -> $y {
my $hue = 4 + sin($x / 19) + sin($y / 9) + sin(($x + $y) / 25) + sin(sqrt($x² + $y²) / 8);
$png.set: $x, $y, |hsv2rgb($hue/8, 1, 1);
}
}
}

sub hsv2rgb ( $h, $s, $v ){
my $c = $v * $s;
my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
my $m = $v - $c;
(do given $h {
when 0..^1/6 { $c, $x, 0 }
when 1/6..^1/3 { $x, $c, 0 }
when 1/3..^1/2 { 0, $c, $x }
when 1/2..^2/3 { 0, $x, $c }
when 2/3..^5/6 { $x, 0, $c }
when 5/6..1 { $c, 0, $x }
} ).map: ((*+$m) * 255).Int
}</syntaxhighlight>


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Project : Plasma effect
# Project : Plasma effect


Line 1,421: Line 2,058:
d = sqrt(((a - c) * (a - c) + (b - d) * (b - d)))
d = sqrt(((a - c) * (a - c) + (b - d) * (b - d)))
return d
return d
</syntaxhighlight>
</lang>
Output:
Output:


[http://www.dropbox.com/s/gdioouv328m2d60/PlasmaEffect.jpg?dl=0 Plasma effect]
[http://www.dropbox.com/s/gdioouv328m2d60/PlasmaEffect.jpg?dl=0 Plasma effect]


=={{header|Ruby}}==
{{libheader|RubyGems}}
{{libheader|JRubyArt}}
JRubyArt is a port of Processing to the ruby language
<syntaxhighlight lang="ruby">
attr_reader :buffer, :palette, :r, :g, :b, :rd, :gd, :bd, :dim

def settings
size(600, 600)
end

def setup
sketch_title 'Plasma Effect'
frame_rate 25
@r = 42
@g = 84
@b = 126
@rd = true
@gd = true
@bd = true
@dim = width * height
@buffer = Array.new(dim)
grid(width, height) do |x, y|
buffer[x + y * width] = (
(
(128 + (128 * sin(x / 32.0))) +
(128 + (128 * cos(y / 32.0))) +
(128 + (128 * sin(Math.hypot(x, y) / 32.0)))
) / 4
).to_i
end
load_pixels
end

def draw
if rd
@r -= 1
@rd = false if r.negative?
else
@r += 1
@rd = true if r > 128
end
if gd
@g -= 1
@gd = false if g.negative?
else
@g += 1
@gd = true if g > 128
end
if bd
@b -= 1
@bd = false if b.negative?
else
@b += 1
@bd = true if b > 128
end
@palette = (0..127).map do |col|
s1 = sin(col * Math::PI / 25)
s2 = sin(col * Math::PI / 50 + Math::PI / 4)
color(r + s1 * 128, g + s2 * 128, b + s1 * 128)
end
dim.times do |idx|
pixels[idx] = palette[(buffer[idx] + frame_count) & 127]
end
update_pixels
end
</syntaxhighlight>

=={{header|Rust}}==
<syntaxhighlight lang="rust">
extern crate image;

use image::ColorType;
use std::path::Path;

// Framebuffer dimensions
const WIDTH: usize = 640;
const HEIGHT: usize = 480;

/// Formula for plasma at any particular address
fn plasma_pixel(x: f64, y: f64) -> f64 {
((x / 16.0).sin()
+ (y / 8.0).sin()
+ ((x + y) / 16.0).sin()
+ ((x * x + y * y).sqrt() / 8.0).sin()
+ 4.0)
/ 8.0
}

/// Precalculate plasma field lookup-table for performance
fn create_plasma_lut() -> Vec<f64> {
let mut plasma: Vec<f64> = vec![0.0; WIDTH * HEIGHT];
for y in 0..HEIGHT {
for x in 0..WIDTH {
plasma[(y * WIDTH) + x] = plasma_pixel(x as f64, y as f64);
}
}
plasma
}

/// Convert from HSV float(1.0,1.0,1.0) to RGB u8 tuple (255,255,255).
/// From https://crates.io/crates/palette 0.5.0 rgb.rs, simplified for example
fn hsv_to_rgb(hue: f64, saturation: f64, value: f64) -> (u8, u8, u8) {
let c = value * saturation;
let h = hue * 6.0;
let x = c * (1.0 - (h % 2.0 - 1.0).abs());
let m = value - c;
let (red, green, blue) = match (h % 6.0).floor() as u32 {
0 => (c, x, 0.0),
1 => (x, c, 0.0),
2 => (0.0, c, x),
3 => (0.0, x, c),
4 => (x, 0.0, c),
_ => (c, 0.0, x),
};
// Convert back to RGB (where components are integers from 0 to 255)
(
((red + m) * 255.0).round() as u8,
((green + m) * 255.0).round() as u8,
((blue + m) * 255.0).round() as u8,
)
}
fn main() {
// The bitmap/framebuffer for our application. 3 u8 elements per output pixel
let mut framebuffer: Vec<u8> = vec![0; WIDTH * HEIGHT * 3];
// Generate a lookup table so we don't do too much math for every pixel.
// Do it in a function so that the local one can be immutable.
let plasma_lookup_table = create_plasma_lut();
// For each (r,g,b) pixel in our output buffer
for (index, rgb) in framebuffer.chunks_mut(3).enumerate() {
// Lookup the precalculated plasma value
let hue_lookup = plasma_lookup_table[index] % 1.0;
let (red, green, blue) = hsv_to_rgb(hue_lookup, 1.0, 1.0);
rgb[0] = red;
rgb[1] = green;
rgb[2] = blue;
}
// Save our plasma image to out.png
let output_path = Path::new("out.png");
match image::save_buffer(
output_path,
framebuffer.as_slice(),
WIDTH as u32,
HEIGHT as u32,
ColorType::RGB(8),
) {
Err(e) => println!("Error writing output image:\n{}", e),
Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
}
}

</syntaxhighlight>


=={{header|Scala}}==
=={{header|Scala}}==
===Java Swing Interoperability===
===Java Swing Interoperability===
<lang Scala>import java.awt._
<syntaxhighlight lang="scala">import java.awt._
import java.awt.event.ActionEvent
import java.awt.event.ActionEvent
import java.awt.image.BufferedImage
import java.awt.image.BufferedImage
Line 1,485: Line 2,276:
})
})


}</lang>
}</syntaxhighlight>

=={{header|Sidef}}==
=={{header|Sidef}}==
{{trans|Perl 6}}
{{trans|Raku}}
<lang ruby>require('Imager')
<syntaxhighlight lang="ruby">require('Imager')


class Plasma(width=400, height=400) {
class Plasma(width=400, height=400) {
Line 1,512: Line 2,304:
var plasma = Plasma(256, 256)
var plasma = Plasma(256, 256)
plasma.generate
plasma.generate
plasma.save_as('plasma.png')</lang>
plasma.save_as('plasma.png')</syntaxhighlight>
Output image: [https://github.com/trizen/rc/blob/master/img/plasma-effect-sidef.png Plasma effect]
Output image: [https://github.com/trizen/rc/blob/master/img/plasma-effect-sidef.png Plasma effect]

=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|DOME}}
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color, ImageData
import "dome" for Window
import "math" for Math

class PlasmaEffect {
construct new(width, height) {
Window.title = "Plasma Effect"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
_bmp = ImageData.create("plasma_effect", _w, _h)
_plasma = createPlasma() // stores the hues for the colors
}

init() {
_frame = 0
_hueShift = 0
Canvas.cls(Color.white)
}

createPlasma() {
var buffer = List.filled(_w, null)
for (x in 0..._w) {
buffer[x] = List.filled(_h, 0)
for (y in 0..._h) {
var value = Math.sin(x / 16)
value = value + Math.sin(y / 8)
value = value + Math.sin((x + y) / 16)
value = value + Math.sin((x * x + y * y).sqrt / 8)
value = value + 4 // shift range from -4 .. 4 to 0 .. 8
value = value / 8 // bring range down to 0 .. 1
if (value < 0 || value > 1) Fiber.abort("Hue value out of bounds")
buffer[x][y] = value
pset(x, y, Color.hsv(value * 360, 1, 1))
}
}
return buffer
}

pset(x, y, col) { _bmp.pset(x, y, col) }

pget(x, y) { _bmp.pget(x, y) }

update() {
_frame = _frame + 1
if (_frame % 3 == 0) { // update every 3 frames or 1/20th second
_hueShift = (_hueShift + 0.02) % 1
}
}

draw(alpha) {
for (x in 0..._w) {
for (y in 0..._h) {
var hue = (_hueShift + _plasma[x][y]) % 1
var col = Color.hsv(hue * 360, 1, 1)
pset(x, y, col)
}
}
_bmp.draw(0, 0)
}
}

var Game = PlasmaEffect.new(640, 640)</syntaxhighlight>

=={{header|XPL0}}==
Translation of Lode's RGB plasma, provided by link at the top of this page.
<syntaxhighlight lang="xpl0">func real Dist(X1, Y1, X2, Y2);
int X1, Y1, X2, Y2;
return sqrt( float((X1-X2)*(X1-X2) + (Y1-Y2)*(Y1-Y2)) );

int Time, X, Y, Color;
real Value;
[SetVid($112); \640x480x24
repeat Time:= GetTime/50_000;
for Y:= 0 to 256-1 do
for X:= 0 to 256-1 do
[Value:= Sin(Dist(X+Time, Y, 128, 128) / 8.0) +
Sin(Dist(X, Y, 64, 64) / 8.0) +
Sin(Dist(X, Y+Time/7, 192, 64) / 7.0) +
Sin(Dist(X, Y, 192, 100) / 8.0);
Color:= fix((4.0+Value) * 31.875); \[0..255]
Point(X, Y, Color<<16 + ((Color*2)&$FF)<<8 + (255-Color));
];
until KeyHit;
]</syntaxhighlight>

Latest revision as of 12:09, 25 January 2024

Task
Plasma effect
You are encouraged to solve this task according to the task description, using any language you may know.

The plasma effect is a visual effect created by applying various functions, notably sine and cosine, to the color values of screen pixels. When animated (not a task requirement) the effect may give the impression of a colorful flowing liquid.


Task

Create a plasma effect.

See also



AWK

#!/usr/bin/awk -f

function clamp(val, a, b) { return (val<a) ? a : (val>b) ? b : val }

## return a timestamp with centisecond precision
function timex() {
  getline < "/proc/uptime"
  close("/proc/uptime")
  return $1
}

## draw image to terminal
function draw(src, xpos, ypos,    w,h, x,y, up,dn, line,screen) {
  w = src["width"]
  h = src["height"]

  for (y=0; y<h; y+=2) {
    line = sprintf("\033[%0d;%0dH", y/2+ypos+1, xpos+1)
    for (x=0; x<w; x++) {
      up = src[x,y+0]
      dn = src[x,y+1]
      line = line "\033[38;2;" palette[up] ";48;2;" palette[dn] "m▀"
    }
    screen = screen line "\033[0m"
  }
  printf("%s", screen)
}

## generate a palette
function paletteGen(    i, r,g,b) {
  # generate palette
  for (i=0; i<256; i++) {
    r = 128 + 128 * sin(3.14159265 * i / 32.0)
    g = 128 + 128 * sin(3.14159265 * i / 64.0)
    b = 128 + 128 * sin(3.14159265 * i / 128.0)
    palette[i] = sprintf("%d;%d;%d", clamp(r,0,255), clamp(g,0,255), clamp(b,0,255))
  }
}

## generate a plasma
function plasmaGen(plasma, w, h,    x,y, color) {
  for (y=0; y<h; y++) {
    for (x=0; x<w; x++) {
      color = ( \
          128.0 + (128.0 * sin((x / 8.0) - cos(now/2) )) \
        + 128.0 + (128.0 * sin((y / 16.0) - sin(now)*2 )) \
        + 128.0 + (128.0 * sin(sqrt((x - w / 2.0) * (x - w / 2.0) + (y - h / 2.0) * (y - h / 2.0)) / 4.0)) \
        + 128.0 + (128.0 * sin((sqrt(x * x + y * y) / 4.0) - sin(now/4) )) \
      ) / 4;

      plasma[x,y] = int(color)
    }
  }
}

BEGIN {
  "stty size" | getline
  buffer["height"] = h = ($1 ? $1 : 24) * 2
  buffer["width"]  = w = ($2 ? $2 : 80)

  paletteGen()
  start = timex()

  while (elapsed < 30) {
    elapsed = (now = timex()) - start

    plasmaGen(plasma, w, h)

    # copy plasma to buffer
    for (y=0; y<h; y++)
      for (x=0; x<w; x++)
        buffer[x,y] = int(plasma[x,y] + now * 100) % 256

    # draw buffer to terminal
    draw(buffer)
  }

  printf("\n")
}

C

ASCII version for Windows

If you don't want to bother with Graphics libraries, try out this nifty implementation on Windows :

#include<windows.h>
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#include<math.h>

#define pi M_PI

int main()
{
	CONSOLE_SCREEN_BUFFER_INFO info;
    int cols, rows;
	time_t t;
	int i,j;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
    cols = info.srWindow.Right - info.srWindow.Left + 1;
    rows = info.srWindow.Bottom - info.srWindow.Top + 1;
	
	HANDLE console;
	
	console = GetStdHandle(STD_OUTPUT_HANDLE);
	
	system("@clear||cls");
	
	srand((unsigned)time(&t));
	
	for(i=0;i<rows;i++)
		for(j=0;j<cols;j++){
			SetConsoleTextAttribute(console,fabs(sin(pi*(rand()%254 + 1)/255.0))*254);
			printf("%c",219);
		}
		
	getchar();
	
	return 0;
}

Graphics version

And here's the Graphics version, requires the WinBGIm library. Prints out usage on incorrect invocation.

#include<graphics.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

#define pi M_PI

void plasmaScreen(int width,int height){
	
	int x,y,sec;
	double dx,dy,dv;
	time_t t;
	
	initwindow(width,height,"WinBGIm Plasma");
	
	while(1){
		time(&t);
		sec = (localtime(&t))->tm_sec;
		
	for(x=0;x<width;x++)
		for(y=0;y<height;y++){
			dx = x + .5 * sin(sec/5.0);
			dy = y + .5 * cos(sec/3.0);
			
			dv = sin(x*10 + sec) + sin(10*(x*sin(sec/2.0) + y*cos(sec/3.0)) + sec) + sin(sqrt(100*(dx*dx + dy*dy)+1) + sec);
			
			setcolor(COLOR(255*fabs(sin(dv*pi)),255*fabs(sin(dv*pi + 2*pi/3)),255*fabs(sin(dv*pi + 4*pi/3))));
			
			putpixel(x,y,getcolor());
		}
	delay(1000);
	}
}

int main(int argC,char* argV[])
{
	if(argC != 3)
		printf("Usage : %s <Two positive integers separated by a space specifying screen size>",argV[0]);
	else{
		plasmaScreen(atoi(argV[1]),atoi(argV[2]));
	}
	return 0;
}

C++

Version 1 (windows.h)

Windows version.

#include <windows.h>
#include <math.h>
#include <string>

const int BMP_SIZE = 240, MY_TIMER = 987654;

class myBitmap {
public:
    myBitmap() : pen( NULL ), brush( NULL ), clr( 0 ), wid( 1 ) {}
    ~myBitmap() {
        DeleteObject( pen ); DeleteObject( brush );
        DeleteDC( hdc ); DeleteObject( bmp );
    }
    bool create( int w, int h ) {
        BITMAPINFO bi;
        ZeroMemory( &bi, sizeof( bi ) );
        bi.bmiHeader.biSize        = sizeof( bi.bmiHeader );
        bi.bmiHeader.biBitCount    = sizeof( DWORD ) * 8;
        bi.bmiHeader.biCompression = BI_RGB;
        bi.bmiHeader.biPlanes      = 1;
        bi.bmiHeader.biWidth       =  w;
        bi.bmiHeader.biHeight      = -h;

        HDC dc = GetDC( GetConsoleWindow() );
        bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
        if( !bmp ) return false;

        hdc = CreateCompatibleDC( dc );
        SelectObject( hdc, bmp );
        ReleaseDC( GetConsoleWindow(), dc );

        width = w; height = h;
        return true;
    }
    void clear( BYTE clr = 0 ) {
        memset( pBits, clr, width * height * sizeof( DWORD ) );
    }
    void setBrushColor( DWORD bClr ) {
        if( brush ) DeleteObject( brush );
        brush = CreateSolidBrush( bClr );
        SelectObject( hdc, brush );
    }
    void setPenColor( DWORD c ) {
        clr = c; createPen();
    }
    void setPenWidth( int w ) {
        wid = w; createPen();
    }
    void saveBitmap( std::string path ) {
        BITMAPFILEHEADER fileheader;
        BITMAPINFO       infoheader;
        BITMAP           bitmap;
        DWORD            wb;

        GetObject( bmp, sizeof( bitmap ), &bitmap );
        DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];

        ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
        ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
        ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );

        infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
        infoheader.bmiHeader.biCompression = BI_RGB;
        infoheader.bmiHeader.biPlanes = 1;
        infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
        infoheader.bmiHeader.biHeight = bitmap.bmHeight;
        infoheader.bmiHeader.biWidth = bitmap.bmWidth;
        infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );

        fileheader.bfType    = 0x4D42;
        fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
        fileheader.bfSize    = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;

        GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );

        HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
        WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
        WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
        WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
        CloseHandle( file );

        delete [] dwpBits;
    }
    HDC getDC() const     { return hdc; }
    DWORD* bits()          { return ( DWORD* )pBits; }
private:
    void createPen() {
        if( pen ) DeleteObject( pen );
        pen = CreatePen( PS_SOLID, wid, clr );
        SelectObject( hdc, pen );
    }
    HBITMAP bmp; HDC    hdc;
    HPEN    pen; HBRUSH brush;
    void    *pBits; int width, height, wid;
    DWORD    clr;
};
class plasma
{
public:
    plasma() {
        currentTime = 0; _WD = BMP_SIZE >> 1; _WV = BMP_SIZE << 1;
        _bmp.create( BMP_SIZE, BMP_SIZE ); _bmp.clear();
        plasma1 = new BYTE[BMP_SIZE * BMP_SIZE * 4];
        plasma2 = new BYTE[BMP_SIZE * BMP_SIZE * 4];
        int i, j, dst = 0;
        double temp;
        for( j = 0; j < BMP_SIZE * 2; j++ ) {
            for( i = 0; i < BMP_SIZE * 2; i++ ) {
                plasma1[dst] = ( BYTE )( 128.0 + 127.0 * ( cos( ( double )hypot( BMP_SIZE - j, BMP_SIZE - i ) / 64.0 ) ) );
                plasma2[dst] = ( BYTE )( ( sin( ( sqrt( 128.0 + ( BMP_SIZE - i ) * ( BMP_SIZE - i ) + 
                               ( BMP_SIZE - j ) * ( BMP_SIZE - j ) ) - 4.0 ) / 32.0 ) + 1 ) * 90.0 );
                dst++;
            }
        }
    }
    void update() {
        DWORD dst;
        BYTE a, c1,c2, c3;
        currentTime += ( double )( rand() % 2 + 1 );

        int x1 = _WD + ( int )( ( _WD - 1 ) * sin( currentTime  / 137 ) ),
            x2 = _WD + ( int )( ( _WD - 1 ) * sin( -currentTime /  75 ) ),
            x3 = _WD + ( int )( ( _WD - 1 ) * sin( -currentTime / 125 ) ),
            y1 = _WD + ( int )( ( _WD - 1 ) * cos( currentTime  / 123 ) ),
            y2 = _WD + ( int )( ( _WD - 1 ) * cos( -currentTime /  85 ) ),
            y3 = _WD + ( int )( ( _WD - 1 ) * cos( -currentTime / 108 ) );

        int src1 = y1 * _WV + x1, src2 = y2 * _WV + x2, src3 = y3 * _WV + x3;
        
        DWORD* bits = _bmp.bits();
        for( int j = 0; j < BMP_SIZE; j++ ) {
            dst = j * BMP_SIZE;
            for( int i= 0; i < BMP_SIZE; i++ ) {
                a = plasma2[src1] + plasma1[src2] + plasma2[src3];
                c1 = a << 1; c2 = a << 2; c3 = a << 3;
                bits[dst + i] = RGB( c1, c2, c3 );
                src1++; src2++; src3++;
            }
            src1 += BMP_SIZE; src2 += BMP_SIZE; src3 += BMP_SIZE;
        }
        draw();
    }
    void setHWND( HWND hwnd ) { _hwnd = hwnd; }
private:
    void draw() {
        HDC dc = _bmp.getDC(), wdc = GetDC( _hwnd );
        BitBlt( wdc, 0, 0, BMP_SIZE, BMP_SIZE, dc, 0, 0, SRCCOPY );
        ReleaseDC( _hwnd, wdc );
    }
    myBitmap _bmp; HWND _hwnd; float _ang;
    BYTE *plasma1, *plasma2;
    double currentTime; int _WD, _WV;
};
class wnd
{
public:
    wnd() { _inst = this; }
    int wnd::Run( HINSTANCE hInst ) {
        _hInst = hInst; _hwnd = InitAll();
        SetTimer( _hwnd, MY_TIMER, 15, NULL );
        _plasma.setHWND( _hwnd );
        ShowWindow( _hwnd, SW_SHOW );
        UpdateWindow( _hwnd );
        MSG msg;
        ZeroMemory( &msg, sizeof( msg ) );
        while( msg.message != WM_QUIT ) {
            if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) != 0 ) {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
        }
        return UnregisterClass( "_MY_PLASMA_", _hInst );
    }
private:
    void wnd::doPaint( HDC dc ) { _plasma.update(); }
    void wnd::doTimer()         { _plasma.update(); }
    static int WINAPI wnd::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) {
        switch( msg ) {
            case WM_PAINT: {
                    PAINTSTRUCT ps;
                    _inst->doPaint( BeginPaint( hWnd, &ps ) );
                    EndPaint( hWnd, &ps );
                    return 0;
                }
            case WM_DESTROY: PostQuitMessage( 0 ); break;
            case WM_TIMER: _inst->doTimer(); break;
            default: return DefWindowProc( hWnd, msg, wParam, lParam );
        }
        return 0;
    }
    HWND InitAll() {
        WNDCLASSEX wcex;
        ZeroMemory( &wcex, sizeof( wcex ) );
        wcex.cbSize        = sizeof( WNDCLASSEX );
        wcex.style         = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc   = ( WNDPROC )WndProc;
        wcex.hInstance     = _hInst;
        wcex.hCursor       = LoadCursor( NULL, IDC_ARROW );
        wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
        wcex.lpszClassName = "_MY_PLASMA_";

        RegisterClassEx( &wcex );

        RECT rc = { 0, 0, BMP_SIZE, BMP_SIZE };
        AdjustWindowRect( &rc, WS_SYSMENU | WS_CAPTION, FALSE );
        int w = rc.right - rc.left, h = rc.bottom - rc.top;
        return CreateWindow( "_MY_PLASMA_", ".: Plasma -- PJorente :.", WS_SYSMENU, CW_USEDEFAULT, 0, w, h, NULL, NULL, _hInst, NULL );
    }
    static wnd* _inst; HINSTANCE _hInst; HWND _hwnd; plasma _plasma;
};
wnd* wnd::_inst = 0;
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) {
    wnd myWnd;
    return myWnd.Run( hInstance );
}

Version 2 (SDL2)

Library: SDL2
Take that, Paulo Jorente!

Version 2.1

// Standard C++ stuff
#include <iostream>
#include <array>
#include <cmath>
#include <numbers>

// SDL2 stuff
#include "SDL2/SDL.h"

// Compile: g++ -std=c++20 -Wall -Wextra -pedantic -Ofast SDL2Plasma.cpp -o SDL2Plasma -lSDL2 -fopenmp

struct RGB {
    int Red, Green, Blue;
};

RGB HSBToRGB(const double hue, const double saturation, const double brightness) {
    double Red   = 0,
           Green = 0,
           Blue  = 0;
    
    if (hue == 1) {
        Red = brightness;
    } else {
        double Sector = hue * 360,
               Cosine = std::cos(Sector*std::numbers::pi/180),
               Sine   = std::sin(Sector*std::numbers::pi/180);
        
        Red   = brightness * Cosine + saturation * Sine;
        Green = brightness * Cosine - saturation * Sine;
        Blue  = brightness - saturation * Cosine;
    }
    
    RGB Result;
    Result.Red   = (int)(Red * 255);
    Result.Green = (int)(Green * 255);
    Result.Blue  = (int)(Blue * 255);
    
    return Result;
}

template <int width_array_length, int height_array_length>
void CalculatePlasma(std::array<std::array<double, width_array_length>, height_array_length> &array) {
    #pragma omp parallel for
    for (unsigned long y = 0; y < array.size(); y++)
        #pragma omp simd
        for (unsigned long x = 0; x < array.at(0).size(); x++) {
            // Calculate the hue
            double Hue = std::sin(x/16.0);
            Hue += std::sin(y/8.0);
            Hue += std::sin((x+y)/16.0);
            Hue += std::sin(std::sqrt(x*x+y*y)/8.0);
            Hue += 4;
            // Clamp the hue to the range of [0, 1]
            Hue /= 8;
            array[y][x] = Hue;
        }
}

template <int width_array_length, int height_array_length>
void DrawPlasma(SDL_Renderer *r, const std::array<std::array<double, width_array_length>, height_array_length> &array, const double &hue_shift) {
    for (unsigned long y = 0; y < array.size(); y++)
        for (unsigned long x = 0; x < array.at(0).size(); x++) {
            // Convert the HSB value to RGB value
            double Hue = hue_shift + std::fmod(array[y][x], 1);
            RGB CurrentColour = HSBToRGB(Hue, 1, 1);
            // Draw the actual plasma
            SDL_SetRenderDrawColor(r, CurrentColour.Red, CurrentColour.Green, CurrentColour.Blue, 0xff);
            SDL_RenderDrawPoint(r, x, y);
        }
}

int main() {
    const unsigned DefaultWidth  = 640,
                   DefaultHeight = 640;
    std::array<std::array<double, DefaultWidth>, DefaultHeight> ScreenArray;
    
    SDL_Window *Window = NULL;     // Define window
    SDL_Renderer *Renderer = NULL; // Define renderer
    
    // Init everything just for sure
    SDL_Init(SDL_INIT_EVERYTHING);
    
    // Set window size to 640x640, always shown
    Window = SDL_CreateWindow("Plasma effect", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, SDL_WINDOW_SHOWN);
    Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
    
    // Set background colour to white
    SDL_SetRenderDrawColor(Renderer, 0xff, 0xff, 0xff, 0xff);
    SDL_RenderClear(Renderer);
    
    // Create an event handler and a "quit" flag
    SDL_Event e;
    bool KillWindow = false;
    
    CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
    double HueShift = 0.0;
    
    // The window runs until the "quit" flag is set to true
    while (!KillWindow) {
        while (SDL_PollEvent(&e) != 0) {
            // Go through the events in the queue
            switch (e.type) {
                // Event: user hits a key
                case SDL_QUIT: case SDL_KEYDOWN:
                    // Destroy window
                    KillWindow = true;
                    break;
            }
        }
        // Render the plasma
        DrawPlasma<DefaultWidth, DefaultHeight>(Renderer, ScreenArray, HueShift);
        SDL_RenderPresent(Renderer);
        
        if (HueShift < 1) {
            HueShift = std::fmod(HueShift + 0.0025, 3);
        } else {
            CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
            HueShift = 0.0;
        }
    }
    
    // Destroy renderer and window
    SDL_DestroyRenderer(Renderer);
    SDL_DestroyWindow(Window);
    SDL_Quit();
    
    return 0;
}
Output:

Version 2.2

// Standard C++ stuff
#include <iostream>
#include <array>
#include <cmath>
#include <numbers>

// SDL2 stuff
#include "SDL2/SDL.h"

// Compile: g++ -std=c++20 -Wall -Wextra -pedantic -Ofast SDL2Plasma.cpp -o SDL2Plasma -lSDL2 -fopenmp

struct RGB {
    int Red, Green, Blue;
};

RGB HSBToRGB(const float hue, const float saturation, const float brightness) {
    float Red   = 0,
          Green = 0,
          Blue  = 0;
    
    if (hue == 1) {
        Red = brightness;
    } else {
        float Sector = hue * 360,
              Cosine = std::cos(Sector*std::numbers::pi/180),
              Sine   = std::sin(Sector*std::numbers::pi/180);
        
        Red   = brightness * Cosine + saturation * Sine;
        Green = brightness * Cosine - saturation * Sine;
        Blue  = brightness - saturation * Cosine;
    }
    
    RGB Result;
    Result.Red   = (int)(Red * 255);
    Result.Green = (int)(Green * 255);
    Result.Blue  = (int)(Blue * 255);
    
    return Result;
}

template <int width_array_length, int height_array_length>
void CalculatePlasma(std::array<std::array<float, width_array_length>, height_array_length> &array) {
    #pragma omp parallel for
    for (unsigned long y = 0; y < array.size(); y++)
        #pragma omp simd
        for (unsigned long x = 0; x < array.at(0).size(); x++) {
            // Calculate the hue
            float Hue = std::sin(x/16.0);
            Hue += std::sin(y/8.0);
            Hue += std::sin((x+y)/16.0);
            Hue += std::sin(std::sqrt(x*x+y*y)/8.0);
            Hue += 4;
            // Clamp the hue to the range of [0, 1]
            Hue /= 8;
            array[y][x] = Hue;
        }
}

template <int width_array_length, int height_array_length>
void DrawPlasma(SDL_Renderer *r, SDL_Texture *t, const std::array<std::array<float, width_array_length>, height_array_length> &array, const float &hue_shift) {
    unsigned char *Bytes = NULL;
    int Pitch = 0;
    float Hue;
    
    // Lock the texture
    SDL_LockTexture(t, NULL, (void**)&Bytes, &Pitch);
    
    for (unsigned long y = 0; y < array.size(); y++)
        for (unsigned long x = 0; x < array.at(0).size(); x++) {
            // Convert the HSB value to RGB value
            Hue = hue_shift + std::fmod(array[y][x], 1);
            RGB CurrentColour = HSBToRGB(Hue, 1, 1);
            
            // Write colour data directly to texture
            Bytes[y*Pitch+x*4]   = CurrentColour.Red;   // Red
            Bytes[y*Pitch+x*4+1] = CurrentColour.Green; // Green
            Bytes[y*Pitch+x*4+2] = CurrentColour.Blue;  // Blue
            Bytes[y*Pitch+x*4+3] = 0xff;                // Alpha
        }
    
    // Unlock the texture
    SDL_UnlockTexture(t);
    
    // Feed the finished texture to the renderer
    SDL_RenderCopy(r, t, NULL, NULL);
}

int main() {
    const unsigned DefaultWidth  = 640,
                   DefaultHeight = 640;
    std::array<std::array<float, DefaultWidth>, DefaultHeight> ScreenArray;
    
    SDL_Window *Window = NULL;     // Define window
    SDL_Renderer *Renderer = NULL; // Define renderer
    
    // Init everything just for sure
    SDL_Init(SDL_INIT_EVERYTHING);
    
    // Set window size to 640x640, always shown
    Window = SDL_CreateWindow("Plasma effect", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, SDL_WINDOW_SHOWN);
    Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
    SDL_Texture *PlasmaTexture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, DefaultWidth, DefaultHeight);
    
    // Set background colour to white
    SDL_SetRenderDrawColor(Renderer, 0xff, 0xff, 0xff, 0xff);
    SDL_RenderClear(Renderer);
    
    // Create an event handler and a "quit" flag
    SDL_Event e;
    bool KillWindow = false;
    
    CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
    float HueShift = 0.0;
    
    // The window runs until the "quit" flag is set to true
    while (!KillWindow) {
        while (SDL_PollEvent(&e) != 0) {
            // Go through the events in the queue
            switch (e.type) {
                // Event: user hits a key
                case SDL_QUIT: case SDL_KEYDOWN:
                    // Destroy window
                    KillWindow = true;
                    break;
            }
        }
        // Render the plasma
        DrawPlasma<DefaultWidth, DefaultHeight>(Renderer, PlasmaTexture, ScreenArray, HueShift);
        SDL_RenderPresent(Renderer);
        
        if (HueShift < 1) {
            HueShift = std::fmod(HueShift + 0.0025, 3);
        } else {
            CalculatePlasma<DefaultWidth, DefaultHeight>(ScreenArray);
            HueShift = 0.0;
        }
    }
    
    // Destroy renderer and window
    SDL_DestroyRenderer(Renderer);
    SDL_DestroyWindow(Window);
    SDL_Quit();
    
    return 0;
}
Output:

Ceylon

Be sure to import javafx.base, javafx.graphics and ceylon.numeric in your module file.

Translation of: Java
import javafx.application {
    Application
}
import javafx.stage {
    Stage
}
import javafx.scene {
    Scene
}
import javafx.scene.layout {
    BorderPane
}
import javafx.scene.image {
    WritableImage,
    ImageView
}
import ceylon.numeric.float {
    sin,
    sqrt,
    remainder
}
import javafx.scene.paint {
    Color
}
import javafx.animation {
    AnimationTimer
}

shared void run() {
    Application.launch(`Plasma`);
}

shared class Plasma() extends Application() {

    function createPlasma(Integer width, Integer height) => [
        for (j in 0:height) [
            for (i in 0:width)
            let (x = i.float, y = j.float)
            ( sin(x / 16.0)
            + sin(y / 8.0)
            + sin((x + y) / 16.0)
            + sin(sqrt(x ^ 2.0 + y ^ 2.0) / 8.0)
            + 4.0 )
            / 8.0
        ]
    ];

    void writeImage(Float[][] plasma, WritableImage img, Float hueShift = 0.0) {
        value writer = img.pixelWriter;
        for(j->row in plasma.indexed) {
            for(i->percent in row.indexed) {
                value hue = remainder(hueShift + percent, 1.0)  * 360.0;
                writer.setColor(i, j, Color.hsb(hue, 1.0, 1.0));
            }
        }
    }

    shared actual void start(Stage primaryStage) {

        value w = 500;
        value h = 500;
        value plasma = createPlasma(w, h);
        value img = WritableImage(w, h);
        writeImage(plasma, img);

        value root = BorderPane();
        root.center = ImageView(img);

        variable value hueShift = 0.0;
        value timer = object extends AnimationTimer() {
            shared actual void handle(Integer now) {
                hueShift = remainder(hueShift + 0.02, 1.0);
                writeImage(plasma, img, hueShift);
            }
        };
        timer.start();

        value scene = Scene(root);
        primaryStage.title = "Plasma";
        primaryStage.setScene(scene);
        primaryStage.sizeToScene();
        primaryStage.show();
    }

}

Common Lisp

Library: simple-rgb

plasma_demo.lisp:

(require :lispbuilder-sdl)
(require :simple-rgb)

(defparameter *palette*
  (let ((palette-aux (make-array 256 :element-type 'fixnum)))
    (dotimes (i 256)
      (let ((color_i (simple-rgb:hsv->rgb (simple-rgb:hsv (/ i 255.0) 1.0 1.0))))
        (setf (aref palette-aux i) (loop :for component :across color_i
                                       :for i :from 0
                                       :sum (ash component (* 8 i))))))
    palette-aux)
  "palette")

(defun value->color (palette palette-shift index)
  (aref palette (mod (+ index palette-shift) (length palette))))

(defun return-color-by-pos (x y &optional w h)
  "returns a color index"
  (floor
   (/ (+ (+ 128.0 (* 128.0 (sin (/ x 16.0))))
         (+ 128.0 (* 128.0 (sin (/ y 8.0))))
         (+ 128.0 (* 128.0 (sin (/ (+ x y) 16.0))))
         (+ 128.0 (* 128.0 (sin (/ (sqrt (+ (* x x) (* y y))) 8.0)))))
      4.0)))

(defun return-color-by-pos-another (x y &optional w h)
  "a different function that returns a color index"
  (floor
   (/ (+ (+ 128.0 (* 128.0 (sin (/ x 16.0))))
         (+ 128.0 (* 128.0 (sin (/ y 32.0))))
         (+ 128.0 (* 128.0 (sin (/ (sqrt (+ (expt (/ (- x w) 2.0) 2) (expt (/ (- y h) 2.0) 2))) 8.0))))
         (+ 128.0 (* 128.0 (sin (/ (sqrt (+ (* x x) (* y y))) 8.0)))))
      4.0)))

(defun plasma-render (surface palette-shift)
  "render plasma"
  (let ((width (sdl:width surface))
        (height (sdl:height surface)))
    (sdl-base::with-pixel (s (sdl:fp surface))
      (dotimes (h height)
        (dotimes (w width)
          (sdl-base::write-pixel s w h (value->color *palette* palette-shift (funcall #'return-color-by-pos-another w h width height)))))))
  surface)

(defun demo/plasma ()
  "main function: shows a window rendering a plasma efect"
  (sdl:with-init ()
    (let ((win (sdl:window 320 240
                           :bpp 24
                           :resizable nil
                           :title-caption "demo/plasma"
                           :icon-caption "demo/plasma")))
      (let ((palette-shift 0))
      (sdl:update-display win)
      (sdl:with-events ()
        (:idle
         (plasma-render win palette-shift)
         (sdl:update-display win)
         (incf palette-shift))
        (:video-expose-event () (sdl:update-display win))
        (:key-down-event (:key key)
                         (when (or
                                (sdl:key= key :sdl-key-escape)
                                (sdl:key= key :sdl-key-q))
                           (sdl:push-quit-event)))
        (:quit-event () t))))))

(demo/plasma)

Delphi

Works with: Delphi version 6.0

This code animates the plasma, which looks very nice. However, there are too many colors to render it properly with an animated GIF. As a result, I've only posted a static image of the plasma.


function PasmaPixel(X,Y,W,H: integer; Offset: double): TColor;
{Return pixel based on X,Y position and the size of the image}
{Offset controls the progression through the plasma for animation}
var A, B, C, Red, Green, Blue: double;
begin
A:=X + Y + Cos(Sin(Offset) * 2) * 100 + Sin(x / 100) * 1000;
B:=Y / H / 0.2 + Offset;
C:=X / W / 0.2;
Red:=abs(Sin(B + Offset) / 2 + C / 2 - B - C + Offset);
Green:=abs(Sin(Red + Sin(A / 1000 + Offset) + Sin(Y / 40 + Offset) + Sin((X + Y) / 100) * 3));
Blue:=abs(sin(Green + Cos(B + C + Green) + Cos(C) + Sin(X / 1000)));
Result := RGB(Round(255*Red), Round(255*Green), Round(255*Blue));
end;


procedure DisplayPlasma(Bmp: TBitmap; Width,Height: integer; Offset: double);
{Draw the plasma pattern on the bitmap progressed according to "Offset"}
var X,Y: integer;
var Scan: pRGBTripleArray;
begin
Bmp.PixelFormat:=pf24Bit;
for Y:=0 to Height-1 do
	begin
	Scan:=Bmp.ScanLine[Y];
	for X:=0 to Width-1 do
		begin
		Scan[X]:=ColorToTriple(PasmaPixel(X,Y,Width,Height,Offset));
		end;
	end;
end;
var Offset: double;


procedure ShowPlasma(Image: TImage);
{Animate 10 seconds of plasma display}
var X,Y: integer;
var I,StartTime,CurTime,StopTime: integer;
const TimeLimit = 10;
begin
{setup stop time based on real-time clock}
StartTime:=GetTickCount;
StopTime:=StartTime + (TimeLimit * 1000);
{Keep display frame until stop time is reached}
for I:=0 to high(integer) do
	begin
	{Display one frame}
	DisplayPlasma(Image.Picture.Bitmap,Image.Width,Image.Height,Offset);
	{Display count-down time}
	CurTime:=GetTickCount;
	Image.Canvas.Brush.Style:=bsClear;
	Image.Canvas.TextOut(5,5,IntToStr((CurTime-StartTime) div 1000)+' '+IntToStr(I));
	Image.Repaint;
	Application.ProcessMessages;
	if Application.Terminated then exit;
	{Exit if timed out}
	if CurTime>StopTime then break;
	Sleep(50);
	{progress animation one step}
	Offset:=Offset+0.1;
	end;
end;
Output:
Elapsed Time: 10.127 Sec.

Forth

Works with: gforth version 0.7.3

Ouputs a PPM file.

: sqrt ( u -- sqrt )            ( Babylonian method                 )
  dup 2/                        ( first square root guess is half   )
  dup 0= if drop exit then      ( sqrt[0]=0, sqrt[1]=1              )
  begin dup >r 2dup / r> + 2/   ( stack: square old-guess new-guess )
  2dup > while                  ( as long as guess is decreasing    )
  nip repeat                    ( forget old-guess and repeat       )
  drop nip ;

: sgn 0< if -1 else 1 then ;
: isin
  256 mod 128 -                 \ full circle is 255 "degrees"
  dup dup sgn * 128 swap - *    \ second order approximation
  negate 32 / ;                 \ amplitude is +/-128

: color-shape 256 mod 6 * 765 - abs 256 - 0 max 255 min ;  \ trapezes
: hue
  dup color-shape .          \ red
  dup 170 + color-shape .    \ green
  85 + color-shape . ;       \ blue

: plasma
  outfile-id >r
  s" plasma.ppm" w/o create-file throw to outfile-id
  s\" P3\n500 500\n255\n" type
  500 0 do
    500 0 do
      i 2 * isin 128 +
      j 4 * isin 128 + +
      i j + isin 2 * 128 + +
      i i * j j * + sqrt 4 * isin 128 + +
      4 /
      hue
      s\" \n" type
    loop
    s\" \n" type
  loop

  outfile-id close-file throw
  r> to outfile-id ;

plasma



FreeBASIC

' version 12-04-2017
' compile with: fbc -s gui
' Computer Graphics Tutorial (lodev.org), last example

#Define dist(a, b, c, d) Sqr(((a - c) * (a - c) + (b - d) * (b - d)))

Const As ULong w = 256
Const As ULong h = 256
ScreenRes w, h, 24
WindowTitle ("Plasma effect")

Dim As ULong x, y
Dim As UByte c
Dim As Double time_, value

Do
    time_ += .99
    ScreenLock
    For x = 0 To w -1
        For y = 0 To h -1
            value = Sin(dist(x + time_, y, 128, 128) / 8) _
            + Sin(dist(x, y, 64, 64) / 8) _
            + Sin(dist(x, y + time_ / 7, 192, 64) / 7) _
            + Sin(dist(x, y, 192, 100) / 8) + 4
            ' c = Int(value) * 32
            c = int(value * 32)
            PSet(x, y), RGB(c, c * 2, 255 - c)
        Next
    Next
    ScreenUnLock
    Sleep 1

    If Inkey <> "" Or Inkey = Chr(255) + "k" Then
        End
    End If

Loop

Go

This uses Go's 'image' packages in its standard library to create an animated GIF.

When played this is broadly similar to the Java entry on which it is based. The whole animation completes in 4 seconds and repeats indefinitely.

Although the .gif works fine in Firefox it might not do so in EOG due to optimizations made during its creation. If so, then the following ImageMagick command should fix it:

  $ convert plasma.gif -coalesce plasma2.gif
  $ eog plasma2.gif
package main

import (
    "image"
    "image/color"
    "image/gif"
    "log"
    "math"
    "os"
)

func setBackgroundColor(img *image.Paletted, w, h int, ci uint8) {
    for x := 0; x < w; x++ {
        for y := 0; y < h; y++ {
            img.SetColorIndex(x, y, ci)
        }
    }
}

func hsb2rgb(hue, sat, bri float64) (r, g, b int) {
    u := int(bri*255 + 0.5)
    if sat == 0 {
        r, g, b = u, u, u
    } else {
        h := (hue - math.Floor(hue)) * 6
        f := h - math.Floor(h)
        p := int(bri*(1-sat)*255 + 0.5)
        q := int(bri*(1-sat*f)*255 + 0.5)
        t := int(bri*(1-sat*(1-f))*255 + 0.5)
        switch int(h) {
        case 0:
            r, g, b = u, t, p
        case 1:
            r, g, b = q, u, p
        case 2:
            r, g, b = p, u, t
        case 3:
            r, g, b = p, q, u
        case 4:
            r, g, b = t, p, u
        case 5:
            r, g, b = u, p, q
        }
    }
    return
}

func main() {
    const degToRad = math.Pi / 180
    const nframes = 100
    const delay = 4 // 40ms
    w, h := 640, 640
    anim := gif.GIF{LoopCount: nframes}
    rect := image.Rect(0, 0, w, h)
    palette := make([]color.Color, nframes+1)
    palette[0] = color.White
    for i := 1; i <= nframes; i++ {
        r, g, b := hsb2rgb(float64(i)/nframes, 1, 1)
        palette[i] = color.RGBA{uint8(r), uint8(g), uint8(b), 255}
    }
    for f := 1; f <= nframes; f++ {
        img := image.NewPaletted(rect, palette)
        setBackgroundColor(img, w, h, 0) // white background
        for y := 0; y < h; y++ {
            for x := 0; x < w; x++ {
                fx, fy := float64(x), float64(y)
                value := math.Sin(fx / 16)
                value += math.Sin(fy / 8)
                value += math.Sin((fx + fy) / 16)
                value += math.Sin(math.Sqrt(fx*fx+fy*fy) / 8)
                value += 4 // shift range from [-4, 4] to [0, 8]
                value /= 8 // bring range down to [0, 1]
                _, rem := math.Modf(value + float64(f)/float64(nframes))
                ci := uint8(nframes*rem) + 1
                img.SetColorIndex(x, y, ci)
            }
        }
        anim.Delay = append(anim.Delay, delay)
        anim.Image = append(anim.Image, img)
    }
    file, err := os.Create("plasma.gif")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close() 
    if err2 := gif.EncodeAll(file, &anim); err != nil {
        log.Fatal(err2)
    }    
}

Gosu

File:Gosu plasma.png
Translation of: Java
uses javax.swing.*
uses java.awt.*
uses java.awt.image.*
uses java.awt.event.ActionEvent
uses java.awt.image.BufferedImage#*
uses java.lang.Math#*

var size = 400
EventQueue.invokeLater(\ -> showPlasma())

function showPlasma() {
  var frame = new JFrame("Plasma") {:Resizable = false, :DefaultCloseOperation = JFrame.EXIT_ON_CLOSE}
  frame.add(new Plasma(), BorderLayout.CENTER)
  frame.pack()
  frame.setLocationRelativeTo(null)
  frame.Visible = true 
}
  
class Plasma extends JPanel  {
  var hueShift: float
  property get plasma: float[][] = createPlasma(size, size)
  property get img: BufferedImage = new BufferedImage(size, size, TYPE_INT_RGB)
  
  construct() {
    PreferredSize = new Dimension(size, size)
    new Timer(50, \ e -> {hueShift+=0.02 repaint()}).start()
  }
  
  private function createPlasma(w: int, h: int): float[][] {
    var buffer = new float[h][w]
    for(y in 0..|h)
      for(x in 0..|w) {
        var value = (sin(x / 16) + sin(y / 8) + sin((x + y) / 16) + sin(sqrt(x * x + y * y) / 8) + 4) / 8
        buffer[y][x] = value as float
      }
    return buffer
  }

  override function paintComponent(g: Graphics) {
    for(y in 0..|plasma.length)
      for(x in 0..|plasma[0].length)
        img.setRGB(x, y, Color.HSBtoRGB(hueShift + plasma[y][x], 1, 1))
    g.drawImage(img, 0, 0, null)
  }
}

J

require 'trig viewmat'
plasma=: 3 :0
  'w h'=. y
  X=. (i. % <:) w
  Y=. (i. % <:) h
  x1=. sin X*16
  y1=. sin Y*32
  xy1=. sin (Y+/X)*16
  xy2=. sin (Y +&.*:/ X)*32
  xy1+xy2+y1+/x1
)
   viewmat plasma 256 256

Java

Works with: Java version 8
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import static java.awt.image.BufferedImage.*;
import static java.lang.Math.*;
import javax.swing.*;

public class PlasmaEffect extends JPanel {
    float[][] plasma;
    float hueShift = 0;
    BufferedImage img;

    public PlasmaEffect() {
        Dimension dim = new Dimension(640, 640);
        setPreferredSize(dim);
        setBackground(Color.white);

        img = new BufferedImage(dim.width, dim.height, TYPE_INT_RGB);
        plasma = createPlasma(dim.height, dim.width);

        // animate about 24 fps and shift hue value with every frame
        new Timer(42, (ActionEvent e) -> {
            hueShift = (hueShift + 0.02f) % 1;
            repaint();
        }).start();
    }

    float[][] createPlasma(int w, int h) {
        float[][] buffer = new float[h][w];

        for (int y = 0; y < h; y++)
            for (int x = 0; x < w; x++) {

                double value = sin(x / 16.0);
                value += sin(y / 8.0);
                value += sin((x + y) / 16.0);
                value += sin(sqrt(x * x + y * y) / 8.0);
                value += 4; // shift range from -4 .. 4 to 0 .. 8
                value /= 8; // bring range down to 0 .. 1

                // requires VM option -ea
                assert (value >= 0.0 && value <= 1.0) : "Hue value out of bounds";

                buffer[y][x] = (float) value;
            }
        return buffer;
    }

    void drawPlasma(Graphics2D g) {
        int h = plasma.length;
        int w = plasma[0].length;
        for (int y = 0; y < h; y++)
            for (int x = 0; x < w; x++) {
                float hue = hueShift + plasma[y][x] % 1;
                img.setRGB(x, y, Color.HSBtoRGB(hue, 1, 1));
            }
        g.drawImage(img, 0, 0, null);
    }

    @Override
    public void paintComponent(Graphics gg) {
        super.paintComponent(gg);
        Graphics2D g = (Graphics2D) gg;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        drawPlasma(g);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setTitle("Plasma Effect");
            f.setResizable(false);
            f.add(new PlasmaEffect(), BorderLayout.CENTER);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

JavaScript

Translation of: Java
<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <style>
        canvas {
            position: absolute;
            top: 50%;
            left: 50%;
            width: 700px;
            height: 500px;
            margin: -250px 0 0 -350px;
        }
        body {
            background-color: navy;
        }
    </style>
</head>
<body>
    <canvas></canvas>
    <script>
        'use strict';
        var canvas = document.querySelector('canvas');
        canvas.width = 700;
        canvas.height = 500;

        var g = canvas.getContext('2d');

        var plasma = createPlasma(canvas.width, canvas.height);
        var hueShift = 0;

        function createPlasma(w, h) {
            var buffer = new Array(h);

            for (var y = 0; y < h; y++) {
                buffer[y] = new Array(w);

                for (var x = 0; x < w; x++) {

                    var value = Math.sin(x / 16.0);
                    value += Math.sin(y / 8.0);
                    value += Math.sin((x + y) / 16.0);
                    value += Math.sin(Math.sqrt(x * x + y * y) / 8.0);
                    value += 4; // shift range from -4 .. 4 to 0 .. 8
                    value /= 8; // bring range down to 0 .. 1

                    buffer[y][x] = value;
                }
            }
            return buffer;
        }

        function drawPlasma(w, h) {
            var img = g.getImageData(0, 0, w, h);

            for (var y = 0; y < h; y++) {

                for (var x = 0; x < w; x++) {

                    var hue = hueShift + plasma[y][x] % 1;
                    var rgb = HSVtoRGB(hue, 1, 1);
                    var pos = (y * w + x) * 4;
                    img.data[pos] = rgb.r;
                    img.data[pos + 1] = rgb.g;
                    img.data[pos + 2] = rgb.b;
                }
            }
            g.putImageData(img, 0, 0);
        }

        /* copied from stackoverflow */
        function HSVtoRGB(h, s, v) {
            var r, g, b, i, f, p, q, t;

            i = Math.floor(h * 6);
            f = h * 6 - i;
            p = v * (1 - s);
            q = v * (1 - f * s);
            t = v * (1 - (1 - f) * s);
            switch (i % 6) {
                case 0: r = v, g = t, b = p; break;
                case 1: r = q, g = v, b = p; break;
                case 2: r = p, g = v, b = t; break;
                case 3: r = p, g = q, b = v; break;
                case 4: r = t, g = p, b = v; break;
                case 5: r = v, g = p, b = q; break;
            }
            return {
                r: Math.round(r * 255),
                g: Math.round(g * 255),
                b: Math.round(b * 255)
            };
        }

        function drawBorder() {
            g.strokeStyle = "white";
            g.lineWidth = 10;
            g.strokeRect(0, 0, canvas.width, canvas.height);
        }

        function animate(lastFrameTime) {
            var time = new Date().getTime();
            var delay = 42;

            if (lastFrameTime + delay < time) {
                hueShift = (hueShift + 0.02) % 1;
                drawPlasma(canvas.width, canvas.height);
                drawBorder();
                lastFrameTime = time;
            }
            
            requestAnimationFrame(function () {
                animate(lastFrameTime);
            });
        }

        g.fillRect(0, 0, canvas.width, canvas.height);
        animate(0);
    </script>

</body>
</html>

Julia

Translation of: Perl
using Luxor, Colors

Drawing(800, 800)

function plasma(wid, hei)
    for x in -wid:wid, y in -hei:hei
        sethue(parse(Colorant, HSV(180 + 45sin(x/19) + 45sin(y/9) +
            45sin((x+y)/25) + 45sin(sqrt(x^2 + y^2)/8), 1, 1)))
        circle(Point(x, y), 1, :fill)
    end
end

@png plasma(800, 800)

Kotlin

Translation of: Java
// version 1.1.2

import java.awt.*
import java.awt.image.BufferedImage
import javax.swing.*

class PlasmaEffect : JPanel() {
    private val plasma: Array<FloatArray>
    private var hueShift = 0.0f
    private val img: BufferedImage

    init {
        val dim = Dimension(640, 640)
        preferredSize = dim
        background = Color.white
        img = BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_RGB)
        plasma = createPlasma(dim.height, dim.width)
        // animate about 24 fps and shift hue value with every frame
        Timer(42) {
            hueShift = (hueShift + 0.02f) % 1
            repaint()
        }.start()
    }

    private fun createPlasma(w: Int, h: Int): Array<FloatArray> {
        val buffer = Array(h) { FloatArray(w) }
        for (y in 0 until h)
            for (x in 0 until w) {
                var value = Math.sin(x / 16.0)
                value += Math.sin(y / 8.0)
                value += Math.sin((x + y) / 16.0)
                value += Math.sin(Math.sqrt((x * x + y * y).toDouble()) / 8.0)
                value += 4.0  // shift range from -4 .. 4 to 0 .. 8
                value /= 8.0  // bring range down to 0 .. 1
                if (value < 0.0 || value > 1.0) throw RuntimeException("Hue value out of bounds")
                buffer[y][x] = value.toFloat()
            }
        return buffer
    }

    private fun drawPlasma(g: Graphics2D) {
        val h = plasma.size
        val w = plasma[0].size
        for (y in 0 until h)
            for (x in 0 until w) {
                val hue = hueShift + plasma[y][x] % 1
                img.setRGB(x, y, Color.HSBtoRGB(hue, 1.0f, 1.0f))
            }
        g.drawImage(img, 0, 0, null)
    }

    override fun paintComponent(gg: Graphics) {
        super.paintComponent(gg)
        val g = gg as Graphics2D
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
        drawPlasma(g);
    }
}

fun main(args: Array<String>) {
    SwingUtilities.invokeLater {
        val f = JFrame()
        f.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        f.title = "Plasma Effect"
        f.isResizable = false
        f.add(PlasmaEffect(), BorderLayout.CENTER)
        f.pack()
        f.setLocationRelativeTo(null)
        f.isVisible = true
    }
}

Lua

Needs LÖVE 2D Engine

Translation of: C++
_ = love.graphics
p1, p2, points = {}, {}, {}

function hypotenuse( a, b )
    return a * a + b * b
end
function love.load()
    size = _.getWidth()
    currentTime, doub, half = 0, size * 2, size / 2
    local b1, b2
  
    for j = 0, size * 2 do
        for i = 0, size * 2 do
            b1 = math.floor( 128 + 127 * ( math.cos( math.sqrt( hypotenuse( size - j , size - i ) ) / 64 ) ) )
            b2 = math.floor( ( math.sin( ( math.sqrt( 128.0 + hypotenuse( size - i, size - j ) ) - 4.0 ) / 32.0 ) + 1 ) * 90 )
            table.insert( p1, b1 ); table.insert( p2, b2 )
        end
    end
end
function love.draw()
    local a, c1, c2, c3, s1, s2, s3
    currentTime = currentTime + math.random( 2 ) * 3
    local x1 = math.floor( half + ( half -  2 ) * math.sin(  currentTime /  47 ) )
    local x2 = math.floor( half + ( half /  7 ) * math.sin( -currentTime / 149 ) )
    local x3 = math.floor( half + ( half -  3 ) * math.sin( -currentTime / 157 ) )
    local y1 = math.floor( half + ( half / 11 ) * math.cos(  currentTime /  71 ) )
    local y2 = math.floor( half + ( half -  5 ) * math.cos( -currentTime / 181 ) )
    local y3 = math.floor( half + ( half / 23 ) * math.cos( -currentTime / 137 ) )
    s1 = y1 * doub + x1; s2 = y2 * doub + x2; s3 = y3 * doub + x3
    for j = 0, size do
        for i = 0, size do
            a = p2[s1] + p1[s2] + p2[s3]
            c1 = a * 2; c2 = a * 4; c3 = a * 8
            table.insert( points, { i, j, c1, c2, c3, 255 } )
            s1 = s1 + 1; s2 = s2 + 1; s3 = s3 + 1;
        end
        s1 = s1 + size; s2 = s2 + size; s3 = s3 + size
    end
    _.points( points ) 
end

Mathematica / Wolfram Language

s = 400;
Image@Table[
  hue = Sin[i/16] + Sin[j/8] + Sin[(i + j)/16] + Sin[Sqrt[i^2 + j^2]/8];
  hue = (hue + 4)/8;
  Hue[hue, 1, 0.75]
  ,
  {i, 1.0, s},
  {j, 1.0, s}
  ]
Output:

Outputs an image.

Nim

Library: imageman
import math
import imageman

const
  Width = 400
  Height = 400

var img = initImage[ColorRGBF](Width, Height)
for x in 0..<Width:
  for y in 0..<Height:
    let fx = float32(x)
    let fy = float32(y)
    var hue = sin(fx / 16) + sin(fy / 8) + sin((fx + fy) / 16) + sin(sqrt((fx^2 + fy^2)) / 8)
    hue = (hue + 4) / 8   # Between 0 and 1.
    let rgb = to(ColorHSL([hue * 360, 1, 0.5]), ColorRGBF)
    img[x, y] = rgb
  img.savePNG("plasma.png")

Ol

; creating the "plasma" image buffer
(import (scheme inexact))
(define plasma
   (fold append #null
      (map (lambda (y)
            (map (lambda (x)
                  (let ((value (/
                           (+ (sin (/ y 4))
                              (sin (/ (+ x y) 8))
                              (sin (/ (sqrt (+ (* x x) (* y y))) 8))
                              4) 8)))
                     value))
               (iota 256)))
         (iota 256))))
; rendering the prepared buffer (using OpenGL)
(import (lib gl1))
(gl:set-window-size 256 256)

(glBindTexture GL_TEXTURE_2D 0)
(glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_LINEAR)
(glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_LINEAR)
(glTexImage2D GL_TEXTURE_2D 0 GL_LUMINANCE
   256 256
   0 GL_LUMINANCE GL_FLOAT (cons (fft* fft-float) plasma))

(glEnable GL_TEXTURE_2D)

(gl:set-renderer (lambda (_)
   (glClear GL_COLOR_BUFFER_BIT)
   (glBegin GL_QUADS)
      (glTexCoord2f 0 0)
      (glVertex2f -1 -1)
      (glTexCoord2f 0 1)
      (glVertex2f -1 1)
      (glTexCoord2f 1 1)
      (glVertex2f 1 1)
      (glTexCoord2f 1 0)
      (glVertex2f 1 -1)
   (glEnd)))

Perl

Translation of: Raku
use Imager;

sub plasma {
    my ($w, $h) = @_;

    my $img = Imager->new(xsize => $w, ysize => $h);

    for my $x (0 .. $w-1) {
        for my $y (0 .. $h-1) {
            my $hue = 4 + sin($x/19) + sin($y/9) + sin(($x+$y)/25) + sin(sqrt($x**2 + $y**2)/8);
            $img->setpixel(x => $x, y => $y, color => {hsv => [360 * $hue / 8, 1, 1]});
        }
    }

    return $img;
}

my $img = plasma(400, 400);
$img->write(file => 'plasma-perl.png');

Off-site image: Plasma effect

Phix

Library: Phix/pGUI
Translation of: JavaScript
-- demo\rosetta\plasma.exw
include pGUI.e

Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

sequence plasma
integer pw = 0, ph = 0

procedure createPlasma(integer w, h)
    plasma = repeat(repeat(0,w),h)
    for y=1 to h do
        for x=1 to w do
            atom v = sin(x/16)
            v += sin(y/8)
            v += sin((x+y)/16)
            v += sin(sqrt(x*x + y*y)/8)
            v += 4 -- shift range from -4 .. 4 to 0 .. 8
            v /= 8 -- bring range down to 0 .. 1
            plasma[y][x] = v
        end for
    end for
    pw = w
    ph = h
end procedure

atom hueShift = 0

procedure drawPlasma(integer w, h)
    hueShift = remainder(hueShift + 0.02,1)
    sequence rgb3 = repeat(repeat(0,w*h),3)
    integer cx = 1
    for y=1 to h do
        for x=1 to w do
            atom hue = hueShift + remainder(plasma[y][x],1)
            integer i = floor(hue * 6)
            atom t = 255,
                 f = (hue * 6 - i)*t,
                 q = t - f, 
                 r, g, b
            switch mod(i,6) do
                case 0: r = t; g = f; b = 0
                case 1: r = q; g = t; b = 0
                case 2: r = 0; g = t; b = f
                case 3: r = 0; g = q; b = t
                case 4: r = f; g = 0; b = t
                case 5: r = t; g = 0; b = q
            end switch
            rgb3[1][cx] = r
            rgb3[2][cx] = g
            rgb3[3][cx] = b
            cx += 1
        end for
    end for
    cdCanvasPutImageRectRGB(cddbuffer, w, h, rgb3, 0, 0, 0, 0, 0, 0, 0, 0) 
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)
    atom {w,h} = IupGetIntInt(canvas, "DRAWSIZE")
    if pw!=w or ph!=h then
        createPlasma(w,h)
    end if
    cdCanvasActivate(cddbuffer)
    drawPlasma(w,h)
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function timer_cb(Ihandle /*ih*/)
    IupUpdate(canvas)
    return IUP_IGNORE
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_WHITE)
    cdCanvasSetForeground(cddbuffer, CD_GRAY)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()

    canvas = IupCanvas(NULL)
    IupSetAttribute(canvas, "RASTERSIZE", "450x300")
    IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
    IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))

    dlg = IupDialog(canvas)
    IupSetAttribute(dlg, "TITLE", "Plasma")

    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL)
    Ihandle timer = IupTimer(Icallback("timer_cb"), 50)
    IupMainLoop()
    IupClose()
end procedure

main()

And here's a simple console ditty, similar I think to C's ASCII version for Windows, though this also works on Linux:

sequence s = video_config() 
for i=1 to s[VC_SCRNLINES]*s[VC_SCRNCOLS]-1 do
    bk_color(rand(16)-1)
    text_color(rand(16)-1)
    puts(1,"\xDF")
end for
{} = wait_key()

Processing

/**
 Plasmas with Palette Looping
 https://lodev.org/cgtutor/plasma.html#Plasmas_with_Palette_Looping_
 */

int pal[] = new int[128];
int[] buffer;
float r = 42, g = 84, b = 126;
boolean rd, gd, bd;

void setup() {
  size(600, 600);
  frameRate(25);
  buffer = new int[width*height];
  for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
      buffer[x+y*width] = int(((128+(128*sin(x/32.0)))
        +(128+(128*cos(y/32.0))) 
        +(128+(128*sin(sqrt((x*x+y*y))/32.0))))/4);
    }
  }
}

void draw() {
  if (r > 128) rd = true;
  if (!rd) r++;
  else r--;
  if (r < 0) rd = false;
  if (g > 128) gd = true;
  if (!gd) g++;
  else g--;
  if (r < 0) gd = false; 
  if (b > 128) bd = true;
  if (!bd) b++;
  else b--;
  if (b < 0){ bd = false;}
  float s_1, s_2;
  for (int i = 0; i < 128; i++) {
    s_1 = sin(i*PI/25);
    s_2 = sin(i*PI/50+PI/4);
    pal[i] = color(r+s_1*128, g+s_2*128, b+s_1*128);
  }
  loadPixels();
  for (int i = 0; i < buffer.length; i++) {                    
    pixels[i] =  pal[(buffer[i]+frameCount)&127];
  }
  updatePixels();
}

It can be played on line :
here.

Processing Python mode

"""
Plasmas with Palette Looping
https://lodev.org/cgtutor/plasma.html#Plasmas_with_Palette_Looping_
"""

pal = [0] * 128
r = 42
g = 84
b = 126
rd = gd = bd = False

def setup():
    global buffer
    size(600, 600)
    frameRate(25)
    buffer = [None] * width * height
    for x in range(width):
        for y in range(width):
            value = int(((128 + (128 * sin(x / 32.0)))
                         + (128 + (128 * cos(y / 32.0)))
                         + (128 + (128 * sin(sqrt((x * x + y * y)) / 32.0)))) / 4)
            buffer[x + y * width] = value

def draw():
    global r, g, b, rd, gd, bd
    if r > 128: rd = True
    if not rd: r += 1
    else: r-=1
    if r < 0: rd = False
    if g > 128: gd = True
    if not gd: g += 1
    else: g- = 1
    if r < 0: gd = False 
    if b > 128: bd = True
    if not bd: b += 1
    else: b- = 1
    if b < 0: bd = False
 
    for i in range(128):
          s_1 = sin(i * PI / 25)
          s_2 = sin(i * PI / 50 + PI / 4)
          pal[i] = color(r + s_1 * 128, g + s_2 * 128, b + s_1 * 128)

    loadPixels()
    for i, b in enumerate(buffer):
          pixels[i] = pal[(b + frameCount) % 127]
    updatePixels()

Python

Translation of: Raku
import math
import colorsys
from PIL import Image

def plasma (w, h):
	out = Image.new("RGB", (w, h))
	pix = out.load()
	for x in range (w):
		for y in range(h):
			hue = 4.0 + math.sin(x / 19.0) + math.sin(y / 9.0) \
				+ math.sin((x + y) / 25.0) + math.sin(math.sqrt(x**2.0 + y**2.0) / 8.0)
			hsv = colorsys.hsv_to_rgb(hue/8.0, 1, 1)
			pix[x, y] = tuple([int(round(c * 255.0)) for c in hsv])
	return out

if __name__=="__main__":
	im = plasma(400, 400)
	im.show()

Racket

Uses `return-color-by-pos` from #Lisp, because it was almost lift and shift

#lang racket
;;  from lisp (cos I could just lift the code)
(require images/flomap
         2htdp/universe
         racket/flonum)

;; copied from pythagoras-triangle#racket
(define (real-remainder x q) (- x (* (floor (/ x q)) q)))

(define (HSV->RGB H S V)
  (define C (* V S)) ; chroma
  (define H′ (/ H 60))
  (define X (* C (- 1 (abs (- (real-remainder H′ 2) 1)))))
  (define-values (R1 G1 B1)
    (cond
      [(< H′ 1) (values C X 0.)]
      [(< H′ 2) (values X C 0.)]
      [(< H′ 3) (values 0. C X)]
      [(< H′ 4) (values 0. X C)]
      [(< H′ 5) (values X 0. C)]
      [(< H′ 6) (values C 0. X)]
      [else (values 0. 0. 0.)]))
  (define m (- V C))
  (values (+ R1 m) (+ G1 m) (+ B1 m)))


(define ((colour-component-by-pos ϕ) k x y)
  (let ((rv
         (/ (+ (+ 1/2 (* 1/2 (sin (+ ϕ (/ x 16.0)))))
               (+ 1/2 (* 1/2 (sin (+ ϕ (/ y 8.0)))))
               (+ 1/2 (* 1/2 (sin (+ ϕ (/ (+ x y) 16.0)))))
               (+ 1/2 (* 1/2 (sin (+ ϕ (/ (sqrt (+ (sqr x) (sqr y))) 8.0))))))
            4.0)))
    rv))

(define ((plasma-flomap (ϕ 0)) w h)
  (build-flomap 1 w h (colour-component-by-pos ϕ)))

(define ((plasma-image (ϕ 0)) w h)
  (flomap->bitmap ((plasma-flomap ϕ) w h)))

(define ((colour-plasma plsm) t)
  (let ((w (flomap-width plsm))
        (h (flomap-height plsm)))
    (flomap->bitmap
     (build-flomap* 3 w h
                    (λ (x y)
                      (define-values (r g b)
                        (HSV->RGB (real-remainder
                                   (+ (* t 5.)
                                      (* 360 (flomap-ref plsm 0 x y)))
                                   360.) 1. 1.))
                      (flvector r g b))))))

;((plasma-image) 200 200)

;((plasma-image (/ pi 32)) 200 200)

(define plsm ((plasma-flomap) 300 300))
  (animate (λ (t)
             ((colour-plasma plsm) t)))

Raku

(formerly Perl 6)

Works with: Rakudo version 2018.09
use Image::PNG::Portable;

my ($w, $h) = 400, 400;
my $out = Image::PNG::Portable.new: :width($w), :height($h);

plasma($out);

$out.write: 'Plasma-perl6.png';

sub plasma ($png) {
    (^$w).race.map: -> $x {
        for ^$h -> $y {
            my $hue = 4 + sin($x / 19) + sin($y / 9) + sin(($x + $y) / 25) + sin(sqrt($x² + $y²) / 8);
            $png.set: $x, $y, |hsv2rgb($hue/8, 1, 1);
        }
    }
}

sub hsv2rgb ( $h, $s, $v ){
    my $c = $v * $s;
    my $x = $c * (1 - abs( (($h*6) % 2) - 1 ) );
    my $m = $v - $c;
    (do given $h {
        when   0..^1/6 { $c, $x, 0 }
        when 1/6..^1/3 { $x, $c, 0 }
        when 1/3..^1/2 { 0, $c, $x }
        when 1/2..^2/3 { 0, $x, $c }
        when 2/3..^5/6 { $x, 0, $c }
        when 5/6..1    { $c, 0, $x }
    } ).map: ((*+$m) * 255).Int
}

Ring

# Project : Plasma effect

load "guilib.ring"

paint = null

new qapp
       {
        win1 = new qwidget()
       {
                   setwindowtitle("Plasma effect")
                   setgeometry(100,100,500,600)

                   label1 = new qlabel(win1)
                   {
                   setgeometry(10,10,400,400)
                   settext("")
                    }

                   new qpushbutton(win1)
                   {
                   setgeometry(150,500,100,30)
                   settext("Draw")
                   setclickevent("Draw()")
                  }
                  show()
       }
       exec()
       }

func draw

        p1    = new qpicture()
        color = new qcolor() { setrgb(0,0,255,255) }   ### <<< BLUE
        pen   = new qpen() { setcolor(color) setwidth(1) }

        paint = new qpainter()
        {
                   begin(p1)
                   setpen(pen)

                   w = 256 
                   h = 256
                   time = 0

                   for x = 0 to w -1
                         for y = 0 to h -1
                               time = time + 0.99 
                               value = sin(dist(x + time, y, 128, 128) / 8) +
                                           sin(dist(x, y, 64, 64) / 8) +
                                           sin(dist(x, y + time / 7, 192, 64) / 7) +
                                           sin(dist(x, y, 192, 100) / 8) + 4
                               c = floor(value * 32)
                               r = c
                               g = (c*2)%255
                               b = 255-c
                               color2 = new qcolor()
                               color2.setrgb(r,g,b,255)
                               pen.setcolor(color2) 
                               setpen(pen)     
                               drawpoint(x,y)
                        next
                   next
        endpaint()
        }
        label1 { setpicture(p1) show() }
        return

func dist(a, b, c, d)
        d = sqrt(((a - c) * (a - c) + (b - d) * (b - d)))
        return d

Output:

Plasma effect


Ruby

Library: RubyGems
Library: JRubyArt

JRubyArt is a port of Processing to the ruby language

attr_reader :buffer, :palette, :r, :g, :b, :rd, :gd, :bd, :dim

def settings
  size(600, 600)
end

def setup
  sketch_title 'Plasma Effect'
  frame_rate 25
  @r = 42
  @g = 84
  @b = 126
  @rd = true
  @gd = true
  @bd = true
  @dim = width * height
  @buffer = Array.new(dim)
  grid(width, height) do |x, y|
    buffer[x + y * width] = (
      (
        (128 + (128 * sin(x / 32.0))) +
        (128 + (128 * cos(y / 32.0))) +
        (128 + (128 * sin(Math.hypot(x, y) / 32.0)))
      ) / 4
    ).to_i
  end
  load_pixels
end

def draw
  if rd
    @r -= 1
    @rd = false if r.negative?
  else
    @r += 1
    @rd = true if r > 128
  end
  if gd
    @g -= 1
    @gd = false if g.negative?
  else
    @g += 1
    @gd = true if g > 128
  end
  if bd
    @b -= 1
    @bd = false if b.negative?
  else
    @b += 1
    @bd = true if b > 128
  end
  @palette = (0..127).map do |col|
    s1 = sin(col * Math::PI / 25)
    s2 = sin(col * Math::PI / 50 + Math::PI / 4)
    color(r + s1 * 128, g + s2 * 128, b + s1 * 128)
  end
  dim.times do |idx|
    pixels[idx] = palette[(buffer[idx] + frame_count) & 127]
  end
  update_pixels
end

Rust

extern crate image;

use image::ColorType;
use std::path::Path;

// Framebuffer dimensions
const WIDTH: usize = 640;
const HEIGHT: usize = 480;

/// Formula for plasma at any particular address
fn plasma_pixel(x: f64, y: f64) -> f64 {
    ((x / 16.0).sin()
        + (y / 8.0).sin()
        + ((x + y) / 16.0).sin()
        + ((x * x + y * y).sqrt() / 8.0).sin()
        + 4.0)
        / 8.0
}

/// Precalculate plasma field lookup-table for performance
fn create_plasma_lut() -> Vec<f64> {
    let mut plasma: Vec<f64> = vec![0.0; WIDTH * HEIGHT];
    for y in 0..HEIGHT {
        for x in 0..WIDTH {
            plasma[(y * WIDTH) + x] = plasma_pixel(x as f64, y as f64);
        }
    }
    plasma
}

/// Convert from HSV float(1.0,1.0,1.0) to RGB u8 tuple (255,255,255).
/// From https://crates.io/crates/palette 0.5.0 rgb.rs, simplified for example
fn hsv_to_rgb(hue: f64, saturation: f64, value: f64) -> (u8, u8, u8) {
    let c = value * saturation;
    let h = hue * 6.0;
    let x = c * (1.0 - (h % 2.0 - 1.0).abs());
    let m = value - c;
    let (red, green, blue) = match (h % 6.0).floor() as u32 {
        0 => (c, x, 0.0),
        1 => (x, c, 0.0),
        2 => (0.0, c, x),
        3 => (0.0, x, c),
        4 => (x, 0.0, c),
        _ => (c, 0.0, x),
    };
    // Convert back to RGB (where components are integers from 0 to 255)
    (
        ((red + m) * 255.0).round() as u8,
        ((green + m) * 255.0).round() as u8,
        ((blue + m) * 255.0).round() as u8,
    )
}
fn main() {
    // The bitmap/framebuffer for our application. 3 u8 elements per output pixel
    let mut framebuffer: Vec<u8> = vec![0; WIDTH * HEIGHT * 3];
    // Generate a lookup table so we don't do too much math for every pixel.
    // Do it in a function so that the local one can be immutable.
    let plasma_lookup_table = create_plasma_lut();
    // For each (r,g,b) pixel in our output buffer
    for (index, rgb) in framebuffer.chunks_mut(3).enumerate() {
        // Lookup the precalculated plasma value
        let hue_lookup = plasma_lookup_table[index] % 1.0;
        let (red, green, blue) = hsv_to_rgb(hue_lookup, 1.0, 1.0);
        rgb[0] = red;
        rgb[1] = green;
        rgb[2] = blue;
    }
    // Save our plasma image to out.png
    let output_path = Path::new("out.png");
    match image::save_buffer(
        output_path,
        framebuffer.as_slice(),
        WIDTH as u32,
        HEIGHT as u32,
        ColorType::RGB(8),
    ) {
        Err(e) => println!("Error writing output image:\n{}", e),
        Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
    }
}

Scala

Java Swing Interoperability

import java.awt._
import java.awt.event.ActionEvent
import java.awt.image.BufferedImage

import javax.swing._

import scala.math.{sin, sqrt}

object PlasmaEffect extends App {

  SwingUtilities.invokeLater(() =>
    new JFrame("Plasma Effect") {

      class PlasmaEffect extends JPanel {
        private val (w, h) = (640, 640)
        private var hueShift = 0.0f

        override def paintComponent(gg: Graphics): Unit = {
          val g = gg.asInstanceOf[Graphics2D]

          def drawPlasma(g: Graphics2D) = {
            val img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB)

            for (y <- 0 until h;
                 x <- 0 until w) {

              def design =
                (sin(x / 16f) + sin(y / 8f) + sin((x + y) / 16f) + sin(sqrt(x * x + y * y) / 8f) + 4).toFloat / 8

              img.setRGB(x, y, Color.HSBtoRGB(hueShift + design % 1, 1, 1))
            }
            g.drawImage(img, 0, 0, null)
          }

          super.paintComponent(gg)
          g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
          drawPlasma(g)
        }

        // animate about 24 fps and shift hue value with every frame
        new Timer(42, (_: ActionEvent) => {
          hueShift = (hueShift + 0.02f) % 1
          repaint()
        }).start()

        setBackground(Color.white)
        setPreferredSize(new Dimension(h, w))
      }

      add(new PlasmaEffect, BorderLayout.CENTER)
      pack()
      setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
      setLocationRelativeTo(null)
      setResizable(false)
      setVisible(true)
    })

}

Sidef

Translation of: Raku
require('Imager')

class Plasma(width=400, height=400) {

    has img = nil

    method init {
        img = %O|Imager|.new(xsize => width, ysize => height)
    }

    method generate {
        for y=(^height), x=(^width) {
            var hue = (4 + sin(x/19) + sin(y/9) + sin((x+y)/25) + sin(hypot(x, y)/8))
            img.setpixel(x => x, y => y, color => Hash(hsv => [360 * hue / 8, 1, 1]))
        }
    }

    method save_as(filename) {
        img.write(file => filename)
    }
}

var plasma = Plasma(256, 256)
plasma.generate
plasma.save_as('plasma.png')

Output image: Plasma effect

Wren

Translation of: Kotlin
Library: DOME
import "graphics" for Canvas, Color, ImageData
import "dome" for Window
import "math" for Math

class PlasmaEffect {
    construct new(width, height) {
        Window.title = "Plasma Effect"
        Window.resize(width, height)
        Canvas.resize(width, height)
        _w = width
        _h = height
        _bmp = ImageData.create("plasma_effect", _w, _h)
        _plasma = createPlasma() // stores the hues for the colors
    }

    init() {
        _frame = 0
        _hueShift = 0
        Canvas.cls(Color.white)
    }

    createPlasma() {
        var buffer = List.filled(_w, null)
        for (x in 0..._w) {
            buffer[x] = List.filled(_h, 0)
            for (y in 0..._h) {
                var value = Math.sin(x / 16)
                value = value + Math.sin(y / 8)
                value = value + Math.sin((x + y) / 16)
                value = value + Math.sin((x * x + y * y).sqrt / 8)
                value = value + 4  // shift range from -4 .. 4 to 0 .. 8
                value = value / 8  // bring range down to 0 .. 1
                if (value < 0 || value > 1) Fiber.abort("Hue value out of bounds")
                buffer[x][y] = value
                pset(x, y, Color.hsv(value * 360, 1, 1))
            }
        }
        return buffer
    }

    pset(x, y, col) { _bmp.pset(x, y, col) }

    pget(x, y) { _bmp.pget(x, y) }

    update() {
        _frame = _frame + 1
        if (_frame % 3 == 0) {  // update every 3 frames or 1/20th second
            _hueShift = (_hueShift + 0.02) % 1
        }
    }

    draw(alpha) {
        for (x in 0..._w) {
            for (y in 0..._h) {
                var hue = (_hueShift + _plasma[x][y]) % 1
                var col = Color.hsv(hue * 360, 1, 1)
                pset(x, y, col)
            }
        }
        _bmp.draw(0, 0)
    }
}

var Game = PlasmaEffect.new(640, 640)

XPL0

Translation of Lode's RGB plasma, provided by link at the top of this page.

func real Dist(X1, Y1, X2, Y2);
int     X1, Y1, X2, Y2;
return sqrt( float((X1-X2)*(X1-X2) + (Y1-Y2)*(Y1-Y2)) );

int     Time, X, Y, Color;
real    Value;
[SetVid($112);  \640x480x24
repeat  Time:= GetTime/50_000;
        for Y:= 0 to 256-1 do
            for X:= 0 to 256-1 do
                [Value:= Sin(Dist(X+Time, Y, 128, 128) / 8.0) +
                         Sin(Dist(X, Y, 64, 64) / 8.0) +
                         Sin(Dist(X, Y+Time/7, 192, 64) / 7.0) +
                         Sin(Dist(X, Y, 192, 100) / 8.0);
                Color:= fix((4.0+Value) * 31.875);      \[0..255]
                Point(X, Y, Color<<16 + ((Color*2)&$FF)<<8 + (255-Color));
                ];
until   KeyHit;
]