Skip to content

Instantly share code, notes, and snippets.

@xiaozhuai
Last active December 18, 2024 08:46
Show Gist options
  • Select an option

  • Save xiaozhuai/353d300f75bf6fa393782adfaeb3ea15 to your computer and use it in GitHub Desktop.

Select an option

Save xiaozhuai/353d300f75bf6fa393782adfaeb3ea15 to your computer and use it in GitHub Desktop.

Revisions

  1. xiaozhuai revised this gist Dec 18, 2024. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion x11_art.c
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,6 @@

    #include <X11/Xlib.h>
    #include <X11/Xutil.h>

    #include <stdlib.h>
    #include <time.h>
    #include <math.h>
  2. xiaozhuai revised this gist Dec 18, 2024. No changes.
  3. xiaozhuai created this gist Dec 18, 2024.
    127 changes: 127 additions & 0 deletions x11_art.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,127 @@
    /**
    *
    * Compile on Linux with:
    * gcc x11_art.c -o x11_art -O3 -lX11
    *
    * Compile on MacOS with:
    * gcc x11_art.c -o x11_art -O3 -lX11 -I/opt/X11/include -L/opt/X11/lib
    *
    */

    #include <X11/Xlib.h>
    #include <X11/Xutil.h>

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

    float length(const float *v) {
    return sqrt(v[0] * v[0] + v[1] * v[1]);
    }

    int clamp(int x, int min, int max) {
    return x < min ? min : x > max ? max : x;
    }

    float fract(float x) {
    return x - floor(x);
    }

    void palette(float t, float *color) {
    float a[3] = {0.5, 0.5, 0.5};
    float b[3] = {0.5, 0.5, 0.5};
    float c[3] = {1.0, 1.0, 1.0};
    float d[3] = {0.263, 0.416, 0.557};
    for (int i = 0; i < 3; ++i) {
    color[i] = a[i] + b[i] * cos(6.28318 * (c[i] * t + d[i]));
    }
    }

    unsigned long fragment(int x, int y, int width, int height, float time) {
    float uv[2];
    float uv0[2];
    uv[0] = uv0[0] = (2.0 * x - width) / height;
    uv[1] = uv0[1] = (2.0 * y - height) / height;
    float color[3] = {0.0, 0.0, 0.0};
    for (int i = 0; i < 4; ++i) {
    uv[0] = fract(uv[0] * 1.5) - 0.5;
    uv[1] = fract(uv[1] * 1.5) - 0.5;
    float d = length(uv) * exp(-length(uv0));
    float col[3];
    palette(length(uv0) + i * 0.4 + time * 0.4, col);
    d = sin(d * 8.0 + time) / 8.0;
    d = fabs(d);
    d = pow(0.01 / d, 1.2);
    for (int j = 0; j < 3; ++j) {
    color[j] += col[j] * d;
    }
    }
    unsigned char color_u8c4[4] = {
    clamp(color[2] * 255, 0, 255),
    clamp(color[1] * 255, 0, 255),
    clamp(color[0] * 255, 0, 255),
    255
    };
    return *(unsigned long *)color_u8c4;
    }

    float now() {
    struct timespec ts;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
    return ts.tv_sec + ts.tv_nsec / 1000000000.0;
    }

    int main() {
    const int width = 800;
    const int height = 600;
    Display *d = XOpenDisplay(NULL);
    Window w = XCreateSimpleWindow(
    d, RootWindow(d, 0),
    10, 10, width, height, 1, 0, 0
    );
    XSizeHints hints;
    hints.flags = PMinSize | PMaxSize;
    hints.min_width = hints.max_width = width;
    hints.min_height = hints.max_height = height;
    XSetWMNormalHints(d, w, &hints);
    Atom wmDeleteWindow = XInternAtom(d, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(d, w, &wmDeleteWindow, 1);
    XImage *img = XCreateImage(
    d, DefaultVisual(d, 0), DefaultDepth(d, 0),
    ZPixmap, 0,
    malloc(width * height * 4),
    width, height, 32, 0
    );
    XMapWindow(d, w);
    XFlush(d);
    XEvent e;
    int running = 1;
    const float start = now();
    while(running) {
    while(XPending(d)) {
    XNextEvent(d, &e);
    if (e.type == ClientMessage) {
    if ((Atom)e.xclient.data.l[0] == wmDeleteWindow) {
    running = 0;
    break;
    }
    }
    }
    if (!running) break;
    const float time = now() - start;
    // printf("time: %f\n", time);
    for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
    unsigned long color = fragment(x, y, width, height, time);
    XPutPixel(img, x, y, color);
    }
    }
    XPutImage(d, w, DefaultGC(d, 0), img, 0, 0, 0, 0, width, height);
    XFlush(d);
    }
    XDestroyImage(img);
    XDestroyWindow(d, w);
    XCloseDisplay(d);
    return 0;
    }