Skip to content

Instantly share code, notes, and snippets.

@rexim
Last active November 24, 2025 20:59
Show Gist options
  • Select an option

  • Save rexim/ef86bf70918034a5a57881456c0a0ccf to your computer and use it in GitHub Desktop.

Select an option

Save rexim/ef86bf70918034a5a57881456c0a0ccf to your computer and use it in GitHub Desktop.
// $ cc -o checker checker.c
// $ ./checker
// $ ffmpeg -i output-%02d.ppm -r 60 output.mp4
#include <stdio.h>
int main()
{
char buf[256];
for (int i = 0; i < 60; ++i) {
snprintf(buf, sizeof(buf), "output-%02d.ppm", i);
const char *output_path = buf;
FILE *f = fopen(output_path, "wb");
int w = 16*60;
int h = 9*60;
fprintf(f, "P6\n");
fprintf(f, "%d %d\n", w, h);
fprintf(f, "255\n");
for (int y = 0; y < h; ++y){
for (int x = 0; x < w; ++x) {
if (((x + i)/60 + (y + i)/60)%2) {
fputc(0xFF, f);
fputc(0x00, f);
fputc(0x00, f);
} else {
fputc(0x00, f);
fputc(0x00, f);
fputc(0x00, f);
}
}
}
fclose(f);
printf("Generated %s\n", output_path);
}
return 0;
}
// $ cc -O3 -o plasma plasma.cpp -lm
// $ ./plasma
// $ ffmpeg -i output-%03d.ppm -r 60 output.mp4
#include <stdio.h>
#include <math.h>
struct vec4 {
float x, y, z, w;
vec4(float x = 0, float y = 0, float z = 0, float w = 0):
x(x), y(y), z(z), w(w)
{}
};
struct vec2 {
float x, y;
vec2(float x = 0, float y = 0):
x(x), y(y)
{}
vec2 yx() const { return vec2(y, x); }
vec4 xyyx() const { return vec4(x, y, y, x); }
};
vec2 operator *(const vec2 &a, float s) { return vec2(a.x*s, a.y*s); }
vec2 operator +(const vec2 &a, float s) { return vec2(a.x+s, a.y+s); }
vec2 operator *(float s, const vec2 &a) { return a*s; }
vec2 operator -(const vec2 &a, const vec2 &b) { return vec2(a.x-b.x, a.y-b.y); }
vec2 operator +(const vec2 &a, const vec2 &b) { return vec2(a.x+b.x, a.y+b.y); }
vec2 operator *(const vec2 &a, const vec2 &b) { return vec2(a.x*b.x, a.y*b.y); }
vec2 operator /(const vec2 &a, float s) { return vec2(a.x/s, a.y/s); }
float dot(const vec2 &a, const vec2 &b) { return a.x*b.x + a.y*b.y; }
vec2 abs(const vec2 &a) { return vec2(fabsf(a.x), fabsf(a.y)); }
vec2 &operator +=(vec2 &a, const vec2 &b) { a = a + b; return a; }
vec2 &operator +=(vec2 &a, float s) { a = a + s; return a; }
vec2 cos(const vec2 &a) { return vec2(cosf(a.x), cosf(a.y)); }
vec4 sin(const vec4 &a) { return vec4(sinf(a.x), sinf(a.y), sinf(a.z), sinf(a.w)); }
vec4 exp(const vec4 &a) { return vec4(expf(a.x), expf(a.y), expf(a.z), expf(a.w)); }
vec4 tanh(const vec4 &a) { return vec4(tanhf(a.x), tanhf(a.y), tanhf(a.z), tanhf(a.w)); }
vec4 operator +(const vec4 &a, float s) { return vec4(a.x+s, a.y+s, a.z+s, a.w+s); }
vec4 operator *(const vec4 &a, float s) { return vec4(a.x*s, a.y*s, a.z*s, a.w*s); }
vec4 operator *(float s, const vec4 &a) { return a*s; }
vec4 operator +(const vec4 &a, const vec4 &b) { return vec4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w); }
vec4 &operator +=(vec4 &a, const vec4 &b) { a = a + b; return a; }
vec4 operator -(float s, const vec4 &a) { return vec4(s-a.x, s-a.y, s-a.z, s-a.w); }
vec4 operator /(const vec4 &a, const vec4 &b) { return vec4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w); }
int main()
{
char buf[256];
for (int i = 0; i < 240; ++i) {
snprintf(buf, sizeof(buf), "output-%03d.ppm", i);
const char *output_path = buf;
FILE *f = fopen(output_path, "wb");
int w = 16*60;
int h = 9*60;
fprintf(f, "P6\n");
fprintf(f, "%d %d\n", w, h);
fprintf(f, "255\n");
vec2 r = {(float)w, (float)h};
float t = ((float)i/240)*2*M_PI;
for (int y = 0; y < h; ++y){
for (int x = 0; x < w; ++x) {
vec4 o;
vec2 FC = {(float)x, (float)y};
//////////////////////////////
// https://x.com/XorDev/status/1894123951401378051
vec2 p=(FC*2.-r)/r.y,l,i,v=p*(l+=4.-4.*abs(.7-dot(p,p)));
for(;i.y++<8.;o+=(sin(v.xyyx())+1.)*abs(v.x-v.y))v+=cos(v.yx()*i.y+i+t)/i.y+.7;
o=tanh(5.*exp(l.x-4.-p.y*vec4(-1,1,2,0))/o);
//////////////////////////////
fputc(o.x*255, f);
fputc(o.y*255, f);
fputc(o.z*255, f);
}
}
fclose(f);
printf("Generated %s (%3d/%3d)\n", output_path, i + 1, 240);
}
return 0;
}
@HalanoSiblee
Copy link

plasma
Very nice, works

@auxiliaire
Copy link

With three extra lines, it can also call ffmpeg on its own and clean up the temporary files:

#include <stdlib.h>
 // ...
 system("ffmpeg -i output-%03d.ppm -r 60 output.mp4");
 system("rm *.ppm");

@mancap314
Copy link

Really great. Inspired me to implement it in C (with cglm for the vector part), see there

@aslilac
Copy link

aslilac commented Nov 21, 2025

you can also use std::thread and std::thread::hardware_concurrency() to see how many threads are available on the cpu and execute a thread on each, breaking the work up in to chunks and running them in parallel. obviously still not as fast as just running on the gpu, but will still make it go a lot faster.

@Vavassor
Copy link

In the plasma version it has blue towards the top of the image, but the original has blue on the bottom. So it might be flipped vertically. But can be fixed by changing the fragment coordinate. vec2 FC = {(float)x, (float)(h - 1 - y)};

@Nachx639
Copy link

is there a way to change colors?

@rickmarina
Copy link

rickmarina commented Nov 24, 2025

so nice work i didnt know about ppm format.

this is my port to c# :
code port c#

output.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment