Imgui: ImDrawList coding party - deadline Nov 30, 2020!

Created on 19 Nov 2020  ·  77Comments  ·  Source: ocornut/imgui

ImDrawList coding party!

  • create small visual effects
  • 1024 bytes of source code
  • 320x180 output
  • only use dear imgui's crappy low-level shape drawing api

Two days ago I thought:
_"It'd be fun to organize a contest for writing special effects using the ImDrawList api, with a constraint on source code size. May be fun to see what people can come up with using shape/vector-based api (quite different from a pixel-shading function). Would you participate?"_

It's by no mean a great api but it has served many well, to draw custom widgets etc, let's get it some extra love..

Here's a testbed imdrawlist_party.cpp which you can paste in your application or any dear imgui example:
https://gist.github.com/ocornut/51367cc7dfd2c41d607bb0acfa6caf66

Rules:

  • Your source file fx.inl must be <= 1024 bytes.
  • Effect should be reasonably portable (not relying on specific render backend callback)
  • OK to use preprocessor define or other tricks as long as they are reasonably portable.
  • Included are: math.h, imgui.h, imgui_internal.h with ImVec2 maths operators
  • The effect should not use ImGui:: functions, only use ImDrawList facilities.
  • Canvas ratio is expected to be 16/9, canvas size expected to be 320 by 180.
  • For simplicity we assume you can encode a color as 0xAAGGBBRR instead of using the IM_COL32() macro, therefore IMGUI_USE_BGRA_PACKED_COLOR config option is not supported!

Prizes:

  • This is mostly for fun so please feel free to make multiple submissions or tweak them as you feel. No pressure. Mostly, I'm supposed to work and ship tables this or next week so hey why I am doing this?!
  • We could possibly include some of them in imgui_demo if they strike a good balance of cool and educational. If we end up doing that we'll rework code to be neat and proper for a demo (aka not densely packed into 1024 characters).

Function signature:

void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 mouse, float t);
     d : draw list
     a : upper-left corner
     b : lower-right corner
    sz : size (== b - a)
 mouse : x,y = mouse position (normalized so 0,0 over 'a'; 1,1 is over 'b', not clamped)
         z,w = left/right button held. <-1.0f not pressed, 0.0f just pressed, >0.0f time held.
    t  : time

If not using a given parameter, you can omit its name in your function to save a few characters.

To record gif files you can use ShareX https://getsharex.com or ScreenToGif https://www.screentogif.com/

Let's get started! You can post on this thread, on discord or on twitter!

Known issues

  • ImDrawList polygon stroking with thick lines looks broken on acute angle, good luck!!
drawindrawlist gallery

Most helpful comment

Quicksort visualization.

#define V2 ImVec2
#include <vector>
#include <array>
using namespace std;
int N = 64, S, J;
#define V vector<int>
V v = [] {
    V r;
    for (; J < N; J++) r.push_back(rand() % 180);
    return r;
}();
vector<array<int,4>> st { { 0, N-1, 0, 0} };
#define A st.back()[0]
#define B st.back()[1]
#define I st.back()[2]
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4,float t)
{
    float bs = s.x / N, y, c;
    for (int i = 0; i < N; i++) {
        y=a.y+v[i];
        c=70+v[i];
        d->AddRectFilled(V2(a.x+bs*i,y),V2(a.x+bs*(i+1),b.y),IM_COL32(c,255-c,255,255));
    }
    d->AddText(a, -1u, "Quicksort");
    if (st.empty()) return;
    d->AddRect(V2(a.x+bs*A,a.y),V2(a.x+bs*(B+1),b.y),0xFF00FF00,8,ImDrawCornerFlags_Top,2);
    switch (S) {
    case 0:case 5: if(A>=B)st.pop_back(),S+=3;else I=J=A,S++;break;
    case 1:case 6:
        if(v[J]>v[B])swap(v[I],v[J]),I++;
        if(++J>B)swap(v[I],v[B]),S++;
        break;
    case 2:case 7:st.push_back({A,I-1,A,3});S=0;break;
    case 3:st.push_back({I+1,B,A,8});S=5;break;
    case 8:S = st.back()[3]; st.pop_back();
    }
}

sort
Blobs.

#define V2 ImVec2
void FX (ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    int N = 25;
    float sp = s.y / N, y, st = sin(t) * 0.5 + 0.5,
          r[3] = { 1500, 1087 + 200 * st, 1650 },
          ctr[3][2] = { { 150, 140 }, { s.x * m.x, s.y * m.y },
              { 40 + 200 * st, 73 + 20*sin(st * 5) } };
    for (int i = 0; i < N; i++) {
        y = a.y + sp*(i+.5);
        for (int x = a.x; x <= b.x; x += 2) {
            float D = 0, o = 255;
            for (int k = 0; k < 3; k++)
                D += r[k]/(pow(x-a.x-ctr[k][0], 2) + pow(y-a.y-ctr[k][1], 2));
            if (D < 1) continue;
            if (D>2.5) D = 2.5;
            if (D < 1.15) o /= 2;
            d->AddLine(V2(x, y), V2(x+2, y), IM_COL32(239, 129, 19, o), D + sin(2.3 * t + 0.3 * i));
        }
    }
}

o
3D cube.

#define V2 ImVec2
void FX (ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    a.x += s.x/2, a.y += s.y / 2;
    float S = sin(m.x), C = cos(m.x), x = 50, y, z = (m.y * 2 - 1) * x;
    float v[8][3] { { x, x, z+x }, { x, -x, z+x }, { -x, -x, z+x }, { -x, x, z+x },
            { x, x, z-x }, { x, -x, z-x }, { -x, -x, z-x }, { -x, x, z-x } };
    for (int i = 0; i < 8; i++) {
        x = v[i][0] * C - v[i][1] * S;
        y = v[i][0] * S + v[i][1] * C + 120;
        z = v[i][2];
        v[i][0] = x / y * 50;
        v[i][1] = z / y * 50;
        v[i][2] = y;
    }
#define L(A,B) z = 500 / (v[A][2] + v[B][2]); \
    d->AddLine(V2(a.x+v[A][0],a.y+v[A][1]),V2(a.x+v[B][0],a.y+v[B][1]),-1u,z);
    L(0, 1) L(1, 2) L(2, 3) L(0, 3)
    L(4, 5) L(5, 6) L(6, 7) L(4, 7)
    L(0, 4) L(1, 5) L(2, 6) L(3, 7)
}

cubes
Real-time visualization of the interweb blogosphere.

#define V2 ImVec2
#include <vector>
int N = 300;
auto v = [] {
    std::vector<std::pair<V2,V2>>r(N);
    for (auto&p:r)
        p.second = p.first = V2(rand() % 320, rand() % 180);
    return r;
}();
float l2 (V2 x) { return x.x*x.x + x.y*x.y; }
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4,float t)
{
    float D, T;
    for (auto&p:v) {
        D = sqrt(l2(p.first - p.second));
        if (D > 0) p.first += (p.second - p.first) / D;
        if (D < 4) p.second = V2(rand() % 320, rand() % 180);
    }
    for (int i = 0; i < N; i++) {
        for (int j = i+1; j < N; j++) {
            D = l2(v[i].first - v[j].first);
            T = l2((v[i].first + v[j].first) - s) / 200;
            if (T > 255) T = 255;
            if (D < 400) d->AddLine(a+v[i].first, a+v[j].first, IM_COL32(T, 255-T, 255, 70), 2);
        }
    }
}

interwebs

All 77 comments

Here are some examples I made to get you started:

Circles

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4 mouse, float t)
{
    for (int n = 0; n < (1.0f + sinf(t * 5.7f)) * 40.0f; n++)
        d->AddCircle(V2(a.x + sz.x * 0.5f, a.y + sz.y * 0.5f), sz.y * (0.01f + n * 0.03f), 
            IM_COL32(255, 140 - n * 4, n * 3, 255));
}

drawlist fx 03

Squares

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
    float sx = 1.f / 16.f;
    float sy = 1.f / 9.f;
    for (float ty = 0.0f; ty < 1.0f; ty += sy)
        for (float tx = 0.0f; tx < 1.0f; tx += sx)
        {
            V2 c((tx + 0.5f * sx), (ty + 0.5f * sy));
            float k = 0.45f;
            d->AddRectFilled(
                V2(a.x + (c.x - k * sx) * sz.x, a.y + (c.y - k * sy) * sz.y),
                V2(a.x + (c.x + k * sx) * sz.x, a.y + (c.y + k * sy) * sz.y),
                IM_COL32(ty * 200, tx * 255, 100, 255));
        }
}

unknown

Curves

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t0)
{
    for (float t = t0; t < t0 + 1.0f; t += 1.0f / 100.0f)
    {
        V2 cp0(a.x, b.y);
        V2 cp1(b);
        float ts = t - t0;
        cp0.x += (0.4f + sin(t) * 0.3f) * sz.x;
        cp0.y -= (0.5f + cos(ts * ts) * 0.4f) * sz.y;
        cp1.x -= (0.4f + cos(t) * 0.4f) * sz.x;
        cp1.y -= (0.5f + sin(ts * t) * 0.3f) * sz.y;
        d->AddBezierCurve(V2(a.x, b.y), cp0, cp1, b, IM_COL32(100 + ts*150, 255 - ts*150, 60, ts * 200), 5.0f);
    }
}

drawlist fx 04b

Waves

#define V2 ImVec2
#define ARFM d->AddRectFilledMultiColor
#define ACF d->AddCircleFilled
#define CH s.SetCurrentChannel
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
    ARFM(a, b, 0xFF1E1E1E, 0xFF1E281E, 0xFF1E1E5A, 0xFF321E78);
    ARFM(a, V2(b.x, a.y + sz.y*0.4f), 0x1EFFDCFF, 0x14FFFFDC, 0x001E1E5A, 0x00321E78);
    auto s = d->_Splitter;
    s.Split(d, 2);
    for (int n = 0; n < 256; n++)
    {
        V2 c(a.x + n / 256.f * sz.x, b.y + 20 - cos(t - 0.1f * n / 2) * 10 + cos(t) * 5);
        float r(40 + sin(t + n / 2) * 40);
        CH(d, 0);
        ACF(c, r + 1, 0x80FFFFFF);
        CH(d, 1);
        ACF(c, r, IM_COL32(255, n / 2, n / 8, 255));
    }
    s.Merge(d);
    d->AddRect(a, b, IM_COL32(128, 128, 128, 100));
}

drawlist fx 02

Thunder Storm

#define min(x,y) ((x)<(y)?x:y)
#define wh(a) ImColor(1.f,1.f,1.f,a)
void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec2, float t)
{
    static float fl;
    if ((rand() % 500) == 0) fl = t;
    if ((t-fl) > 0)
    {
        auto ft = 0.25f;
        d->AddRectFilled(a, b, wh((ft - (t - fl)) / ft));
    }

    for (int i = 0; i < 2000; ++i) {
        unsigned h = ImGui::GetID(d+i + int(t/4));
        auto f = fmodf(t + fmodf(h / 777.f, 99), 99);
        auto tx = h % (int)sz.x;
        auto ty = h % (int)sz.y;
        if (f < 1) {
            auto py = ty - 1000 * (1 - f);
            d->AddLine({ a.x + tx, a.y + py }, { a.x + tx, a.y + min(py + 10,ty) }, (ImU32)-1);
        }
        else if (f < 1.2f)
            d->AddCircle({ a.x + tx, a.y + ty }, (f - 1) * 10 + h % 5, wh(1-(f-1)*5.f));
    }
}

imgui_storm

The Matrix effect, slowly been shaving off spaces and making the code uglier and uglier

//v1.1
#define V2 ImVec2
void FX(ImDrawList*d,V2 a,V2,V2 sz,ImVec4,float t)
{
  static struct{int y,h,c; float t,s;} m[40]={0};
  static int S=0x1234;
  static float t0=t;
  float ZI=t*.07f,Z=ZI+1.f;
  for(int x=0;x<40;x++)
  {
    auto& M=m[x];
    int i=x>=15&&x<25;
    if(M.s==0.f||M.y>16)
    {
      M.h = (t<7.f||i)*((int)(2+t*.5f) + S%(int)(6+(t*0.3f)));
      M.y = (M.s==0.f)*-(S%15)-M.h;
      M.c += S;
      M.s = (5+(S%14))*(.01f-t*.001f);
      if(t>5.f&&i)
      {
        M.c = (340003872375972UL>>(x*5-75))&31;
        M.h = i?(x!=19):0;
      }
    }
    if((M.t-=t-t0)<0.f)
    {
      if(t<6.f||!i||M.y!=6)
        M.y++;
      M.t += M.s;
    }
    char c=64|M.c%42;
    for(int j=0; j<M.h; j++,c=64|(c^M.c+M.h^j)%42)
      for(int f=(j+1==M.h)?13:4+(M.c&1);f--;)
        d->AddText(0, 13*(i?Z:-Z), V2(a.x-(sz.x*.5f*ZI)+x*8*Z+sin(j+t*f), a.y-(sz.y*.5f*ZI)+(M.y+j)*13*Z+cos(x*f-t)), 0x3c68bb5b, &c, &c+1);
    S|=((S&1)^((S&8)>>2))<<16;
    S>>=1;
  }
  t0 = t;
}

fx matrix 2

Tiny Loading Screen!

Had a bunch of fun trying to get this as small I could, managed to get it just under 600 bytes for now.

b0bapW4Ez9

#define V ImVec2
#define R d->AddRectFilled
#define C(x) IM_COL32((sin(x) + 1) * 255 / 2, (cos(x) + 1) * 255 / 2, 99, 255)
#include <set>
void FX(ImDrawList* d, V a, V b, V s, ImVec4, float t) {
  static auto z = 0.f;
  if (t > z + 2) z += 2;
  auto c = C(z + 2);
  R(a, b, C(z));
  for (auto B = b.x, i = 0.f, o = s.y / 8; i < 8; ++i, B = b.x) {
    if (auto w = (i / 7) * .2f, x = std::max(t - z - w, 0.f); t - z < w + 1)
      B = a.x + (x < .5 ? 8 * x * x * x * x : std::min(1 - pow(-2 * x + 2, 4.f) / 2, 1.f)) * s.x;
    R(V(a.x, a.y + o * i), V(B, a.y + o * i + o), c);
  }
}

Quicksort visualization.

#define V2 ImVec2
#include <vector>
#include <array>
using namespace std;
int N = 64, S, J;
#define V vector<int>
V v = [] {
    V r;
    for (; J < N; J++) r.push_back(rand() % 180);
    return r;
}();
vector<array<int,4>> st { { 0, N-1, 0, 0} };
#define A st.back()[0]
#define B st.back()[1]
#define I st.back()[2]
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4,float t)
{
    float bs = s.x / N, y, c;
    for (int i = 0; i < N; i++) {
        y=a.y+v[i];
        c=70+v[i];
        d->AddRectFilled(V2(a.x+bs*i,y),V2(a.x+bs*(i+1),b.y),IM_COL32(c,255-c,255,255));
    }
    d->AddText(a, -1u, "Quicksort");
    if (st.empty()) return;
    d->AddRect(V2(a.x+bs*A,a.y),V2(a.x+bs*(B+1),b.y),0xFF00FF00,8,ImDrawCornerFlags_Top,2);
    switch (S) {
    case 0:case 5: if(A>=B)st.pop_back(),S+=3;else I=J=A,S++;break;
    case 1:case 6:
        if(v[J]>v[B])swap(v[I],v[J]),I++;
        if(++J>B)swap(v[I],v[B]),S++;
        break;
    case 2:case 7:st.push_back({A,I-1,A,3});S=0;break;
    case 3:st.push_back({I+1,B,A,8});S=5;break;
    case 8:S = st.back()[3]; st.pop_back();
    }
}

sort
Blobs.

#define V2 ImVec2
void FX (ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    int N = 25;
    float sp = s.y / N, y, st = sin(t) * 0.5 + 0.5,
          r[3] = { 1500, 1087 + 200 * st, 1650 },
          ctr[3][2] = { { 150, 140 }, { s.x * m.x, s.y * m.y },
              { 40 + 200 * st, 73 + 20*sin(st * 5) } };
    for (int i = 0; i < N; i++) {
        y = a.y + sp*(i+.5);
        for (int x = a.x; x <= b.x; x += 2) {
            float D = 0, o = 255;
            for (int k = 0; k < 3; k++)
                D += r[k]/(pow(x-a.x-ctr[k][0], 2) + pow(y-a.y-ctr[k][1], 2));
            if (D < 1) continue;
            if (D>2.5) D = 2.5;
            if (D < 1.15) o /= 2;
            d->AddLine(V2(x, y), V2(x+2, y), IM_COL32(239, 129, 19, o), D + sin(2.3 * t + 0.3 * i));
        }
    }
}

o
3D cube.

#define V2 ImVec2
void FX (ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    a.x += s.x/2, a.y += s.y / 2;
    float S = sin(m.x), C = cos(m.x), x = 50, y, z = (m.y * 2 - 1) * x;
    float v[8][3] { { x, x, z+x }, { x, -x, z+x }, { -x, -x, z+x }, { -x, x, z+x },
            { x, x, z-x }, { x, -x, z-x }, { -x, -x, z-x }, { -x, x, z-x } };
    for (int i = 0; i < 8; i++) {
        x = v[i][0] * C - v[i][1] * S;
        y = v[i][0] * S + v[i][1] * C + 120;
        z = v[i][2];
        v[i][0] = x / y * 50;
        v[i][1] = z / y * 50;
        v[i][2] = y;
    }
#define L(A,B) z = 500 / (v[A][2] + v[B][2]); \
    d->AddLine(V2(a.x+v[A][0],a.y+v[A][1]),V2(a.x+v[B][0],a.y+v[B][1]),-1u,z);
    L(0, 1) L(1, 2) L(2, 3) L(0, 3)
    L(4, 5) L(5, 6) L(6, 7) L(4, 7)
    L(0, 4) L(1, 5) L(2, 6) L(3, 7)
}

cubes
Real-time visualization of the interweb blogosphere.

#define V2 ImVec2
#include <vector>
int N = 300;
auto v = [] {
    std::vector<std::pair<V2,V2>>r(N);
    for (auto&p:r)
        p.second = p.first = V2(rand() % 320, rand() % 180);
    return r;
}();
float l2 (V2 x) { return x.x*x.x + x.y*x.y; }
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4,float t)
{
    float D, T;
    for (auto&p:v) {
        D = sqrt(l2(p.first - p.second));
        if (D > 0) p.first += (p.second - p.first) / D;
        if (D < 4) p.second = V2(rand() % 320, rand() % 180);
    }
    for (int i = 0; i < N; i++) {
        for (int j = i+1; j < N; j++) {
            D = l2(v[i].first - v[j].first);
            T = l2((v[i].first + v[j].first) - s) / 200;
            if (T > 255) T = 255;
            if (D < 400) d->AddLine(a+v[i].first, a+v[j].first, IM_COL32(T, 255-T, 255, 70), 2);
        }
    }
}

interwebs

Here's my attempt at some abstract fireworks... with about four bytes to spare. The code has ended up pretty unreadable as a result, sadly.

````C++

define V ImVec2

define R rand()

define I int

define F float

define S ((F)R/32767)

define T(d,b,e)p[j].d=(b(j&1^j>>1?1:-1))+(e((j>1)?1:-1))+c.d+a.d;

define X(a)I a=128+(R&127);

struct P {F x,y,vx,vy,a;I l,s,f,d;};P p[8192]={0};
void A(V o, I f){P t;t.x=o.x;t.y=o.y;t.vx=S3-1.5;t.vy=S2.5-(f?4:1);t.l=R%(f?50:99);t.s=R;t.f=f;for(I j=0;j<9;j++){t.d=j;t.a=1-(F)j/9;for(I i=0;i<8192;i++)if(!p[i].l){p[i]=t;break;}}}
void FX(ImDrawList*d,V a,V b,V sz,V mn,F t0){I g=R;for(I i=200;i;--i)d->AddLine(V(a.x,a.y+i),V(b.x,a.y+i),IM_COL32(0,0,i,255));I e=0;for(I i=0;i<8192;i++){P&c=p[i];if(c.l){if(c.d)c.d--;else{srand(c.s);c.x+=c.vx;c.y+=c.vy;c.vy+=.04;c.l-=(c.vy>0)?1:0;F s=(S3+.1)(c.f+1);F n=(t0(c.l<0?0:1))+(i*S*2.5-1.5);F sa=sin(n)*s;F ca=cos(n)*s;V p[4];for(I j=0;j<4;j++){T(x,sa,ca);T(y,ca,-sa);}X(r)X(g)X(b)d->AddConvexPolyFilled(p,c.f?4:3,IM_COL32(r,g,b,(c.f?255:c.l)c.a));if(!c.l&&c.f&&c.a==1){I l=R%40+15;for(I j=0;j srand(g);if(e<512)A(V(S*420-50,200),1);}
````

Fireworks

Old school plasma.

ImDrawList_Party_Plasma

#define V2 ImVec2
#define S sinf
#define C cosf
#define I int
#define F float
#define CL(x,l,h) (((x)>(h))?(h):(((x)<(l))?(l):(x)))
#define PI 3.1415926535
#define CO(c,b) (int(c*255)<<b)
void FX(ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    t*=3;
    F ix=s.x/320;
    F iy=s.y/180;
    F sz=s.x / 15;
    for (F x=a.x;x<b.x;x+=ix)
        for (F y=a.y;y<b.y;y+=iy){
            F v=0;
            v+=S((x/sz+t));
            v+=S((y/sz+t)/2.0f);
            v+=S((x/sz+y/sz+t)/2.0f);
            F cx=x/sz/10+0.3*S(t/3.0);
            F cy=y/sz/10+0.3f*C(t/2.0);
            v+=S(sqrt(100*(cx*cx+cy*cy+1))+t);
            v=CL(v/2, 0, 1);
            F r=S(v*PI)*.5f+.5f;
            F g=S(v*PI+PI/3)*.5f+.5f;
            F b=S(v*PI+PI)*.5f+.5f;
            d->AddQuadFilled({x,y},{x+ix,y},{x+ix,y+iy},{x,y+iy},0xff000000|CO(b,16)|CO(g,8)|CO(r,0));
        }
}

Guitar for strumming. Unfortunately, requires that ImGuiWindowFlags_NoMove be set for the window in the testbed to work correctly. Using InvisibleButton instead of Dummy also works.

#define V2 ImVec2
#define C1 0xA7A830FF
#define C2 0x775839FF
float amp[6], ml;
int pk;
void FX(ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    if (m.z > -1)
        pk |= 2;
    m.y *= s.y; m.x *= s.x;
    m.y += a.y; m.x += a.x;
    float st = sin(10*t), th, y, w;
    d->AddRectFilledMultiColor(V2(a.x, a.y+40), V2(b.x, b.y-40), C1, C1, C2, C2);
    for (float i = a.x + 10, j = 20; i < b.x; i += (j += 10))
        d->AddRectFilled(V2(i, a.y+38), V2(i + 8, b.y-38), 0xFF888888, 8);
    for (int i = 0; i < 6; i++) {
        y = a.y + 48 + i * 16.6; th = 4-i*.5f; w = 1;
        int N = 10;
        for (int j = 0; j < N; j++) {
            float x = a.x + j * s.x / N, k = (w *= -1) * amp[i] * st;
            d->AddBezierCurve(V2(x,y+k),V2(x+10,y+k),V2(x+s.x/N-10,y-k),V2(x+s.x/N,y-k),-1u,th);
        }
        amp[i] *= 0.9;
        if (pk == 3) {
            float A=ml, B=m.y;
            if((A<=y&&B>y)||(A>=y&&B<y))amp[i]+=A-B;
        }
    }
    ml = m.y;
    if (pk >>= 1) d->AddTriangleFilled(V2(m.x, m.y), V2(m.x-15, m.y-15), V2(m.x+10, m.y-25), 0xFF0000FF);
}

guitar

Complementary colors I guess? I have to optimize the hell out of it to get it under 1K, the code looks so ugly now :'( But it's quite fun!

#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define fract(x) (abs(x-floor(x)))
#define rand(x,se) (fract(sin(x)*se))
#define eps 1e-3
#define V2 ImVec2
#define C 10000.0f
float mix(float a,float b,float v) {return a+(b-a)*v;}float ss(float a,float b,float v) {return mix(a,b,3.0f*v*v-2.0f*v*v*v);}float perlin(float v,float se) {v=v*0.7f+eps;float f=floor(v);float s=fract(v);float a=rand(f,se);float b=rand(f+1.0f,se);return ss(a,b,s);}float perlin_d(float v,float se) {v *= 2.0f;float f=floor(v);float s=fract(v);float a=rand(f,se);float b=rand(f+1.0f,se);return ss(a,b,s);}void FX(ImDrawList* d,ImVec2 a,ImVec2 b,ImVec2 sz,ImVec4 mouse,float t) {t *= 0.3f;float sa[]={255.0f,0.0f};float sb[]={125.0f,130.0f};float sc[]={0.0f,255.0f};for(int i=0;i<2;i++) {for(int x=0;x<sz.x;x++) {float p=0.5f+rand(1.0f,(C-sa[i]));float bt=perlin(x/sz.x+t*p,C-sa[i])*sz.y;float tp=perlin(x/sz.x+t*p,C-sb[i])*sz.y;float h=tp-bt;d->AddRectFilled(V2(a.x+x,a.y+bt),V2(a.x+x+1,a.y+bt+h),IM_COL32(sa[i],sb[i],sc[i],200));}}}

result

Unfortunately, requires that ImGuiWindowFlags_NoMove be set for the window in the testbed to work correctly.

I updated the test bed today (to 0.22) to use InvisibleButton() instead of Dummy() for the canvas, so it catches inputs.

Beautiful submissions everyone!

Snake Game (781 bytes)

#define v2 ImVec2
#define px(v,c) d->AddRectFilled(a+v*2,a+v*2+v2(2,2),c);
#define fr(v,x) for(int v=0;v<x;++v)
#define eq(l,r) l.x==r.x&l.y==r.y
#define kd(k) ImGui::IsKeyDown(ImGui::GetKeyIndex(k))
v2 sn[160*90]={{20,20}};
int ln=0,tg=4;
float lf;
v2 dr(1,0);
v2 fd(99,45);
void FX(ImDrawList* d, v2 a, v2 b, v2 sz, v2, float t)
{
    if (t-lf>0.033f){
        lf=t;
        if (ln<tg){ln++;sn[ln]=sn[ln-1];}
        else fr(x,ln)sn[x]=sn[x+1];
        sn[ln]+=dr;
        bool e=sn[ln].x<0|sn[ln].x>159|sn[ln].y<0|sn[ln].y>89;
        fr(x,ln-1)e|=eq(sn[x],sn[ln]);
        if(e)ln=0,tg=4,sn[0]={20,20};
        if(eq(sn[ln],fd))tg+=4,fd={rand()%150+5.f,rand()%80+5.f};
        if(kd(1))dr={-1,0};
        if(kd(2))dr={1,0};
        if(kd(3))dr={0,-1};
        if(kd(4))dr={0,1};
    }

    fr(x,ln+1)px(sn[x],-1);
    px(fd,-256);
}

imgui_snake

Mosaic. It wasn't what I was trying to do, but ended up in a neat place.

#define v2 ImVec2
#define wh(a) ImColor(1.f,1.f,1.f,a)
#define px(v,c) d->AddRectFilled(a+v*2,a+v*2+v2(2,2),c);
#define fr(v,x) for(int v=0;v<x;++v)
#define frc(x) ((x)-int(x))
#define hash(x) (srand(x),ImLerp(rand()/32767.f,rand()/32767.f,0.5f))
#define noise(x) ImLerp(hash(x),hash(x+1),frc(x))
void FX(ImDrawList* d, v2 a, v2 b, v2 sz, v2 mm, float t)
{
    fr(x,160)fr(y,90){
        auto rx=x-80;
        auto ry=y-45;
        auto an=ImAtan2(rx,ry);an=an<0?M_PI*2+an:an;
        auto len=(rx*rx+ry*ry+0.1f)+t*4;
        auto n0 = noise(an);
        auto n1 = noise(len);
        auto al= n0+n1;
        px(v2(x,y),wh(al));
    }
}

imgui_noise

Hershey vectorial font! 3.8 KiB. I have not stripped the ASCII chars in the font to make the code fit under 1KiB, bc I wanted to make something useful as well. Sorry for breaking the rules! :D

void Hershey(ImDrawList* d, ImVec2 pos, ImVec2 sca, ImVec2 old, char *s) {
 static const char *fnt[] = {
 "AQ","IKFVFH@@FCEBFAGBFC","FQEVEO@@MVMO","LVLZE:@@RZK:@@EMSM@@DGRG","[UIZI=@@MZ"
 "M=@@RSPUMVIVFUDSDQEOFNHMNKPJQIRGRDPBMAIAFBDD","`YVVDA@@IVKTKRJPHOFODQDSEUGVIVK"
 "UNTQTTUVV@@RHPGOEOCQASAUBVDVFTHRH","c[XMXNWOVOUNTLRGPDNBLAHAFBECDEDGEIFJMNNOOQ"
 "OSNULVJUISIQJNLKQDSBUAWAXBXC","HKFTEUFVGUGSFQEP","KOLZJXHUFQELEHFCH?J<L:","KOD"
 "ZFXHUJQKLKHJCH?F<D:","IQIVIJ@@DSNM@@NSDM","F[NSNA@@EJWJ","IKGBFAEBFCGBG@F>E=",\
 "C[EJWJ","FKFCEBFAGBFC","CWUZC:","RUJVGUERDMDJEEGBJALAOBQERJRMQROULVJV","EUGRIS"
 "LVLA","OUEQERFTGUIVMVOUPTQRQPPNNKDARA","PUFVQVKNNNPMQLRIRGQDOBLAIAFBECDE","GUN"
 "VDHSH@@NVNA","RUPVFVEMFNIOLOONQLRIRGQDOBLAIAFBECDE","XUQSPUMVKVHUFREMEHFDHBKAL"
 "AOBQDRGRHQKOMLNKNHMFKEH","FURVHA@@DVRV","^UIVFUESEQFOHNLMOLQJRHREQCPBMAIAFBECD"
 "EDHEJGLJMNNPOQQQSPUMVIV","XUQOPLNJKIJIGJELDODPESGUJVKVNUPSQOQJPENBKAIAFBED","L"
 "KFOENFMGNFO@@FCEBFAGBFC","OKFOENFMGNFO@@GBFAEBFCGBG@F>E=","DYUSEJUA","F[EMWM@@"
 "EGWG","DYESUJEA","USDQDRETFUHVLVNUOTPRPPONNMJKJH@@JCIBJAKBJC","x\\SNRPPQMQKPJO"
 "ILIIJGLFOFQGRI@@MQKOJLJIKGLF@@SQRIRGTFVFXHYKYMXPWRUTSUPVMVJUHTFREPDMDJEGFEHCJB"
 "MAPASBUCVD@@TQSISGTF","ISJVBA@@JVRA@@EHOH","XVEVEA@@EVNVQURTSRSPRNQMNL@@ELNLQK"
 "RJSHSERCQBNAEA","SVSQRSPUNVJVHUFSEQDNDIEFFDHBJANAPBRDSF","PVEVEA@@EVLVOUQSRQSN"
 "SIRFQDOBLAEA","LTEVEA@@EVRV@@ELML@@EARA","ISEVEA@@EVRV@@ELML","WVSQRSPUNVJVHUF"
 "SEQDNDIEFFDHBJANAPBRDSFSI@@NISI","IWEVEA@@SVSA@@ELSL","CIEVEA","KQMVMFLCKBIAGA"
 "EBDCCFCH","IVEVEA@@SVEH@@JMSA","FREVEA@@EAQA","LYEVEA@@EVMA@@UVMA@@UVUA","IWEV"
 "EA@@EVSA@@SVSA","VWJVHUFSEQDNDIEFFDHBJANAPBRDSFTITNSQRSPUNVJV","NVEVEA@@EVNVQU"
 "RTSRSORMQLNKEK","YWJVHUFSEQDNDIEFFDHBJANAPBRDSFTITNSQRSPUNVJV@@MES?","QVEVEA@@"
 "EVNVQURTSRSPRNQMNLEL@@LLSA","UURSPUMVIVFUDSDQEOFNHMNKPJQIRGRDPBMAIAFBDD","FQIV"
 "IA@@BVPV","KWEVEGFDHBKAMAPBRDSGSV","FSBVJA@@RVJA","LYCVHA@@MVHA@@MVRA@@WVRA",""
 "FUDVRA@@RVDA","GSBVJLJA@@RVJL","IURVDA@@DVRV@@DARA","LOEZE:@@FZF:@@EZLZ@@E:L:",
 "COAVO>","LOJZJ:@@KZK:@@DZKZ@@D:K:","KQGPISKP@@DMIRNM@@IRIA","CQA?Q?","HKGVFUES"
 "EQFPGQFR","RTPOPA@@PLNNLOIOGNELDIDGEDGBIALANBPD","RTEVEA@@ELGNIOLONNPLQIQGPDNB"
 "LAIAGBED","OSPLNNLOIOGNELDIDGEDGBIALANBPD","RTPVPA@@PLNNLOIOGNELDIDGEDGBIALANB"
 "PD","RSDIPIPKOMNNLOIOGNELDIDGEDGBIALANBPD","IMKVIVGUFRFA@@COJO","WTPOP?O<N;L:I"
 ":G;@@PLNNLOIOGNELDIDGEDGBIALANBPD","KTEVEA@@EKHNJOMOONPKPA","IIDVEUFVEWDV@@EOE"
 "A","LKFVGUHVGWFV@@GOG>F;D:B:","IREVEA@@OOEE@@IIPA","CIEVEA","S_EOEA@@EKHNJOMOO"
 "NPKPA@@PKSNUOXOZN[K[A","KTEOEA@@EKHNJOMOONPKPA","RTIOGNELDIDGEDGBIALANBPDQGQIP"
 "LNNLOIO","RTEOE:@@ELGNIOLONNPLQIQGPDNBLAIAGBED","RTPOP:@@PLNNLOIOGNELDIDGEDGBI"
 "ALANBPD","INEOEA@@EIFLHNJOMO","RROLNNKOHOENDLEJGILHNGOEODNBKAHAEBDD","IMFVFEGB"
 "IAKA@@COJO","KTEOEEFBHAKAMBPE@@POPA","FQCOIA@@OOIA","LWDOHA@@LOHA@@LOPA@@TOPA",
 "FRDOOA@@OODA","JQCOIA@@OOIAG=E;C:B:","IROODA@@DOOO@@DAOA","hOJZHYGXFVFTGRHQIOI"
 "MGK@@HYGWGUHSIRJPJNILEJIHJFJDIBHAG?G=H;@@GIIGIEHCGBF@F>G<H;J:","CIEZE:","hOFZH"
 "YIXJVJTIRHQGOGMIK@@HYIWIUHSGRFPFNGLKJGHFFFDGBHAI?I=H;@@IIGGGEHCIBJ@J>I<H;F:",""
 "XYDGDIELGMIMKLOIQHSHUIVK@@DIEKGLILKKOHQGSGUHVKVM" };
 for( char c, *glyph; (c = *s++, glyph = (char*)fnt[c - 32], c > 0 && c < 127); ) {
  if( c != '\n' && c != '\r' ) {
   if( c > 32 ) for( int pen = 0, i = 0; i < (glyph[0] - 65); i++ ) {
    int x = glyph[2 + i*2 + 0] - 65, y = glyph[2 + i*2 + 1] - 65;
    if( x == -1 && y == -1 ) pen = 0; else {
     ImVec2 next = ImVec2(pos.x+sca.x*x, pos.y-sca.y*y);
     if( !pen ) pen = 1; else d->AddLine(old, next, 0.9*(ImU32)-1);
     old = next;
    }
   }
   pos.x += sca.x * (glyph[1] - 65);
  }
 }
}
void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 mouse, float t) {
 ImVec2 pos(a.x,((a+b)/2).y), sca(1,sin(t*5)+1+0.5f);
 char str[128]; sprintf(str, "Hello imgui! %5.2fs", t);
 Hershey(d, pos, sca, ImVec2(), str);
}

GIF 11-20-2020 10-58-19 PM

Ugly Doom Fire
doomfire

#define V2 ImVec2
#define W 64
#define H 48
#define S 0x07
#define T 0x1F
#define U 0x0F
#define I int
#define F float
I w=0,P[]={S,S,S,T,S,S,0x2F,U,S,0x47,U,S,0x57,0x17,S,0x67,T,S,0x77,T,S,0x8F,0x27,S,0x9F,0x2F,S,0xAF,0x3F,S,0xBF,0x47,S,0xC7,0x47,S,0xDF,0x4F,S,0xDF,0x57,S,0xDF,0x57,S,0xD7,0x5F,S,0xD7,0x5F,S,0xD7,0x67,U,0xCF,0x6F,U,0xCF,0x77,U,0xCF,0x7F,U,0xCF,0x87,0x17,0xC7,0x87,0x17,0xC7,0x8F,0x17,0xC7,0x97,T,0xBF,0x9F,T,0xBF,0x9F,T,0xFF,0xFF,0xFF};
char i[W*H];
void FX(ImDrawList *d,V2 a,V2 b,V2 sz,ImVec4,F t){if(!w){memset(i,0,W*H);memset(i+(H-1)*W,27,W);w=1;}for(I x=0;x<W;x++){for(I y=1;y<H;y++){I j=y*W+x,p=i[j];if(!p)i[j-W]=0;else{I r=I(3.f*rand()/RAND_MAX),d=j-r+1;i[d-W]=p-(r&1);}}};I j=0;F sx=1.f/W,sy=1.f/H,k=0.45f,ty=0;for(I y=0;y<H;y++,ty+=sy){F tx=0;for(I x=0;x<W;x++,tx+=sx){V2 c((tx+.5f*sx),(ty+.5f*sy));I *z=P+i[j++]*3;d->AddRectFilled(V2(a.x+(c.x-k*sx)*sz.x,a.y+(c.y-k*sy)*sz.y),V2(a.x+(c.x+k*sx)*sz.x,a.y+(c.y+k*sy)*sz.y),IM_COL32(z[0],z[1],z[2],255));}}}

This one (The Business Card Raytracer from Paul Heckbert) is too big 1 510 bytes 😢 but still fun
aek

#define V2 ImVec2
#define op operator
#define rt return
typedef int i;typedef float f;struct v{f x,y,z;v op+(v r){rt v(x+r.x,y+r.y,z+r.z);}v op*(f r){rt v(x*r,y*r,z*r);}f op%(v r){rt x*r.x+y*r.y+z*r.z;}v(){}v op^(v r){rt v(y*r.z-z*r.y,z*r.x-x*r.z,x*r.y-y*r.x);}v(f a,f b,f c){x=a;y=b;z=c;}v op!(){rt*this*(1/sqrt(*this%*this));}};i G[]={247570,280596,280600,249748,18578,18577,231184,16,16};f R(){rt(f)rand()/RAND_MAX;}i T(v o,v d,f&t,v&n){t=1e9;i m=0;f p=-o.z/d.z;if(.01<p)t=p,n=v(0,0,1),m=1;for(i k=19;k--;)for(i j=9;j--;)if(G[j]&1<<k){v p=o+v(-k,0,-j-4);f b=p%d,c=p%p-1,q=b*b-c;if(q>0){f s=-b-sqrt(q);if(s<t&&s>.01)t=s,n=!(p+d*t),m=2;}}rt m;}v S(v o,v d){f t;v n;i m=T(o,d,t,n);if(!m)rt v(.7,.6,1)*pow(1-d.z,4);v h=o+d*t,l=!(v(9+R(),9+R(),16)+h*-1),r=d+n*(n%d*-2);f b=l%n;if(b<0||T(h,l,t,n))b=0;f p=pow(l%r*(b>0),99);if(m&1){h=h*.2;rt((i)(ceil(h.x)+ceil(h.y))&1?v(3,1,1):v(3,3,3))*(b*.2+.1);}rt v(p,p,p)+S(h,r)*.5;}
v img[512*512];i y=512;void FX(ImDrawList*d,V2 z,V2,V2 sz,ImVec4,f){v g=!v(-6,-16,0),a=!(v(0,0,1)^g)*.002,b=!(g^a)*.002,c=(a+b)*-256+g;f sx=1.f/512.f;f sy=1.f/512.f;if(y){y--;for(i x=512;x--;){v p(13,13,13);for(i r=64;r--;){v t=a*(R()-.5)*99+b*(R()-.5)*99;p=S(v(17,16,8)+t,!(t*-1+(a*(R()+x)+b*(y+R())+c)*16))*3.5+p;}img[y*512+x]=p;}}v*img2=img;f k=0.45f;for(f ty=1.0f;ty;ty-=sy)for(f tx=1.0f;tx;tx-=sx){V2 u((tx+0.5f*sx),(ty+0.5f*sy));v q=*img2++;d->AddRectFilled(V2(z.x+(u.x-k*sx)*sz.x,z.y+(u.y-k*sy)*sz.y),V2(z.x+(u.x+k*sx)*sz.x,z.y+(u.y+k*sy)*sz.y),IM_COL32((i)q.x,(i)q.y,(i)q.z,255));}}

tribute to https://tixy.land/ 473 bytes
ezgif com-gif-maker

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
   int i =0;
   for (int y = 0;y <= sz.y *0.2;y++)
   {
      for (int x = 0;x<=sz.x * 0.2;x++, i++)
      {
         //float v = cos(t * cos(i * 2)) * cos(i * cos(x * 2));
         float v = tan(t * cos(i * 2))* sin(i * cos(x * 2));
         v = ImClamp(v, -1.f, 1.f);
         d->AddCircleFilled(V2(x * 10 + a.x,y * 10 + a.x), 5 * fabsf(v), (v>0.f)?0xFFFFFFFF:0xFF0000FF, 12);
      }
   }
}

Yet another entry because it's a lot of fun!
I tried to emulate DOF with alpha and bigger disks.
ezgif com-gif-maker (1)

800 bytes

#define V2 ImVec2
#define F float
F k;
int i{};
F r() { return F(rand() / 32768.f) * 2.f - 1.f; };
struct P {F x,y,z,a,b,c;void A(){x+=a*k;y+=b*k;z+=c*k;
F ng{0.008f};z-=5.f;F xp=x*cosf(ng)-z*sinf(ng);F zp=x*sinf(ng)+z*cosf(ng);
x=xp;z=zp+5.f;a-=x*k+r()*k;b-=y*k+r()*k;c-=(z-5.0f)*k+r()*k;}};
P p[64];
void FX(ImDrawList* d, V2 o, V2 b, V2 sz, ImVec4, F t)
{int j{};
if (!i) {i=1;for (P&a:p){a={r(),r(),r()+5.f,r(),r(),r() };}}
for (P&a:p){
if (a.z<0.001) continue;
V2 s((a.x/a.z)*sz.x*2.f+sz.x*0.5f+o.x,(a.y/a.z)*sz.y*2.f+sz.y*0.5f+o.y);
int x=(j++)%16;
k=cosf((j/64.f)*3.14592f)*0.002f+0.002f;
F dist=fabsf(a.z-5.f)/2.5f,sc=(10.f+dist*100.f)/a.z;
int tr=int(ImMin(dist*128.f,128.f)+127)<<24;
ImColor col=ImColor::HSV(k*9.f+0.06f,0.8f,1.f,1.f-sqrtf(dist));
d->AddCircleFilled(s,sc,col,12);a.A();
}}

A Breakout/Arkanoid type of game implementation in 1014 bytes. (Control paddle with mouse, use right-click to reset)

ImDrawList_Party_Breakout

#define V2 ImVec2
#define I int
#define F float
#define B bool
#define T static
#define W 320
#define H 180
#define FR(i,m) for(I i=0;i<m;++i)
#define C 0xffffffff
struct B2{V2 l,h;B a=1;B in(V2 p){return(p.x>l.x&&p.x<h.x)&&(p.y>l.y&&p.y<h.y);}};
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4 m,float t)
{T B re=1;T F cx,cy,r,vx,vy;T F lt=t;T F dt=0;T F bw=W/10;T F bh=H/12;T B2 br[60];T B2 p{{0,b.y-5},{0,b.y}};if(re){cx=a.x+W/2;cy=a.y+H-8;r=3;vx=-1;vy=-3;FR(i,6)FR(j,10){B2& b=br[j+i*10];b.a=1;b.l={a.x+j*bw,a.y+i*bh};b.h={a.x+(j+1)*bw,a.y+(i+1)*bh};}re=0;}FR(i,60){B2& b=br[i];if(!b.a)continue;if(!b.in({cx,cy}))continue;b.a=0;F ol=cx-b.l.x;F or=b.h.x-cx;F ot=cy-b.l.y;F ob=b.h.y-cy;F ox=min(ol,or);F oy=min(ot,ob);B lo=ol<ob;B to=ot<ob;ox<oy?vx=-vx:vy=-vy;}dt=t-lt;lt=t;p.l.x=a.x+m.x*s.x-20;p.h.x=p.l.x+40;if(p.in({cx,cy}))vy=-vy;FR(i,60){if(br[i].a)d->AddRect(br[i].l,br[i].h,C);}d->AddRect(p.l,p.h,C);d->AddCircle({cx,cy},r,C);cx+=vx*dt*30;cy+=vy*dt*30;if(cx<a.x||cx>b.x)vx=-vx;if(cy<a.y)vy=-vy;if (!m.w)re=1;}

Update:
@ocornut 's suggestion on Twitter made we want to push it a little further and here it is in 1024 bytes with colors

ImDrawList_Party_Breakout2

using V=ImVec2;using I=int;using F=float;using B=bool;
#define T static
#define W 320
#define H 180
#define FR(i,m) for(I i=0;i<m;++i)
#define A d->AddRectFilled
struct B2{V l,h;B a=1;I c=~0;B in(V p){return(p.x>l.x&&p.x<h.x)&&(p.y>l.y&&p.y<h.y);}};
void FX(ImDrawList* d,V a,V b,V s,ImVec4 m,float t){T B re=1;T F cx,cy,r,vx,vy;T F lt=t;T F dt=0;T F bw=W/10;T F bh=H/12;T B2 br[60];T B2 p{{0,b.y-5},{0,b.y}};if(re){cx=a.x+W/2;cy=a.y+H-8;r=3;vx=-1;vy=-3;FR(i,6)FR(j,10){B2& b=br[j+i*10];b.a=1;b.l={a.x+j*bw,a.y+i*bh};b.h={a.x+(j+1)*bw,a.y+(i+1)*bh};b.c=255<<24|rand();}re=0;}FR(i,60){B2& b=br[i];if(!b.a)continue;if(!b.in({cx,cy}))continue;b.a=0;F ol=cx-b.l.x;F or=b.h.x-cx;F ot=cy-b.l.y;F ob=b.h.y-cy;F ox=min(ol,or);F oy=min(ot,ob);B lo=ol<ob;B to=ot<ob;ox<oy?vx=-vx:vy=-vy;}dt=t-lt;lt=t;p.l.x=a.x+m.x*s.x-20;p.h.x=p.l.x+40;if(p.in({cx,cy}))vy=-vy;FR(i,60){B2& b=br[i];if(b.a)A(b.l,b.h,b.c);}A(p.l,p.h,~0);d->AddCircleFilled({cx,cy},r,~0);cx+=vx*dt*30;cy+=vy*dt*30;if(cx<a.x||cx>b.x)vx=-vx;if(cy<a.y)vy=-vy;if (!m.w)re=1;}

Came across this by accident. I think it looks quite cool.

imdrawlist-party-1

521 bytes

#define V ImVec2
#define CF d->AddCircleFilled
#define RAND(a) (float)rand()/(float)(RAND_MAX/a)
void FX(ImDrawList*d,V a,V b,V s,ImVec4 m,float t) {
 static bool o = true;
 static V bs[1000];
 if(o){
  o=false;
  for(int i=0;i<1000;++i){
   float g=RAND(IM_PI/2)+(IM_PI/4);
   float r=RAND(50)+5;
   bs[i]=V(g,r);
  }
 }
 for(int i=0;i<1000;++i){
  float
   g=bs[i].x,
   r=bs[i].y;
  r+=sin(t+i)*100;
  CF(V(r*cos(g),r*sin(g))+(s/2+a)+V(r*cos(t),0),i%2+1,IM_COL32(r+100,50,fabs(r)+100,200));
 }
}

I did a poor man’s tetris
I’d like top put some more features (like, detection for when the game is lost, for example [mostly done]), but I’m at 1021 994 1024 bytes, so I can’t really add more

By the way, I also took the liberty to change from mouse_data.y = (io.MousePos.y - p1.y) / size.y; to mouse_data.y = (io.MousePos.y - p0.y) / size.y; in the gist, so that it corresponds to the specs on the OP

In case anyone wonders about the controls : the piece follows the mouse’s _y_ coordinate, mouse left click rotates it, and right click accelerates it.

tetris
disclaimer: colors were modified to squeeze some space for end-game detection

source code (1024 bytes)

#define F(a,b)for(I a=b;a--;)
#define S(a,b)s(c[a],c[b]);
#define I int
#define V ImVec2
#define L(w,z) d->AddLine(a+V(p,y)*8,a+V(p+w,y+z)*8,g-1^~0);
#define P(x,y) a+V(x,y)*8,a+V(x+1,y+1)*8
#define R(x,y,c) d->AddRectFilled(P(x,y),c);
I g=1;I pc[][9]={{1,1,1},{1,1,0,1,1},{1,1,1,0,1},{1,1,1,1},{1,1,1,0,0,1},{1,1,0,0,1,1},{0,1,1,1,1}};I*c=0;I p=0;I f=0;I T[41][21];void s(I&a,I&b){I d=a;a=b;b=d;}void FX(ImDrawList * d,V a,V,V,ImVec4 m,float t){F(i,21)T[40][i]=1;if(!p)F(i,40){c=pc[(I)t%7];I s=-21;F(j,21)s+=T[i][j];if(!s){F(j,i)F(k,21)T[j+1][k]=T[j][k];++i;}}if(!m.z){S(0,6)S(1,5)S(2,8)S(3,7)S(3,5)S(0,8)}I y=m.y*23-1.;if(y<0){if(!(c[0]|c[1]|c[2]))F(i,3){c[i]=c[i+3];c[i+3]=c[i+6];c[i+6]=0;}y=0;}if(y>18){if(!(c[6]|c[7]|c[8]))F(i,3){c[i+6]=c[i+3];c[i+3]=c[i];c[i]=0;}y=18;}p+=m.w>0|!(++f%8);F(i,3)F(j,3)if(c[j*3+i]&T[p+i+1][y+j]){F(k,3)F(l,3)T[p+k][y+l]|=g&c[l*3+k];p=0;}F(i,21)g&=!T[0][i];F(i,40)F(j,21)if(T[i][j])R(i,j,g?~0xFDA:~0)if(g)F(i,3)F(j,3)if(c[j*3+i])R(i+p,j+y,~0xFF14)L(3,0)L(0,3)p+=3;y+=3;L(0,-3)L(-3,0)p-=3;}

expanded source code (3409 bytes)

#include <algorithm>
#include <numeric>

static int board[41][21];
static int pieces_list[][9] = {
        {1, 1, 1,
         0, 0, 0,
         0, 0, 0},
        {0, 1, 1,
         0, 1, 1,
         0, 0, 0},
        {1, 1, 1,
         0, 1, 0,
         0, 0, 0},
        {1, 1, 1,
         1, 0, 0,
         0, 0, 0},
        {1, 1, 1,
         0, 0, 1,
         0, 0, 0},
        {1, 1, 0,
         0, 1, 1,
         0, 0, 0},
        {0, 1, 1,
         1, 1, 0,
         0, 0, 0}};

static int * current_piece = nullptr;
static int piece_pos = 0;
static int frame_count = 0;
static int game_ongoing = 1;

void FX(ImDrawList * d, ImVec2 a, ImVec2, ImVec2, ImVec4 mouse, float t) {
    ++frame_count;

    std::fill_n(board[40], 21, 1);// could be done only once

    if (piece_pos == 0) {
        for (int i = 39; i >= 0; --i) {
            current_piece = pieces_list[static_cast<int>(t) % 7];// selecting new piece (such randomness)

            if (std::accumulate(board[i], board[i] + 21, 0) == 21) {// checking for full line
                for (int j = i; j > 0; --j) {
                    for (int k = 0; k < 21; ++k) {
                        board[j + 1][k] = board[j][k];
                    }
                }
                ++i;// rollback
            }
        }
    }

    if (mouse.z == 0.f) {// rotating piece
        int copy[9]{};
        std::copy(current_piece, current_piece + 9, copy);
        current_piece[0] = copy[2];
        current_piece[1] = copy[5];
        current_piece[2] = copy[8];
        current_piece[3] = copy[1];
        current_piece[5] = copy[7];
        current_piece[6] = copy[0];
        current_piece[7] = copy[3];
        current_piece[8] = copy[6];
    }

    int y = mouse.y * 23 - 1.;// piece y coord
    if (y < 0) {
        if (!current_piece[0] && !current_piece[1] && !current_piece[2]) {
            for (int i = 0; i < 3; ++i) {
                current_piece[i] = current_piece[i + 3];
                current_piece[i + 3] = current_piece[i + 6];
                current_piece[i + 6] = 0;
            }
        }
        y = 0;

    } else if (y > 18) {
        if (!current_piece[6] && !current_piece[7] && !current_piece[8]) {
            for (int i = 0; i < 3; ++i) {
                current_piece[i + 6] = current_piece[i + 3];
                current_piece[i + 3] = current_piece[i];
                current_piece[i] = 0;
            }
        }
        y = 18;
    }

    if (mouse.w > 0 || frame_count % 8 == 0) {
        ++piece_pos;
    }

    bool collided = false;
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {

            if (current_piece[j * 3 + i] && board[piece_pos + i + 1][y + j]) {
                collided = true;
            }
        }
    }

    if (collided) {
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (game_ongoing && current_piece[j * 3 + i]) {
                    board[piece_pos + i][y + j] = 1;
                }
            }
        }
        piece_pos = 0;
    }

    if (std::accumulate(board[0], board[0] + 21, 0) != 0) {
        // game lost
        game_ongoing = 0;
    }


    for (int i = 0; i < 40; ++i) {
        for (int j = 0; j < 21; ++j) {
            if (board[i][j]) {
                d->AddRectFilled(a + ImVec2(i, j) * 8, a + ImVec2(i + 1, j + 1) * 8, game_ongoing ? IM_COL32(37,240,255,255) : IM_COL32_WHITE);
            }
        }
    }

    if (game_ongoing) {
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (current_piece[j * 3 + i]) {
                    d->AddRectFilled(a + ImVec2(i + piece_pos, j + y) * 8, a + ImVec2(i + piece_pos + 1, j + y + 1) * 8, IM_COL32(235,0,255,255));
                }
            }
        }

        d->AddLine(a + ImVec2(piece_pos, y) * 8, a + ImVec2(piece_pos + 3, y) * 8, IM_COL32_WHITE);
        d->AddLine(a + ImVec2(piece_pos, y) * 8, a + ImVec2(piece_pos, y + 3) * 8, IM_COL32_WHITE);
        d->AddLine(a + ImVec2(piece_pos + 3, y + 3) * 8, a + ImVec2(piece_pos + 3, y) * 8, IM_COL32_WHITE);
        d->AddLine(a + ImVec2(piece_pos + 3, y + 3) * 8, a + ImVec2(piece_pos, y + 3) * 8, IM_COL32_WHITE);
    }
}

I made a Mandelbrot set visualization with mouse-centered zoom/de-zoom:

Mandelbrot

I also took the liberty to change from mouse_data.y = (io.MousePos.y - p1.y) / size.y; to mouse_data.y = (io.MousePos.y - p0.y) / size.y; in the gist, so that it corresponds to the specs on the OP


Source code (1024 bytes)

#include <complex>

ImVec2 shift(-2.12,-0.9);
float scale = 0.01;
float zoom_factor = 0.9;
size_t max_iter = 32;

void FX(ImDrawList* d, ImVec2 a, ImVec2, ImVec2 sz, ImVec4 m, float)
{
    if((m.x >= 0 && m.x <= 1 && m.y >= 0 && m.y <= 1) && (m.z > 0 || m.w > 0))
    {
        float zf = m.z > 0 ? zoom_factor : 1 / zoom_factor;
        shift.x -= (m.x * sz.x * scale * (zf - 1));
        shift.y -= (m.y * sz.y * scale * (zf - 1));
        scale *= zf;
    }

    for(size_t x = 0; x < sz.x; ++x)
    {
        for (size_t y = 0; y < sz.y; ++y)
        {
            std::complex<double> c(shift.x + x /(sz.x-1.0)*(sz.x * scale), shift.y + y /(sz.y-1.0)*(sz.y * scale)), z;

            size_t iter;
            for (iter = 0; iter < max_iter && std::abs(z) < 2.0; ++iter)
                z = z * z + c;

            double v = std::log(iter) / std::log(max_iter - 1);
            if(iter < max_iter)
                d->AddRectFilled(ImVec2(a.x+ x,a.y+ y), ImVec2(a.x+ x +1,a.y+ y +1), IM_COL32((v*255), 255-(v*255), 255, 255));
            else
                d->AddRectFilled(ImVec2(a.x+ x,a.y+ y), ImVec2(a.x+ x +1,a.y+ y +1), IM_COL32(0, 0,0, 255));
        }
    }
}

Mandatory tunnel 971 bytes

#define V2 ImVec2
#define F float
V2 conv(V2 v, F z, V2 sz, V2 o){return V2((v.x/z)*sz.x*5.f+sz.x*0.5f,(v.y/z)*sz.y*5.f+sz.y*0.5f)+o;}
V2 R(V2 v, F ng){ng*=0.1f;return V2(v.x*cosf(ng)-v.y*sinf(ng),v.x*sinf(ng)+v.y*cosf(ng));}
void FX(ImDrawList* d, V2 o, V2 b, V2 sz, ImVec4, F t){d->AddRectFilled(o,b,0xFF000000,0);t*=4;
for (int i = 0; i < 20; i++){
F z=21.-i-(t-floorf(t))*2.,ng=-t*2.1+z,ot0=-t+z*0.2,ot1=-t+(z+1.)*0.2,os=0.3;
V2 s[]={V2(cosf((t+z)*0.1)*0.2+1.,sinf((t+z)*0.1)*0.2+1.),V2(cosf((t+z+1.)*0.1)*0.2+1.,sinf((t+z+1.)*0.1)*0.2+1.)};
V2 of[]={V2(cosf(ot0)*os,sinf(ot0)*os),V2(cosf(ot1)*os,sinf(ot1)*os)};
V2 p[]={V2(-1,-1),V2(1,-1),V2(1,1),V2(-1,1)};
ImVec2 pts[8];int j;
for (j=0;j<8;j++){int n = (j/4);pts[j]=conv(R(p[j%4]*s[n]+of[n],ng+n),(z+n)*2.,sz,o);}
for (j=0;j<4;j++){V2 q[4]={pts[j],pts[(j+1)%4],pts[((j+1)%4)+4],pts[j+4]};
F it=(((i&1)?0.5:0.6)+j*0.05)*((21.-z)/21.);
d->AddConvexPolyFilled(q,4,ImColor::HSV(0.6+sinf(t*0.03)*0.5,1,sqrtf(it)));
}}}

ezgif com-gif-maker (2)

Awesome stuff so far.

I started by looking at some of the first entries, and decided to play with circles. So I went on googling for something to find some inspiration, and I though it would be cool to replicate this: Black and White Minimal Circles
by Colin Saunders
.

Anyway, while playing with the drawing algorithm something went wrong and I ended up with an out of control Death Star laser-shooting randomly onto the galaxy!

Death Star - 926 bytes

#define V2 ImVec2
#define CR(o,r,c) d->AddCircle(o,r,c)
#define LN(a,b,c) d->AddLine(a,b,c)
#define FORI(n) for(int i=0;i<n;++i)
void FX(ImDrawList*d,V2 a,V2 b,V2 sz,ImVec4,float t){
    static float pr{t}, tm{};
    static auto st=[](){ImVector<V2> v; v.resize(512); FORI(512) v[i]=V2(rand()%480,rand()%270); return v;}();
    V2 hsz{sz/2}, o{a+hsz}, dir{sinf(tm),cosf(tm)}, c, sf;
    float dt{}, rad{hsz.y*0.7}, r;
    int cnt{rad/2}, sh{!(int(t)%2)}, inc;
    FORI(512) CR(st[i],1,0xFF333333);
    if(!sh) dt=t-pr,tm+=dt;
    pr=t;
    ImU32 BL{0xFF000000}, WH{0xFFFFFFFF}, G{0xFF00FF00};
    FORI(cnt){r=rad-i,inc=i; c={o.x+inc*dir.x,o.y+inc*dir.y}; CR(c,r,WH);}
    V2 la{o.x-rad,o.y}, lb{o.x+rad,o.y};
    LN(la,lb,BL);
    FORI(cnt){r=rad-(cnt+i), inc=(cnt-i); c={o.x+inc*dir.x,o.y+inc*dir.y}; CR(c,r,WH);}
    if(sh){la=o+dir*rad/8; lb=o+dir*hsz.x*2; sf={3*sinf(t*1024),3*cosf(t*1024)}; LN(la,lb,G); LN(la+sf,lb+sf,G); LN(la-sf,lb-sf,G);}
}

death-star

Following the Mandelbrot set visualization, this time I made a Julia sets visualization:

Julia

Inspired by this Wikipedia gif, the Julia sets represented are generated by

z^{2} + 0.7885 e^{ia}

where a ranges from 0 to 2π.


Source code (1024 bytes)

#include <complex>
#define C(r,g,b) IM_COL32(255*(r), 255*(g), 255*(b), 255)
size_t max_iter = 256;
float color_f = 48.0;
float speed_f = 2.0;

ImU32 to_color(float v)
{
    v = 1.f - std::log(v * color_f+1) / std::log(color_f+1);
    size_t p = v * 5.0;
    double g = (v * 5.0 - p);
    ImU32 colors[] = {C(1, 0, 1-g),C(1, g, 0),C(1-g, 1, 0),C(0, 1, g),C(0, 1-g, 1),C(0, 0, 1),};
    return colors[p];
}
void FX(ImDrawList* d, ImVec2 a, ImVec2, ImVec2 sz, ImVec4, float t)
{
    for (size_t x = 0; x < sz.x; ++x)
        for (size_t y = 0; y < sz.y; ++y)
        {
            std::complex<double> z(-2.1+x/(sz.x-1.0)*(sz.x*0.013), -1.15+y/(sz.y-1.0)*(sz.y*0.013));
            std::complex<double> c(0.7885*std::cos(t/speed_f),0.7885*std::sin(t/speed_f));

            size_t iter;
            for (iter = 0; iter < max_iter && std::abs(z) < 2.0; ++iter)
                z=z*z+c;

            if(iter < max_iter)
                d->AddRectFilled(ImVec2(a.x+x,a.y+y), ImVec2(a.x+x+1,a.y+y+1), to_color((float)iter / max_iter));
            else
                d->AddRectFilled(ImVec2(a.x+x,a.y+y), ImVec2(a.x+x+1,a.y+y+1), 0XFF000000);
        }
}

A little driving game. Use the mouse buttons to move left and right.

drive

#define V2 ImVec2
#define R d->AddRectFilled
#define RED 0xff0000ff

void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4 m, float t)
{
    static float mx = a.x + 160;
    float dy = 36, dt = 8;
    int i = fmodf(dt * t, 2) < 1 ? 1 : 0;
    auto v = fmodf(dt * t, 1), y = a.y - dy + v * dy;
    for (int s = 1 + sz.y / dy; s > 0; --s, y += dy) {
        float c = sinf(t + v / dy - s / dy) * 40;
        V2 tl = { c + a.x + sz.x / 2 - 64, y };
        V2 br = { c + a.x + sz.x / 2 + 64, y + dy };
        R(tl, br, (++i & 1) ? 0xffffffff : RED);
        tl.x += 8;
        br.x -= 8;
        R(tl, br, 0xff3f3f3f);
    }
    if (m.z >= 0) mx--; if (m.w >= 0) mx++;
    R({ mx - 8, b.y - sz.y / 4 - 15 }, { mx + 8, b.y - sz.y / 4 + 15 }, 0xff00ff00, 4);
    R({ mx - 7, b.y - sz.y / 4 - 8 }, { mx + 7, b.y - sz.y / 4 + 12 }, 0xff007f00, 4);
    R({ mx - 6, b.y - sz.y / 4 + 12 }, { mx - 2, b.y - sz.y / 4 + 14 }, RED);
    R({ mx + 2, b.y - sz.y / 4 + 12 }, { mx + 6, b.y - sz.y / 4 + 14 }, RED);
}

Inspired by this party, my entry is a Game of Life pulsar oscillator (see Wikipedia)

GoL

Uses left mouse button clicks to process next generation.

My algorithm is probably not efficient, and I need quite a big data input, so had to make the code ugly to get to 994 bytes:

#define V2 ImVec2
#define S 17
#define L 16
#define I int
#define F float

I h[S][S],g[S][S]={{0},{0},{0,0,0,0,1,1,1,0,0,0,1,1,1},{0},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,0,0,1,1,1,0,0,0,1,1,1},{0},{0,0,0,0,1,1,1,0,0,0,1,1,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0},{0,0,0,0,1,1,1,0,0,0,1,1,1}};

void FX(ImDrawList* d,V2 a,V2 b,V2 sz,ImVec4 m,F t)
{
if (!m.z)
{
for(I i=1;i<L;i++)
for(I j=1;j<L;j++)
{
I c=g[i-1][j-1]+g[i-1][j]+g[i-1][j+1]+g[i][j-1]+g[i][j+1]+g[i+1][j-1]+g[i+1][j]+g[i+1][j+1];
h[i][j]=(g[i][j]&&c==2)||c==3;
}
for(I i=1;i<L;i++)
for(I j=1;j<L;j++)
g[i][j]=h[i][j];
}
F s=1.f/S; I i=0,j=0;
for(F y=0.f;y<1.f;y+=s,j++,i=0)
for(F x=0.f;x<1.f;x+=s,i++)
{
V2 c((x+.5f*s),(y+.5f*s));
F k = .45f;
d->AddRectFilled(
V2(a.x+(c.x-k*s)*sz.x,a.y+(c.y-k*s)*sz.y),
V2(a.x+(c.x+k*s)*sz.x,a.y+(c.y+k*s)*sz.y),
g[i][j]*0xFFFF0000);
}
}

Non competing (I mean it’s not really my idea ; and truthfully it’s not really an effect), inspired by the previous comment, Conway’s Game of Life
conways
conways2

Use left click to place/remove a cell, and right click to start/stop.


Source code (1024 bytes)

#define V ImVec2
#define R(c)d->AddRectFilled(a+V(1,1)+V(i-1,j-1)*8, a-V(1,1)+V(i,j)*8,c)
int board[42][24]{};
int r = 0;
int f = 0;
void FX(ImDrawList * d,V a,V,V,ImVec4 m, float t) {
    if (r && ++f%10==1) {
        int n[42][22] = {};
        for (int i = 41; --i;) {
            for (int j = 23; --j;) {
                int s = -board[i][j];
                for (int k = 3; k--;) {
                    for (int l = 3; l--;) {
                        s += board[i + k - 1][j + l - 1];
                    }
                }
                if (s == 3)
                    n[i][j] = board[i][j]?1:2;
                if (s == 2)
                    n[i][j] = board[i][j];
            }
        }
        for (int i = 41; --i;)
            for (int j = 23; --j;)
                board[i][j] = n[i][j];
    }
    int x = int(m.x * 40);
    int y = int(m.y * 22.5f);
    if (m.z == 0.f && !r)
        if (x >= 0 && x < 41 && y >= 0 && y < 23)
            board[x+1][y+1] = !board[x+1][y+1];

    if (m.w == 0.f)
        r = !r;

    for (int i = 41; --i;)
        for (int j = 23; --j;) {
            if (board[i][j] == 2) {
                board[i][j] = 1+!!(f%10);
                R(0xFF55AAAA);
            }
            if (board[i][j] == 1)
                R(0xFFFF8855);
        }

    d->AddRect(a + V(x,y) * 8, a + V(x+1,y+1) * 8, ~0);
}

A kind of 2D version of the old electropaint effect using translucent circles. Works well against either a light or dark background.

fx_ec_23 fx_ec_17


Source Code (1021 bytes)

typedef float F;
struct G { F v0, v1; int mc, w; F ms, ma; int c; F v, d, a; };

F x(G& g){
g.c++;
if (g.c > g.mc){
g.a = (drand48() - 0.5) * 2 * g.ma;
g.c = 0;
}
g.d += g.a;
g.d = fmin(g.ms, fmax(-g.ms, g.d));
g.v += g.d;
if (g.w)
g.v = g.v0 + fmodf(g.v - g.v0, g.v1 - g.v0);
else
g.v = fmin(g.v1, fmax(g.v0, g.v));
return g.v;
}

int mx=999;
G rc={-15, 15, 150, 0, 0.05, 0.005, mx};
G ac={0, 360, 120, 1, 1, 0.025, mx};
G da={0, 360, 80, 1, 0.1, 0.01, mx};
G rm={0, 255, 95, 0, 5, 1.275, mx};
G gm={0, 255, 40, 0, 5, 1.275, mx};

struct Elt{F r;F a;F da;F cr;F cg;};
Elt ne() {return {x(rc),x(ac),x(da),x(rm),x(gm)};}
#include <deque>
std::deque<Elt> es(80);

void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, F){
es.pop_back();
es.push_front(ne());
V2 o = a + sz * 0.5;
for (Elt& e : es){
F ar=e.a*M_PI/180;
V2 p(sinf(ar), cosf(ar));
p *= sz.y*e.r/37.5;
F cr = sz.y/10 * (0.25 + fabs(e.r/20));
d->AddCircleFilled(o+p, cr, IM_COL32(e.cr, e.cg, (255-e.cr*e.cg/255), 48));
d->AddCircle(o+p, cr, 64<<24);
e.a += e.da;
}
}

Simple DFS Maze Generation, I had a rough time getting it under 1024 bytes

9iN3byNyCq

Source Code (989 bytes)

#include <random>
#include <functional>
#define arf q->AddRectFilled
#define al q->AddLine
#define V ImVec2
#define I(p,o) V(a.x+j*5+p,a.y+i*5+o)
#define J I(0,0)
#define K I(5,5)
#define wh 0xFFFFFFFF
#define bl 0xFF000000
#define fr(x,y) for(int x=0;x<y;++x)
#define P int p,int&c,int m,int&f
int u=1,d=2,r=4,l=8;auto S=std::random_device()();float W=0,I=.002;void FX(ImDrawList*q,V a,V,V s,ImVec4,float t){if(t>W+I)W=t;int w=64,h=36,C=0,F=-1;std::vector<int>G(w*h,15);std::mt19937 N(S);std::function<void(P)>fn=[&](P){if(c==m){f=p;return;}int n[]={-w,w,1,-1};int T[]={0,1,2,3};std::shuffle(T,T+4,N);fr(i,4){if(c==m)return;int L=p+n[T[i]];if(L<0||L>w*h-1||(L<p&&!(p%w))||(L>p&&!((p+1)%w)))continue;if(G[L]==15){auto v=1<<T[i];G[p]^=v;G[L]^=(v==u||v==r)?v*2:v/2;fn(L,++c,m,f);}}};fn(0,C,W/I,F);fr(i,h)fr(j,w){int e=G[i*w+j];if(i*w+j==F)arf(J,K,0xFF00FF00);else if(e!=15)arf(J,K,wh);if(e&u)al(J,I(5,0),bl);if(e&d)al(I(0,5),K,bl);if(e&l)al(I(0,5),J,bl);if(e&r)al(K,I(5,0),bl);}}

Non competing (I mean it’s not really my idea ; and truthfully it’s not really an effect), inspired by the previous comment, Conway’s Game of Life
conways
conways2

Use left click to place/remove a cell, and right click to start/stop.
Source code (1024 bytes)

That's a nice improvement over my attempt! And it can double as a paint program :-D

Boids implementation, 1020 bytes. It was a nightmare to get from 1090 to 1020. It had triangles for boids initially that looked better but I had to cut from somewhere 😅. This is so much fun, I feel like a teen again 🎉

ImDrawList_Party_Boids

using V=ImVec2;using F=float;using I=int;
#define O operator
#define R return
#define C cos(u)
#define S sin(u)
#define P(s)(V l,V r){R{l.x s r.x,l.y s r.y};};
#define Ps(s)(V l,F r){R{l.x s r,l.y s r};};
#define Y(s)V O s P(s)
#define Z(s)V O s Ps(s)
#define W(i,m)for(I i=0;i<m;++i)
Y(+)
Y(-)
Z(+)
Z(*)
Z(/)
F L(V v){R sqrt(v.x*v.x+v.y*v.y);}V M(V v,F m){F d=L(v);if(d>m)R v/d*m;R v;}V N(V v){R v/L(v);}V U(V v,F u){R{v.x*C-v.y*S,v.x*S+v.y*C};}struct B{V p,v,a;};B z[50];I t=1;void FX(ImDrawList* d,V a,V b,V,ImVec4,F){if(t){W(i,50){B&o=z[i];o.p={(b.x+a.x)/2,(b.y+a.y)/2};F u=rand()%99;o.v={C,S};}t=0;}W(i,50){auto&[p,v,f]=z[i];V pa,pc,ps;I c=0,cs=0;W(j,50){B&n=z[j];F d=L(n.p-p);if(d>0&&d<20){pa=pa+n.v;pc=pc+n.p;c++;}if(d>0&&d<10){ps=ps+(p-n.p)/d/d;cs++;}}if(c){pa=N(pa/c)*2-v;pc=N(pc/c-p)*2-v;}if(cs){ps=N(ps/cs)*2-v;}f=M(ps*2+pa+pc,.03);v=v+f;v=M(v,2);p=p+v;if(p.x<a.x-2)p.x=b.x+2;if(p.y<a.y-2)p.y=b.y+2;if(p.x>b.x+2)p.x=a.x-2;if(p.y>b.y+2)p.y=a.y-2;F u=atan2(v.x,-v.y);d->AddLine(p+U({0,-4},u),p+U({2,4},u),~0);}}

Update:
With the help of good folks around here, see bellow, I managed to reduce the size and add predator behavior as well. (986 bytes) now

ImDrawList_Party_Boids2

#define R return
#define C cos(u)
#define S sin(u)
#define W(i,m)for(I i=m;i--;)
using V=ImVec2;using F=float;using I=int;F L(V v){R sqrt(v.x*v.x+v.y*v.y);}V M(V v,F m){F d=L(v);if(d>m)R v/d*m;R v;}V N(V v){R v/L(v);}V U(V v,F u){R{v.x*C-v.y*S,v.x*S+v.y*C};}struct B{V p,v,a;I h;};B z[50];I t=1;void FX(ImDrawList* d,V a,V b,V,ImVec4,F){if(t){W(i,50){B&o=z[i];o.p=(b+a)/2;F u=rand()%99;o.v={C,S};o.h=i%20==0;}t=0;}W(i,50){auto&[p,v,f,h]=z[i];V pa,pc,ps,ph;I c=0,cc=0,cs=0,ch=0;I hs=h?3:1;W(j,50){B&n=z[j];F d=L(n.p-p);if(d>0&&d<20){pa=pa+n.v;c++;}if(d>0&&d<20*hs){pc=pc+n.p;cc++;}if(d>0&&d<10){ps=ps+(p-n.p)/d/d;cs++;}if(!h&&n.h){if(d>0&&L(p+v-n.p)<40){ph=ph+(p-n.p)/d*3;ch++;}}}if(c){pa=N(pa/c)*2-v;}if(cc){pc=N(pc/cc-p)*2-v;}if(cs){ps=N(ps/cs)*2-v;}if(ch){ph=N(ph/ch)-v;}f=M(ps*2+pa+pc,.03)+ph;v=v+f;v=M(v,2);p=p+v;if(p.x<a.x-2)p.x=b.x+2;if(p.y<a.y-2)p.y=b.y+2;if(p.x>b.x+2)p.x=a.x-2;if(p.y>b.y+2)p.y=a.y-2;F u=atan2(v.x,-v.y);d->AddLine(p+U({0,-4},u),p+U({2,4},u),h?0xff0000ff:~0);}}

Catalin: are you on testbed 0.10? because since 0.20 we enabled the math operators so you should be able to shave some of that code defining them :)

@heretique If you still need a few extra bytes after removing math ops, you can also use reverse for loops to gain a few (for(I i=m;i--;) instead of for(I i=0;i<m;++i)), and replace o.p={(b.x+a.x)/2,(b.y+a.y)/2} with o.p={(b+a)/2};

Haven't checked since the beginning, so yeah I'm using the first version. Thanks for the tip 😉

@heretique If you still need a few extra bytes after removing math ops, you can also use reverse for loops to gain a few (for(I i=m;i--;) instead of for(I i=0;i<m;++i)), and replace o.p={(b.x+a.x)/2,(b.y+a.y)/2} with o.p={(b+a)/2};

Thanks Lucas for the hints, keen eyes you have there 😉.

@ocornut and @Organic-Code with your suggestions I'm down to 834 bytes, I might be able to add predator behavior as well.

@heretique Hm that’s strange, I shove your code down to 815 bytes, but I don’t remember changing anything apart from what was mentioned 🤔
Well that’s not entirely true, because I forgot to say that you could reorder the code and put the using directives in the same line as the rest, but I mean that’s only 1 byte. Maybe you have some extra spaces here and there?


for comparison, here is what I have

#define C cos(u)
#define S sin(u)
#define W(i,m)for(I i=m;i--;)
#define R return
using V=ImVec2;using F=float;using I=int;F L(V v){R sqrt(v.x*v.x+v.y*v.y);}V M(V v,F m){F d=L(v);if(d>m)R v/d*m;R v;}V N(V v){R v/L(v);}V U(V v,F u){R{v.x*C-v.y*S,v.x*S+v.y*C};}struct B{V p,v,a;};B z[50];I t=1;void FX(ImDrawList*d,V a,V b,V,ImVec4,F){if(t){W(i,50){B&o=z[i];o.p={(b+a)/2};F u=rand()%99;o.v={C,S};}t=0;}W(i,50){auto&[p,v,f]=z[i];V pa,pc,ps;I c=0,cs=0;W(j,50){B&n=z[j];F d=L(n.p-p);if(d>0&&d<20){pa=pa+n.v;pc=pc+n.p;c++;}if(d>0&&d<10){ps=ps+(p-n.p)/d/d;cs++;}}if(c){pa=N(pa/c)*2-v;pc=N(pc/c-p)*2-v;}if(cs){ps=N(ps/cs)*2-v;}f=M(ps*2+pa+pc,.03);v=v+f;v=M(v,2);p=p+v;if(p.x<a.x-2)p.x=b.x+2;if(p.y<a.y-2)p.y=b.y+2;if(p.x>b.x+2)p.x=a.x-2;if(p.y>b.y+2)p.y=a.y-2;F u=atan2(v.x,-v.y);d->AddLine(p+U({0,-4},u),p+U({2,4},u),~0);}}

@Organic-Code my bad, I forgot to remove #define O operator line 😁

These demos are pretty cool! Thought I'd give it a shot.
Bouncing balls, new ones spawning on bounce, motion blur, light by distance from mouse, pause on mouse down (that's what the pauses are) - 760 bytes. There is still heaps of room to reduce it further, but this will do.

Bouncy

```C

define V2 ImVec2

define N 400

define R(x) rand()/(F)RAND_MAX*x

define F float

V2 P[N]={{100,80}},v[N];F r[N]={10},a=.02,t=10;ImVec4 c[N];int cu=1;
void FX(ImDrawList* d,V2 p,V2,V2 s,ImVec4 m,F)
{int n=-1;for(int i=0;i if(P[i].x+r[i]>s.x||P[i].x-r[i]<=0){v[i].x=-v[i].x;}}F e=P[i].x-m.xs.x,f=P[i].y-m.ys.y;int ii=max(255-sqrt(ee+ff),0);for(int j=0;j<=t;j++)
{F sc=j/t;d->AddCircleFilled(V2(P[i].x+p.x+v[i].xsc4,P[i].y+p.y+v[i].ysc4),r[i],IM_COL32(c[i].xii,c[i].yii,c[i].zii,sc255));}}
if(n>-1&&(cu

A racetrack. 948 bytes (thanks to tabs!)

horizon

#define V2 ImVec2
#define Q d->AddQuadFilled

void FX(ImDrawList* d, V2 a, V2 b, V2, ImVec4, float)
{
    static float cz = 0;
    V2 bl = {160, 90}, br = bl, bri = bl, bli = bl;
    cz += 0.5f;
    Q(a, {b.x, a.y}, {b.x, a.y + 30}, {a.x, a.y + 30}, 0xffffff00);
    Q({a.x, a.y + 30}, {b.x, a.y + 30}, b, {a.x, b.y}, 0xff007f00);
    for (int s = 300; s > 0; s--) {
        float c = sinf((cz + s) * 0.1f) * 500;
        float f = cosf((cz + s) * 0.02f) * 1000;
        V2 tl = bl, tr = br, tli = bli, tri = bri;
        tli.y--;
        tri.y--;
        float ss = 0.003f / s;
        float w = 2000 * ss * 160;
        float px = a.x + 160 + (f * ss * 160);
        float py = a.y + 30 - (ss * (c * 2 - 2500) * 90);
        bl = {px - w, py};
        br = {px + w, py};
        w = 1750 * ss * 160;
        bli = {px - w, py};
        bri = {px + w, py};
        if (s != 300) {
            bool j = fmodf(cz + s, 10) < 5;
            Q(tl, tr, br, bl, j ? 0xffffffff : 0xff0000ff);
            Q(tli, tri, bri, bli, j ? 0xff2f2f2f : 0xff3f3f3f);
        }
    }
}

<>

Doom fire in 666 bytes.

Short aniamted gif of this Doom FX

I first started to add interactive features, but I thought it would be more fun to get it down to 666 bytes instead (including carriage returns). There is room to get it a bit smaller still, but I didn't want to sacrifice readability any more than that. I'm happy I could keep the #define directives for W and H.

#define U unsigned
#define V ImVec2
#define P(o) V(a.x+(o+x)*s.x/W,b.y-(o+y)*s.y/H)
#define W 160
#define H 90
U n,C[666]={0xFFFFFF,0xC7EFEF,0x9FDFDF,0x6FCFCF,0x37B7B7,0x2FB7B7,0x2FAFB7,0x2FAFBF,0x27A7BF,0x27A7BF,0x1F9FBF,0x1F9FBF,0x1F97C7,0x178FC7,0x1787C7,0x1787CF,0xF7FCF,0xF77CF,0xF6FCF,0xF67D7,0x75FD7,0x75FD7,0x757DF,0x757DF,0x74FDF,0x747C7,0x747BF,0x73FAF,0x72F9F,0x7278F,0x71F77,0x71F67,0x71757,0x70F47,0x70F2F,0x7071F,0x70707};
U char T[H+2][W];
void FX(ImDrawList*d,V a,V b,V s,ImVec4,float t){20*t>n?n++:t=0;for(U x=0;x<W;x++)for(U y=0;y<H;y++){d->AddRectFilled(P(),P(1),C[T[y+1][x]]|255U<<24);U r=3&rand();if(t)T[y+1][x]=T[y][x+r-(r>1)]+(r&1);}}

I've ported a number of these funs into my java binding, the code can be retrieved here. Here's the collection view I've created for them: https://youtu.be/ojgWnelaRfw

I also have an executable jar for download, renamed to a .zip as GitHub required so: fun-v0.11-full.jar.zip

Flat Shaded Cup - 1019 bytes
ImguiCup

#include<algorithm>
#define V ImVec2
#define F float
F L(F d,F s){d*=d>0;return sqrt(1-exp(-s*(d+.1)-d*d*d));}
void R(F&x,F&y,F r){F s=sin(r),c=cos(r),t=c*x-s*y;y=s*x+c*y;x=t;}
F x,y,z,e,f,g,l;
void T(F u,F t){R(x,z,t/3+u);R(x,y,t);R(y,z,t/5);}
void FX(ImDrawList*d,V a,V b,V S,ImVec4,F t){
int n=0,i,j,k,u,v,K=7,J=16;
char P[]="GZHXITGPBMBCGA",*X=P;
V m=(a+b)/2;
struct Q{F d,l;V o[4];bool operator<(Q&b){return d<b.d;}}q[99];
for(k=K;--k;){X+=2;for(j=J;j--;){
Q&o=q[n++];
o.d=0;
for(i=4;i--;){
u=j+(i%3>0);v=-(i/2)*2;
x=X[v]-65;y=77-X[v+1];z=0;
T(IM_PI*2*u/J,t);
e=x;f=y;
o.d+=z=S.y/(g=z+40);
o.o[i]=m+V(x,y)*z;
}
x=X[1]-X[-1];y=*X-X[-2];z=0;
l=sqrt(x*x+y*y);
T(IM_PI*2*(j+.5)/J,t);
o.l=((x*e+y*f+z*g)>0?1:-1)*y/l;
}}
std::sort(q,q+n);
for(i=99;i--;){b.y=a.y;a.y=m.y+9e2/(i+1);d->AddRectFilled(a,b,i>97?0xffffd050:0xff608000+(i/9&1)*64+i*65793);}
for(i=0;i<n;i++){Q&o=q[i];l=o.l;
d->AddConvexPolyFilled(o.o,4,ImColor(L(l,.1),L(l,.3),L(l,1),1.));
d->AddPolyline(o.o,4,~0<<24,1,1);
}}

Working on porting some of the demos on my RISCV core for FPGAs (https://github.com/BrunoLevy/learn-fpga).
For now I do not have a FPU so it is damned slow. The goal in the end is to have a fully working ImGui API for it.

Imgui_Femtorv32

Making progress ! Tweaked a bit the code, to have a smoother animation (removed some tiny polygons near the horizon, which saves many floating point ops).

Imgui_Femtorv32

The Doom fire one is awesome ! Since it does not use FPU, it runs smoothly on the FemtoRV32 core. So realistic that I do not dare touching the screen !
DoomFire

An old school screensaver, remember these?

ScreenSaver

Add points with left click.

It was already < 1024 before making it ugly, but hey, it's part of the fun. I've stopped at 716 bytes.

#define V2 ImVec2
#define Co ImColor
#define SZ 32
#define SP 40
#define I int
#define F float

V2 p[SZ],s[SZ];
Co c[SZ];
I n=-1;

Co RandColor(){return Co(55+rand()%200,55+rand()%200,55+rand()%200);}

void FX(ImDrawList* d,V2 a,V2,V2 sz,ImVec4 m,F)
{
    if(m.z==0)
    {
        if(++n>=SZ){n=0;}
        else{p[n]=V2((F)(rand()%(I)sz.x),(F)(rand()%(I)sz.y));s[n]=V2((rand()%SP)/10.0f,(rand()%SP)/10.0f);c[n]=RandColor();}
    }

    for (I i=0;i<n;i++)
    {
        if(p[i].x<0.f||p[i].x>sz.x){s[i].x*=-1.0f;c[i]=RandColor();}
        if(p[i].y<0.f||p[i].y>sz.y){s[i].y*=-1.0f;c[i]=RandColor();}
        p[i]+=s[i];
    }

    for (I i=1;i<n;i++)
        d->AddLine(a+p[i-1],a+p[i],c[i]);

    if(n>1)
        d->AddLine(a+p[n-1],a+p[0],c[0]);
}

Sorry for the spam but I just had to post an updated version - all I changed was the alpha from 1. to .8 but it's loads better!

ImguiCupAlpha

https://gist.github.com/pmalin/550058583492478beedd7b31ab468174

Here is mine, which is an upgraded version of an effect from our VX2 demo from Revision2020
I managed to keep some indentation in the compression process, but still hard to read ;)
@ocornut : thanks to the PushClipRect so the creature can blink 👀

test3

using V=ImVec2;
using I=int;
using F=float;
const I t=10,s=50;
F p1=IM_PI,p2=2*p1,lb=10;
V T[t][s];
V e(10,0);
I bk=0xFF000000;
F NA(F f){return f-p2*floor((f+p1)/p2);}
void FX(ImDrawList* d,V a,V z,V sz,ImVec4 m,F u)
{
    V vP=a+V(m.x,m.y-.3f)*sz;
    for (I i=0;i<t;++i)
    {
        F aT=i*p2/t,apv=aT,l=lb;
        V vDT(cos(aT),sin(aT)),vpv=vP;
        for (I j=0;j<s;++j)
        {
            V& vC=T[i][j];
            V vab=vC-vpv;
            V vAB=vab*ImInvLength(vab,1);
            F aS=atan2(vAB.y,vAB.x);
            F cl=ImClamp(NA(aS-apv),-p1,p1);
            aS=apv+ImClamp(cl-cl*.6f,-p1,p1);
            V vD(cos(aS),sin(aS));
            vC=vpv+vD*l;
            d->AddLine(vpv,vC,j&1?0xFF800000:0xFF000040,2*l);
            d->AddLine(vpv,vC,j&1?0xFFE08020:0xFF4020E0,2*l/3);
            apv=aS;
            vpv=vC;
            l*=i&1?.9f:.85f;
        }
    }
    F cs=pow(abs(sin(u)),.3);
    d->PushClipRect(vP-V(99,10)*cs,vP+V(99,10)*cs,1);
    d->AddCircleFilled(vP+e,9,-1);
    d->AddCircleFilled(vP-e,9,-1);
    V o=e*.5*sin(u*.8);
    d->AddCircleFilled(vP+e+o,4,bk);
    d->AddCircleFilled(vP-e+o,4,bk);
    d->PopClipRect();
}

Little raycaster (1020 bytes).
Hold right mouse button to look around and left mouse to move forward.
There's no collision testing for the walls but there's a limitation on position inside map (16x16 squares).
Code is unreadable but pretty simple actually, for a good basic explanation of the principles have a look here, for an in depth dive I recommend The Black Book series

ImDrawList_Party_Raycasting2

#define C(u)cos(u)
#define S(u)sin(u)
#define W(i,m,c)for(F i=0;i<m;i+=c)
using V=ImVec2;using F=float;using I=int;I mp[8]={0xffff8001,0x82418001,0xa0018cf9,0x8009a289,0x80098289,0xa0018ef1,0x80058001,0x8001ffff},t1[8]={0x4003a001,0x10001,0x30003,0x8045ffff,0x3a00140,0x1000500,0x21000704,0xb80ffff},K=16;F px=1.5,py=1.5,pa=0,fv=1,mx=0;
#define M(m,x,y)m[I(y/2)]&(1<<I(32-(x+(I(y)%2?K:0))))
#define R(k,l,m,n,r,p)d->AddRectFilled({a.x+i,(b.y+a.y)/2+(k)},{a.x+i+1,(b.y+a.y)/2+(k)+1},M((l),(m),(n))?(r):(p))
void FX(ImDrawList* d,V a,V b,V s,ImVec4 m,F t){W(i,s.x,1){F ag=pa-fv/2+fv*i/s.x;W(j,K,.01){F x=px+j*C(ag),y=py+j*S(ag),di=j*cos(ag-pa),ch=min(300,I(s.y/di));R(ch/2,t1,I(32*x)%K,I(32*y)%K,0xff082f3d,0xff042530);if(M(mp,x,y)){F wx=x-I(x+.5),wy=y-I(y+.5);I tx = I(64*(abs(wy)>abs(wx)?wy:wx))%K;if(tx<0)tx+=K;W(c,ch,1){I ty=I(64*c/ch)%K;R(-ch/2+c,t1,tx,ty,0xff062036,0xff044275);}break;}}}if(m.w==0)mx=m.x;if(m.w>0){pa+=m.x-mx;mx=m.x;}if(m.z>0){px=max(1.3,min(14.5,px+.05*C(pa)));py=max(1.3,min(14.5,py+.05*S(pa)));}}

Update:

image

I added a small map/texture editor for who wants to play with the map or texture for the demo.
Use left mouse left click to toggle cells and right click to print the values to console. Copy paste the values from the console inside the mp[8]= or t1[8]= arrays and recompile.

using V = ImVec2;
using I = int;
using F = float;
const I kTiles = 16;
// the map is 16x16 encoded in 8 integers
// one value in the array encodes two rows
// The same idea is used for the ground/wall texture as well
I map[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
ImU32 gridColor = 0xff303000;
void FX(ImDrawList* d, V a, V b, V s, ImVec4 m, F)
{
    // I chose to draw the map centered and with 1 aspect ratio
    // as it looks better
    F sz = (s.y - 1) / kTiles; // define size of tile in pixels


    // tile drawing
    for (I i = 0; i < kTiles; ++i)
    {
        for (I j = 0; j < kTiles; ++j)
        {
            // we pack 2 rows into an integer
            // so we have to adjust index in map and bit position in value
            I mapIndex = j / 2;
            I shift = 32 - (i + (j % 2 ? 16 : 0));
            if (map[mapIndex] & (1 << shift))
            {
                d->AddRectFilled({ (a.x + b.x - s.y - 1) / 2 + i * sz + 1, a.y + j * sz }, { (a.x + b.x - s.y - 1) / 2 + (i + 1) * sz + 1, a.y + (j + 1) * sz }, ~0);
            }
        }
    }

    if (!m.z && (m.x >= 0 && m.x <= 1.0) && (m.y >= 0 && m.y <= 1.0))
    {
        // remap mouse pos to [0,1] inside grid
        F mx = (m.x - (s.x - s.y) / 2 / s.x) * s.x / s.y;
        F my = m.y;
        if ((mx >= 0 && mx <= 1.0) && (my >= 0 && my <= 1.0))
        {
            I mapIndex = my * kTiles / 2;
            I mod = I(my * kTiles) % 2;
            I shift = 32 - (I(mx * kTiles) + (mod ? kTiles : 0));
            map[mapIndex] ^= 1 << shift;
        }
    }
    // vertical grid
    for (I i = 0; i < kTiles + 1; ++i)
    {
        d->AddLine({ (a.x + b.x - s.y - 1) / 2 + i * sz + 1, a.y }, { (a.x + b.x - s.y - 1) / 2 + i * sz, b.y }, gridColor);
    }
    // horizontal grid
    for (I j = 0; j < kTiles + 1; ++j)
    {
        d->AddLine({ (a.x + b.x - s.y - 1) / 2, a.y + j * sz }, { (a.x + b.x + s.y - 1) / 2, a.y + j * sz }, gridColor);
    }
    if (!m.w)
    {
        for (I i = 0; i < 8; ++i)
        {
            printf("0x%x", map[i]);
            if (i != 7)
                printf(",");
        }
        printf("\n");
    }
}

@heretique OK, that's seriously impressive - you even managed to fit a texture in there!

Googly Eyes
googley

WASM demo: https://floooh.github.io/oryol-sticky-tests/xeyes/imgui-sapp.html

void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 m, float) {
    #define el(p,rx,ry,c){for(int s=0;s<36;s++){d->PathLineTo(ImVec2(p.x+sinf((IM_PI/18)*s)*rx,p.y+cosf((IM_PI/18)*s)*ry));}d->PathFillConvex(c);}
    #define v2 ImVec2
    v2 c((a+b)*0.5f);
    v2 mp(a.x+m.x*sz.x,a.y+m.y*sz.y);
    d->AddRectFilled(a,b,0xFF665544);
    v2 eye[2]={{c.x-50,c.y},{c.x+50,c.y}};
    for (int i=0;i<2;i++){
        el(eye[i],40,70,0xFF000000);
        el(eye[i],35,65,0xFFFFFFFF);
        v2 v(mp-eye[i]);
        float l=sqrtf(v.x*v.x+v.y*v.y);
        v2 n(v/l);
        if (l>20)l=20;
        v2 p(eye[i]+n*l);
        el(p,10,10,0xFF000000);
    }
}

ImGuiFx2a

My contribution (1020b). Thx you so much for ur great lib omar.
It's a tribute to the spreadpoint demo also ported on atari by TCB.
Demoscene for ever!
Stef/Spectrals

using V=ImVec2;using F=float;
#define R(w,x,y,z) d->PushClipRect(V(w,x),V(y,z),1);
#define Rf d->PopClipRect();
#define L(i,x,y,z) for(F i=x;i<y;i+=z)
#define X(i,x,y,z,w) d->AddText(ImGui::GetFont(),i,x,0xff000000+y,z,w);
void FX(ImDrawList* d,V a,V b,V sz,ImVec4 m,F t){char*s="Thank you so much Omar Cornut for this outstanding Dear ImGui!";V c=a+sz/2;F o=410;
L(y,0,sz.y,10)L(x,fmod(t*-100+30*sin(t+y),o)-o,sz.x,o) X(0,a+V(x,y),0xaa+0x55*cos(y*.1),s,0)
L(x,a.x,b.x,1){R(x,a.y,x+1,b.y)L(j,8,16,1) X(60,V(b.x-fmod(t,12)*200-j,10+c.y+cos(x*.01+t*5+j*.3)*30),0x111111*j,s,0);Rf}
F z=fabs(cos(t)*30);L(y,a.y+z,a.y+z+60,1){R(a.x,y,b.x,y+1.01)L(i,0,6,1) X(60,V(c.x-150+20*sin(t*3-i*.2+(y-z)*.1),a.y+z),i*0x5500,s+51,0)Rf}
L(i,0,50,1){F tt=t+i*.02;V p=V(sin(tt*10)-cos(tt*5),sin(tt*-3)+cos(tt*1.5))*sz/4+c;L(j,0,5,1) d->AddCircleFilled(p+V(1,-1)*10*j/8,10*(1-j/5),j<4?0xff000000+j*0x5500:-1);}
for(int k=18;k<29;k++) L(j,0,6,1){F w=sin(j*-.2+t*5+k*.3)*15+30; X(w,a+V(-190+k*16-w/2,16-w/2),j*0x550000,s+k,s+k+1)}}

Here is mine, which is an upgraded version of an effect from our VX2 demo from Revision2020
I managed to keep some indentation in the compression process, but still hard to read ;)
@ocornut : thanks to the PushClipRect so the creature can blink 👀

test3

My son (9y) goes crazy with this one... It could be a good candidate for a Dear Imgui mascot...

Wow, oh dear this is all incredibly amazing <3 I'm not even sure how to comment on those yet!

@StephaneMenardais yours as well as being touching was very ingenuous, how you simulated raster/scanline effect with cliprect.
@speedoog incredibly charming, would make a good screen saver as well (or easter egg)
@heretique i'm not even sure what to say at this point :)

It's quite fun to investigate them, still have lots to catch up with! keep them coming!
I believe we could end up packaging all of them in bundled sources + ship on emscripten with code on the side :)

Particle Text

particle text

Code is in orb form (1024 bytes):

#include <algorithm>
#define V ImVec2
#define R(u,v,r){float U=u;u=cos(r)*u-sin(r)*v;v=sin(r)*U+cos(r)*v;}
#define S(T)1.f/(1+exp(-(T)))*IM_PI*2
#define B(T)sin((T)*3)*exp(-(T))
                       int  W =
             11;unsigned c [] ={0xD9000080,
      0x750A2B18,0xDC2A2A17,0x0200025D,0x5AB1E800,
   0x26EAB555,0x01800100};struct T{float x,y,z; int i
 ;bool operator < (T &o) {return z > o.z; }}; void FX (
ImDrawList *d,V a,V b,V s,ImVec4 m,float t){float L=fmod
(t,6)*10;T v[221];for(int n=3;n<224;n++){int i=n-3;float
x =i%17*W-8.5*W,y=i/17*W-6.5*W,z=0,D=sqrt(x*x+y*y)/32,X=
S(L-4-D)+cos(t/3)/4,Y=S(L-12-D)+cos(t/7)/4,Z=S(L-20-D) +
cos(t/2)/4;R(x,y,Z)R(y,z,X)R(x,z,Y)z-=L-D>28?B((L-28-D)/
2)*50:0;z=c[n/32]&1<<n%32?z/100+1:0; v[i] = {a.x+s.x*.5f
 +x/z,a.y+s.y*.5f+y/z,z,i};}std::sort(v,&v[221]); for (
   int i = 0; i < 221; i++) { if ( v[i].z != 0 ) {d->
      AddCircleFilled(V(v[i].x,v[i].y),W*.8/v[i].z
            ,ImColor(v[i].i>102?0.f:1.f,v[i]
                   .i<102?0.f:1.f,3.f
-v[i].z*2.5f,1.f));}}}

A slightly less obfuscated version (1015 bytes):

#include <algorithm>
#define V ImVec2
#define R(u,v,r) {float U=u;u=cos(r)*u-sin(r)*v;v=sin(r)*U+cos(r)*v;}
#define S(T) 1.f/(1+exp(-(T)))*IM_PI*2
#define B(T) sin((T)*3)*exp(-(T))
int W = 11;
unsigned c[] = {0xD9000080,0x750A2B18,0xDC2A2A17,0x0200025D,0x5AB1E800,0x26EAB555,0x01800100};
struct T{float x,y,z;int i;bool operator<(T&o){return z>o.z;}};
void FX(ImDrawList *d,V a,V b,V s,ImVec4 m,float t) {
    float L=fmod(t,6)*10;T v[221];
    for (int n=3;n<224;n++) {
        int i=n-3;
        float x=i%17*W-8.5*W,y=i/17*W-6.5*W,z=0,D=sqrt(x*x+y*y)/32,
            X=S(L-4-D)+cos(t/3)/4,Y=S(L-12-D)+cos(t/7)/4,Z=S(L-20-D)+cos(t/2)/4;
        R(x,y,Z)R(y,z,X)R(x,z,Y)
        z-=L-D>28?B((L-28-D)/2)*50:0;
        z=c[n/32]&1<<n%32?z/100+1:0;
        v[i] = {a.x+s.x*.5f+x/z,a.y+s.y*.5f+y/z,z,i};
    }
    std::sort(v,&v[221]);
    for (int i=0;i<221;i++)
        if (v[i].z!=0)
            d->AddCircleFilled(V(v[i].x,v[i].y),W*.8/v[i].z,ImColor(v[i].i>102?0.f:1.f,v[i].i<102?0.f:1.f,3.f-v[i].z*2.5f,1.f));
}

Another one (806 bytes)

Update: fixed UB.

ezgif-7-0616877d6c6d

WASM demo: https://floooh.github.io/oryol-sticky-tests/imguidl2/imgui-sapp.html

void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 m, float t) {
#define v2 ImVec2
#define u32 uint32_t
#define R(p0,p1,c) d->AddRectFilled(p0,p1,c)
u32 s[]={0xF1F8C7C3,0xD8CF3378,0xD981E661,0x9DD9B330,0xCD833661,0x9FD83330,0xCDE3F7C1,0x9ADBB330,0xCD833781,0x98D9B330,0xD98336C1,0x98D9B330,0xF1FB3663,0xD8CF1E78};
u32 p[]={0xFF0000FF,0xFF0088FF,0xFF00FFFF,0xFF00FF00,0xFFFFFF00,0xFFFF8888,0xFFFF88FF,0xFFFF8888,0xFFFFFF00,0xFF00FF00,0xFF00FFFF,0xFF0088FF};
v2 p0(a+v2(165,60));R(a,b,0xFFCC0000);for(int y=0;y<7;y++){for (int x=0,ix=-32;x<2;x++){u32 c=s[y*2+x];for (int i=31; i>=0;i--,ix++){
if (c&(1<<i)){v2 p1(p0.x+ix*4,p0.y+y*4);u32 pi=u32((t*30+32)-ix)%12;R(p1,p1+v2(3,3),p[pi]);float w=4+(6-y)*0.5;v2 p2(p0.x+ix*w+sinf(t*2+p1.y*.3)*(6-y),p0.y+48-y*3);
R(p2,p2+v2(w,2),p[pi]&0x7FFFFFFF);}}}}}

Formatted:

void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 m, float t) {
    #define v2 ImVec2
    #define u32 uint32_t
    #define R(p0,p1,c) d->AddRectFilled(p0,p1,c)
    u32 s[]={0xF1F8C7C3,0xD8CF3378,0xD981E661,0x9DD9B330,0xCD833661,0x9FD83330,0xCDE3F7C1,0x9ADBB330,0xCD833781,0x98D9B330,0xD98336C1,0x98D9B330,0xF1FB3663,0xD8CF1E78};
    u32 p[]={0xFF0000FF,0xFF0088FF,0xFF00FFFF,0xFF00FF00,0xFFFFFF00,0xFFFF8888,0xFFFF88FF,0xFFFF8888,0xFFFFFF00,0xFF00FF00,0xFF00FFFF,0xFF0088FF};
    v2 p0(a+v2(165,60));
    R(a,b,0xFFCC0000);
    for(int y=0;y<7;y++){
        for (int x=0,ix=-32;x<2;x++){
            u32 c=s[y*2+x];
            for (int i=31; i>=0;i--,ix++){
                if (c&(1<<i)){
                    v2 p1(p0.x+ix*4,p0.y+y*4);
                    u32 pi=u32((t*30+32)-ix)%12;
                    R(p1,p1+v2(3,3),p[pi]);
                    float w=4+(6-y)*0.5;
                    v2 p2(p0.x+ix*w+sinf(t*2+p1.y*.3)*(6-y),p0.y+48-y*3);
                    R(p2,p2+v2(w,2),p[pi]&0x7FFFFFFF);
                }
            }
        }
    }
}

ImGuiFx3c

2nd effect, 1022b
Thx @bdero for sort idea.

#include <algorithm>
using V=ImVec2;using F=float;int h;struct E{V p;F z,w;bool operator<(E&o){return z<o.z;}};E G[999];
#define L(i,x,y,z)for(F i=x;i<y;i+=z)
#define Q(y)sin((y+t)*.03)*(1-sin(t*3)*cos(y/99+t))*9
#define H(p,w)L(k,0,5,1)d->AddCircleFilled(p+V(1,-1)*w*k/8,w*(1-k/5),k<4?0xff000000+k*0x554400:-1);
#define J(b)L(i,0,h,1){E&o=G[int(i)];if(b*o.z>0)H(o.p,(o.z*.3+4)*o.w)}
#define O(b)i=t+1.6+j/99;if(b*sin(i)>0)H(c+v*j+u*(cos(i)*40+Q(j)),30)
void FX(ImDrawList*d,V a,V b,V,ImVec4,F t){F i=sin(t)-.7;V u(cos(i),sin(i)),v(-sin(i),cos(i)),c=(a+b)/2;F l=300;
F w=0;L(z,4,20,1){w+=z;L(yy,-l,l,z*2){F y=yy+fmod(t*z*10,z*2);L(i,-1,2,2)d->AddCircle(c+v*y+u*i*(w+sin((y+t)/25)*w/30),z,0xff000000+0x110e00*int(z*z*z/384),12,z/2);}}
h=0;L(y,-l,l,15)L(b,0,16,1){i=t+b*.2+y/99;G[h++]={c+v*y+u*(cos(i)*60+Q(y)),sinf(i),(b<1||b>14)?2.f:1.5f};}std::sort(G,G+h);
F j=(-2+fmod(t*3,5))*99;J(-1)O(-1)a=c+v*-l;L(y,-l,l,15){b=c+v*y+u*(15-rand()&31)*.1;L(k,0,9,1)d->AddLine(a-v,b,k<8?0x11222200*k:-1,(9-k)*4);a=b;}O(1)J(1)}

Stateless particle effect with mouse controlling the acceleration (1022b)

ezgif com-gif-maker (3)

using V=ImVec2;
using I=int;
using U=unsigned int;
using F=float;
I sc=50,pa=0;
F lt=800.0f;
I noise(U p, U s){const U a=0xB5297A4D,b=0x68E31DA4,c=0x1B56C4E9;U m=p;m*=a;m+=s;m^=(m>>8);m+=b;m^=(m <<8);m*=c;m^=(m>>8);return m;}
F rbt(U s,U *p,F a,F b){U v = noise(*p, s); *p += 1;return (F)((((F)(v%10000))/10000.0f)*(b-a)+a);}
V dv(U s,U *p,F a,F b,F c,F d){F z=rbt(s,p,a,b);return V(cos(z),sin(z))*rbt(s, p, c, d);}
void FX(ImDrawList* d,V a,V z,V sz,ImVec4 m,F dt){F t=dt*1000.0f,tbe=100.0f/5.0f;I g=(I)(t/tbe);F cst=(F)g*tbe;I mga=ceil(lt/tbe),pc=min(g+1,mga)*sc;I icg=max(0,g+1-mga),cg=icg;for(I pi=0;piAddCircleFilled(p,si,pt/lt<0.1?0x44FFFFFF:pt/lt<0.3?0xAA00AAFF:ImColor(1.0f,.0f,.0f,1.0f-pt/lt));}}}

Colored random walks, very simple code, cool looking result.

RandomWalk


Source code (741 bytes)

#define C(r,g,b) IM_COL32(255*(r), 255*(g), 255*(b), 255)

ImU32 to_color(float v)
{
    size_t p = v * 5.0;
    double g = (v * 5.0 - p);
    ImU32 colors[] = {
      C(1, g, 0),
      C(1-g, 1, 0),
      C(0, 1, g),
      C(0, 1-g, 1),
      C(g, 0, 1),
      C(1, 0, 1-g),
    };
    return colors[p];
}

float pixel[320][180];
#define R ((float)std::rand()/RAND_MAX > 0.5)

void FX(ImDrawList* d, ImVec2 a, ImVec2, ImVec2, ImVec4, float t)
{
    size_t x(320.f/2), y(180.f/2);
    do
    {
        pixel[x][y] = t - (int) t;
        if(R)
            x += R ? -1 : 1;
        else
            y += R ? -1 : 1;
    } while(x >= 0 && x < 320 && y >= 0 && y < 180);

    for (x = 0; x < 320; ++x)
        for (y = 0; y < 180; ++y)
        {
            d->AddRectFilled(ImVec2(a.x+x,a.y+y), ImVec2(a.x+x+1,a.y+y+1), to_color(pixel[x][y]));
        }
}

I made this landscape for another entry.
Shame the deadline is so soon, these are fun and I have a list of ideas.

ImguiLandscapeB
1017 bytes

#define V ImVec2
#define F float
#define D 2048
F m[D*D],I,O,w,x,y,z,h,u,v,l;
int q,i,j,T,M;
F&A(int x,int y){return m[(x&(D-1))+(y&(D-1))*D];}
F S(F x,F y){return A(x*D,y*D);}
void L(F& x,F a,F c){x=sqrt(1.-exp(-a*I*(1.-O)-c*O));}
#define R ((rand()%98)/49.-1)*l
void FX(ImDrawList*d,V a,V b,V B,ImVec4 o,F t){
if(!q){q=1;m[0]=0;l=.5;
for(T=D;T>1;l=l/2,T=T/2){M=T/2;for(j=0;j<D;j+=T){for(i=0;i<D;i+=T){w=A(i,j);x=A(i+T,j);y=A(i,j+T);z=A(i+T,j+T);
A(i+M,j)=(w+x)/2+R;A(i+M,j+T)=(y+z)/2+R;A(i,j+M)=(w+y)/2+R;A(i+T,j+M)=(x+z)/2+R;A(i+M,j+M)=(w+x+y+z)/4+R;}}}}
V s=a,e=b;o.w=1;for(i=64;i--;){s.y=e.y;e.y=a.y+B.y*i/150;d->AddRectFilled(s,e,0xffff6000+i*771);}
for(i=0;i<B.x;i++){s.x=e.x=a.x+i;e.y=s.y=b.y;w=(i/B.x)*2-1;h=S(.5,t*.2)-.5;
for(j=0;j<400;j++){z=j/400.;z=z*z*500;x=w*z;u=x/300+.5;v=z/300+t*.2;l=S(u,v);y=(l-h)*32;s.y=a.y+B.y*(y/(z+.1)+.25);
if(s.y<e.y){I=l-S(u+.01,v+.005)+.01;I=I*(I>0)*99+.2;O=1.0-exp(-z*3e-4);
L(o.x,.6,2);L(o.y,.25,4);L(o.z,.15,10);d->AddLine(s,e,ImColor(o));e.y=s.y;}}}}

Once again I find a hack just after I posted that improves things. Sorry for the double post.

ImguiLandscapeBetter

https://gist.github.com/pmalin/5e2906acc4983bdcbf9a7349997fe824
(1021 bytes)

@pmalin I love that that the compression of the gif paints in an extra mountain range on the right side. Extra scenic!

Second entry: Sail boat!

b2

Based on a small game jam entry I made a few years back.

Source is 1019 bytes -- thanks to @andwn for brainstorming additional ideas to shed off characters:

#define C cos
#define W(I){F R=H(I)*62,X=a.x+s.x/8*((I%11)-1)+C(R+t)*10,Y=a.y+s.y/8*(I/11)+40+sin(R+t)*10,E=1-exp(-(I/11)/3.);\
d->AddTriangleFilled(V(X,Y),V(X+300,Y+90),V(X-300,Y+90),ImColor(.94f-.17f*E,.61-.25*E,.36+.38*E));}
using F=float;using V=ImVec2;
ImU32 c[7]={0xff00a4fb,0xff00a4fb,(ImU32)-1,(ImU32)-1,0xff262aa2,0xff01007d,0xff64c9fd};
F M=FLT_MAX;V N=V(M,M);F H(F x){F y=C(x)*42;return y-floor(y);}
void FX(auto *d,V a,V b,V s,auto m,F t){d->AddRectFilled(a,b,c[6]);int i=0,j=0,k=0;
for(;i<33;i++)W(i)
F x=C(t*1.3)*2+a.x+s.x*.5,y=15+C(t*1.4)*2.5+C(t*2)*3+a.y+s.y*.5,r=C(t)/10+C(t*1.33)/12,
f[98]={-11,-3.5,4,-24,1.5,-3.5,M,M,5.5,-2,3,-24,11,-2,M,M,2.8,-24,4,-24,4,-2,2.8,-2,M,M,-11,-4.4,4,-4.4,4,-3.5,-11,-3.5,M,M,-12,-2,12,-2,12,0,-12,0,M};
V *v=(V*)f;v[48]=N;
for(i=25;i--;){F d=.1308*i;v[i+23]=V(C(d)*11,sin(d)*8);};
for(;i<49;i++)
if(v[i].x==M){d->AddConvexPolyFilled(&v[j],i-j,c[k]);j=i+1;k++;}
else{v[i]=V(x+(C(r)*v[i].x-sin(r)*v[i].y)*3.5,y+(sin(r)*v[i].x+C(r)*v[i].y)*3.5);}
for(i=33;i<88;i++)W(i)}

Got an hour to remove the STL dependency from my entry (particularly as I see there are some cool ports above) and polish it a bit.

spirals4

Calling it "spirals" -- source is now down to 1010 bytes, with _some_ formatting retained :)

typedef float F;
struct G{F v0,v1; int mc,w; F ms,ma; int c; F v,d,a;};

F x(G& g){
g.c++;
if (g.c > g.mc){
g.a = (drand48()-0.5)*2*g.ma;
g.c = 0;
}
g.d += g.a;
g.d = fmin(g.ms, fmax(-g.ms, g.d));
g.v += g.d;
if (g.w)
g.v = g.v0 + fmod(g.v-g.v0, g.v1-g.v0);
else
g.v = fmin(g.v1, fmax(g.v0, g.v));
return g.v;
}

int mx=999;
G rc={-15,15, 150,0,0.05,0.005,mx};
G ac={0,360,120,1,1,0.03,mx};
G da={0,360,80,1,0.1,0.01,mx};
G rm={64,255,95,0,10,1.3,mx};
G gm={64,255,40,0,10,1.3,mx};

struct E{F r;F a;F da;F cr;F cg;};
E ne(){return{x(rc),x(ac),x(da),x(rm),x(gm)};}

int ei=0,en=400;
E es[400];

void FX(ImDrawList* d,V2 a,V2 b,V2 sz,ImVec4,F){
ei++;ei%=en;
es[ei]=ne();

V2 o=a+sz*0.5;
d->AddRectFilled(a,b,~0);

for (int i=en;i;){
E& e = es[(i-- + ei)% en];
F ar = e.a*M_PI/180;
V2 p(sin(ar),cos(ar));
p.x += sin(e.da*e.a/3600)*.5;
p *= sz.y*e.r/42;
F cr = sz.y/20 * (1+fabs(e.r/15));
d->AddCircleFilled(o+p, cr, IM_COL32(e.cr, e.cg, (255-e.cr*e.cg/255), 60));
d->AddCircle(o+p, cr, 30<<24);
e.a += e.da/4;
}}

ImGuiFx4c

A little shot'em up. Lots of features bypassed to make it fit in 1Ko (missile, gui, sort, planet background, level of difficulty etc.)
Did not anticipate how game logic increase complexity. If some1 is able to compress 10+bytes i could increase sphere display quality :)

edit: updated sphere visual (1022b).
nb: u must have mouse on windows before start (2sec delay)

#define Q 999
#define L(i,x)for(I i=0;i<x;i++)
#define D(a,b)sqrt(pow(a.p.x-b.p.x,2)+pow(a.p.y-b.p.y,2))
#define S(...)L(i,Q)if(!E[i].h){E[i]={__VA_ARGS__};i=Q;}
#define J (rand()&511)*.002
#define H(a)a.h--;z=!a.h&&a.i==8;L(i,6)S(a.p,V(cos(J*9),sin(J*9))*99,z?4:2,z?1:120,z*2)
using V=ImVec2;using I=int;struct T{V p,v;I i=9,h=0,s=2;};I z;T E[Q],C,&M=E[Q-1],&N=E[Q-2];void FX(ImDrawList*d,V a,V b,V sz,ImVec4 m,float t){C.p=a+sz/2;M.p=a+V(m.x,m.y)*sz;N.p=a+sz*V(.75,.5)+V(sin(t),cos(t*2))*40;if(t<2){M.h=N.h=99;M.s=1;}else{S(V(b.x,a.y+sz.y*J),V(-1-J,0)*50,1,40,0)L(i,Q)if(E[i].h){T&e=E[i];e.p+=e.v/50;t=e.i>8?e.s*10+J*(99-e.h)*.1:e.i;I j=64+7*e.i;L(k,(e.i>8?4:1))d->AddCircleFilled(e.p+(M.p-e.p)*k/50,t-k*t/4,((k&1)+2)*ImColor(e.s&2?j:e.h,e.s&1?j:e.h,e.s?0:e.h),32);if(e.i==2)e.h-=5;if(D(C,e)>200+e.i)e.h=0;L(j,Q){T&f=E[j];if(e.h*f.h&&e.s*f.s==2&&D(e,f)<f.i+e.i){H(e)H(f)}}}if(M.h*N.h){if(J<.1)S(N.p,M.p-N.p,4,2)if(J<.02)S(N.p,V(-50,0),8,2)if(m.z==0)L(j,4)S(M.p+V(0,(j&1)*(j-2)*4),V(500,j<3?(j-1)*250:0),4,1,1)}}}

Inspired by 'Symmetry in Chaos' from Michael Field and Martin Golubitsky. 997 bytes.

out

#define V ImVec2
#define f float
#define i int
i color(f h){h=fmod(h,3);i n=192,o=n*h;i c=0xFF404040;if(h<1){c+=n-o;c+=o<<8;}else if(h<2){o-=n;c+=(n-o)<<8;c+=o<<16;}else{o-=2*n;h-=2;c+=(n-o)<<16;c+=o;}return c;}
#define mul(a,b)V((a).x*(b).x-(a).y*(b).y,(a).x*(b).y+(a).y*(b).x)
void FX(ImDrawList* d,V a,V b,V s,ImVec4 m,f t){
i c = color(t);
f ps[5][7]={{-1.860,2,0,1,.1,4,90},{-2.08,1,-.1,0.167,0,7,60},{-1.816,1.791,0,1,0,5,90},{1.52,-1.21,-.091,-0.8005,0,3,60},{2.404,-2.505,0,.9,0,13,90}};
static f*qs=ps[0];i k=(i)(m.y*5);k=k<0?-1:k>=5?-1:k;
for(i j=0;j<5;j++)d->AddRectFilled(a+V(0,s.y*j/5+3),a+V(s.x*.2,s.y*(j+1)/5-3),k==j&&0<m.x&&m.x<0.2?c:c&0xEFFFFFF,2);
k=k==-1?0:k;
if(m.x<0.2&&m.z==0)qs=ps[k];
f l1=qs[0]+m.x*.01;
f l2=qs[1]+m.y*.01;
V z=V(.1,.1);
for(i j=0;j<1<<16;j++){
V p=z,q(1,0),e= V(z.x,-z.y);
for(i j=1;j<qs[5];j++){p = mul(p,z); q=mul(q,e);}
z=z*(l1+l2*(z.x*z.x+z.y*z.y)+qs[2]*p.x)+q*qs[3]+V(-z.y*qs[4],z.x*qs[4]);
d->AddCircleFilled(z*qs[6]+(a+b)/2,1.0,c&0x08FFFFFF,4);
}}

@StephaneMenardais


There you go, 15 bytes removed

#define Q 999
#define L(i,x)for(I i=0;i<x;i++)
#define D(a,b)pow(pow(a.p.x-b.p.x,2)+pow(a.p.y-b.p.y,2),.5)
#define S(...)L(i,Q)if(!E[i].i){E[i]={__VA_ARGS__};i=Q;}
#define J (rand()&511)*.002
#define H(a)a.h--;L(i,8)S(a.p,V(cos(J*9),sin(J*9))*99,2,120,0)
using V=ImVec2;using I=int;struct T{V p,v;I i=0,h=99,s=2;};T E[Q],C,&M=E[Q-1],&N=E[Q-2];void FX(ImDrawList*d,V a,V b,V sz,ImVec4 m,float t){C.p=a+sz/2;M.p=a+V(m.x,m.y)*sz;N.p=a+sz*V(.75,.5)+V(sin(t),cos(t*2))*40;if(t<2){M.i=N.i=9;M.s=1;}else{S(V(b.x,a.y+sz.y*J),V(-50-J*50,0),1,40,0)L(i,Q)if(E[i].i){T&e=E[i];e.p+=e.v/50;I j=50+16*e.i;d->AddCircleFilled(e.p,e.i>8?e.s*10+J*(99-e.h)*.1:e.i,ImColor(e.s&2?j:e.h,e.s&1?j:e.h,e.s?0:e.h)*2,32);if(D(C,e)>200+e.i)e.h=0;L(j,Q){T&f=E[j];if(e.h*f.h&&e.s*f.s==2&&D(e,f)<(f.i+e.i)){H(e);H(f);}}if(!e.h){if(e.i==8)L(i,16)S(e.p,V(cos(J*7),sin(J*7))*99,4,1)e.i=0;}if(e.i==2)e.h-=5;}if(M.h*N.h){if(J<.1)S(N.p,M.p-N.p,4,4)if(J<.01)S(N.p,V(-50,0),8,4)if(!m.z)L(j,4)S(M.p+V(0,(j&1)*(j-2)*4),V(500,j<3?(j-1)*250:0),4,1,1)}}}

changes :

  • replaced if(m.z==0) by if(!m.z)
  • removed an extraneous ; (S(e.p,V(cos(J*7),sin(J*7))*99,4,1);)
  • moved M and N declarations (from T E[Q],C;//...//T&M=E[Q-1];T&N=E[Q-2]; to T E[Q],C,&M=E[Q-1],&N=E[Q-2];//...//

edit: nvm I can’t count, that’s not 15 at all, that’s only 5 my bad

!m.z do not work on my visual since it is the mouse (a float)
thx for the others. your eyes are definitely better than mine ^^

edit: finally i saved 16bytes (thx @Organic-Code) :), i'll try tonight to improve the gfx quality of the spheres
edit2: omg i reduced to 980bytes with a factorisation between explosion particles and bomb explosion (/me dancing!)

That’s peculiar, I am building it using MVSC (not visual studio itself though)

imguiWolf

#define V2 ImVec2
#define fl float
#define in int
#define S 1000
V2 p(S/2,S/2);
fl r=0;
#define c cos
#define s sin
#define re return
in m[S][S];
in g=1;
V2 ro(V2 v){re V2(v.x*s(r)-v.y*c(r),v.x*c(r)+v.y*s(r));}
V2 ro(V2 v,fl b){re V2(v.x*s(b)-v.y*c(b),v.x*c(b)+v.y*s(b));}
fl dot(V2 v1,V2 v2){re v1.x*v2.x+v1.y*v2.y;}
void gm() 
{
    if(!g)re;
    for(in j=0;j<S;j++)for(in i=0;i<S;i++)m[j][i]=rand()>20000;
    m[(in)p.y][(in)p.x]=0;g=0;
}
void FX(ImDrawList*dl,V2 a,V2 b,V2 sz,ImVec4 ms,fl)
{
    gm();
    fl d=sz.x/2/tan(IM_PI/4);
    fl adv=ms.z>=0?ms.z:0;adv=ms.w>=0?-ms.w:adv;
    r=(ms.x-.5)*IM_PI*2;
    V2 f=ro(V2(adv,0));p+=f;
    for(fl x=-sz.x/2;x<sz.x/2;x++){
        V2 ray=V2(x,d)/sqrt(x*x+d*d);ray=ro(ray,r+IM_PI/2);
        V2 q=p;fl s;
        for(s=0;s<S;s+=.01){
            if(m[(in)(q.y)][(in)(q.x)])break;
            q=ray*s+p;
        }
        fl z=dot(q-p,ro(V2(1,0)));
        fl h2=d/z/2;fl l=.15+1/s;in v=((in)q.x+(in)q.y)&1;
        dl->AddLine(V2(x+a.x+sz.x/2,sz.y/2-h2+a.y),V2(x+a.x+sz.x/2,sz.y/2+h2+a.y),ImColor(v*l,l/4,(1-v)*l));
    }
}

This is my entry, Wolf3D style sw rendering in imgui, called imguiWolf.
Mouse.x = yaw
Mouse.LButton = move forward
Mouse.RButton = move backward

Fluid paint

BapO2ZEUVZ
1024 bytes

#define U using
#define L for(I
#define M L y=Y;y--;)L x=X;x--;){
#define R return
#define Z [x][y]
enum{X=160,Y=90};U I=int;U F=float;U A=ImVec2;U B=ImVec4;U C=ImColor;U D=A[X][Y];U E=B[X][Y];A operator+(A a,A b){R{a.x+b.x, a.y+b.y};}A operator*(A v,F f){R{f*v.x,f*v.y};}A G(A v){R{v.x-I(v.x),v.y-I(v.y)};}A J(A p){R A(p.x*-.5+p.y*.87,-p.x*.87-p.y*.5);}F K(F a,F b){R a<b?a:b;}E c,d;D e,f,g,h,i;F j,k;void FX(ImDrawList*_,A a,A b,A,B m,F t){F s,z;M g Z=g Z*.9;d Z=c Z;f Z=e Z;}M A u((x+.5)/X,(y+.5)/Y),a=u*2,t(cos(a.x),sin(a.x)),v;s=.01;L l=4;l--;s*=3.7)L m=3;m--;t=J(t)){A q=t*s,r=u+q,p(cos(a.y),sin(a.y)),b,o,w;z=0;L i=3;i--;p=J(p)){b=p*s,w=G(r+b);I x=w.x*X,y=w.y*Y;o=f Z;z+=(o.x*b.y-o.y*b.x)/(b.x*b.x+b.y*b.y);}v=v+A(-q.y*.02,q.x*.03)*z*.33;}u=G(u+v);I i=u.x*X,m=u.y*Y;c Z=d[i][m];e Z=(f[i][m]+g Z*.08)*.99;}s=m.x,z=m.y;M F a=s*X-x,b=z*Y-y,d=1-K(sqrt(a*a+b*b)/12,1);d*=m.z>0;if(d)c Z=C::HSV(t-I(t),sin(t)*.3+.7,1);e Z=e Z+A((j-s)*16,(k-z)*9)*d*.5;}j=s,k=z;M s=a.x+x*2,z=a.y+y*2;_->AddLine({s,z},{s+1,z+2},C(c Z));}}

Mouse left-click + drag to paint.

Sorry for the heavily compressed code :-s!

Inspired by flockaroo's fluid dynamics (https://www.shadertoy.com/view/MdKXRy).

Ok, here is another one. I thought the ImDrawList coding party needed a disco ball.

DiscoBallD

#define V ImVec2
#define F float
void R(F&x,F&y,F r){F s=sin(r),c=cos(r),t=c*x-s*y;y=s*x+c*y;x=t;}
F c,e,f,g,l,r,x,y,z;
int i,j,k,u,v,K=24,J=48;
F L(F a){l*=l>0;return sqrt(1-exp(-a*(l+.1)-l*l*l));}
void T(F u){R(x,z,c+6.28*u);}
V P(F t){t*=3.14/K;return V(sin(t),cos(t));}
void FX(ImDrawList*d,V a,V b,V S,ImVec4 I,F t){
V o[4],m=(a+b)/2;c=t/2;
k=sin(t*13)*24+24;j=-0xafefb0+k*0x101;d->AddRectFilledMultiColor(a,b,j,j+0x503010,j+0x4050,j+0x7040);
for(k=K;--k;){for(j=J;j--;){for(i=4;i--;){
u=j+(i%3>0);v=-(i/2);
V p=P(k+v);x=p.x;y=p.y;z=0;
T((F)u/J);e=x;f=y;z=S.y/(g=z+2.5);
o[i]=m+V(x,y)*z;}
V v1=P(k),v2=P(k-1);
x=v1.y-v2.y;y=v2.x-v1.x;z=0;
l=sqrt(x*x+y*y);x=x/l;y=y/l;T((j+.5)/J);
r=2*(x*e+y*f+z*g);
e-=r*x;f-=r*y;g-=r*z;
l=sqrt(e*e+f*f+g*g);
x=atan2(e,g);y=atan2(sqrt(e*e+g*g),f);
l=sin(x*5+sin(y*3+t))+sin(x*9+sin(y*5+t))+cos(y*4+sin(x*5+t));
l=l/4+.5;
I.x=l;I.y=l*.9*(.8+e/4);I.z=(.5-f/2)*l/2;I.w=1;
if(r>0)d->AddConvexPolyFilled(o,4,ImColor(I)),d->AddPolyline(o,4,0xff<<24,true,1);
}}}

(1022 bytes)

Amazing work all! As per the undefined behavior of what constitute a deadline of "Nov 30", let's make it maximum-optimistic Pacific Time, aka about 19 extra hours from the time of this post.

What shall we do with this to provide some kind of climax?
Would an "everyone wins" statement constitute enough climax? :)
How about:

  • We assemble everything into a single thing that's somehow shippable (potentially the stub could also play it as a megademo)
  • Publish on the web via emscripten
  • Bonus: with a source / text editor display on the side using ImGuiColorTextEdit ?

sir

#include <vector>
#define Z std::vector
#define V ImVec2
#define W ImVec4
#define F float
#define R return
ImDrawList*gd;V bl;W ey;W la;W z;W x;W y;
W operator*(W&l,F r){R W(l.x*r,l.y*r,l.z*r,l.w*r);}
F d(W v,W w){R v.x*w.x+v.y*w.y+v.z*w.z+v.w*w.w;}
W n(W&v){R v*(1./sqrt(d(v,v)));}
V j(W&v){v.w=1;W r(d(x,v),d(y,v),d(z,v),v.w);V p(r.x*277/r.z+160,-r.y*277/r.z+90);R p+bl;}
#define A(a,b,c) W p##c=(v[a]+v[b])*.5;
#define Q(a,b,c,e,f) P({p##a,p##b,p##c,p##e,p##f},r+1);
#define C(a) W p##a=v[a-10];
#define I ImColor
#define D(a,b,c,f,g,h) gd->AddTriangleFilled(j(v[a]),j(v[b]),j(v[c]),I((F)l*f/10,l*g/10,l*h/10,1.));
void P(Z<W>v,int r){if(r<5) A(0,1,1)A(0,2,2)A(0,3,3)A(0,4,4)A(1,2,5)A(1,3,6)A(2,4,7)A(3,4,8)A(1,4,9)C(10)C(11)C(12)C(13)C(14)Q(1,11,5,6,9)Q(2,5,12,4,7)Q(10,1,2,3,4)Q(3,6,9,13,8)Q(4,9,7,8,14)R;}   F l=2./(v[0].z+5);D(0,2,2,5,5,0)D(0,2,4,0,5,0)D(0,1,3,0,0,10)D(0,3,4,10,0,0)}
void FX(ImDrawList*dl,V a,V,V,W,F t)
{bl=a;gd=dl;ey=W(sin(t/2.)*7,3.,-9,0);la=W(0,1,0,1);z=n(la-ey);x=n(W(z.z,0,-z.x,0));y=W(z.y*x.z-z.z*x.y,z.z*x.x-z.x*x.z,z.x*x.y-z.y*x.x,0);x.w=-d(x,ey);y.w=-d(y,ey);z.w=-d(z,ey);Z<W>v={{0,5,0,1},{-5,0,5,1},{5,0,5,1},{-5,0,-5,1},{5,0,-5,1}};P(v,0);}

3D Sierpinksi Triangle
I tried to reduce to 1024 but did not succeed, if we had ImVec4 math operators in imgui, it could end up being under 1024, maybe worth to share anyway :)

Hello, here's my entry, mixing random terrain generation and some kind of simulation (pseudo random movement, boundary checking). Randomness strives to eat all vegetation; once that happens, everything starts all over.

imgui_contest

````

define g using

g C=int;C f=10;g A=ImVec2;g B=float;bool E=1;B G;B U=IM_PI2;B H=0;B R(A S){C X=S.x+S.y57;X=(X<<13)^X;return .5+.5*(1.-((X*((X*X*15731)+789221)+1376312589)&0x7fffffff)/1073741824.);}B V(B Y,B Z,B X){B W=ImClamp((X-Y)/(Z-Y),0,1);return WW(3-2W);}C I(A S){return C(ImMin(S.x,320-1)/f)+C(ImMin(S.y,180-1)/f)(320/f);}A K[50];B Q[576];void FX(ImDrawListF,A D,A,A b,ImVec4,B T){B J=0;if(E)G=(H+1337e-8(intptr_t)&E);for(C M=0;M<576;++M){A c=A(fmodf(M,320/f),M/(320/f));if(E){B X=R(ImFloor(c)+A(G*f,0));Q[M]=(X<.5?1:(X>.7?0:2))+(H>T-1)1-fmodf(T+M,2.1);}C d,e=d=0;if(Q[M]<=1){e=255-20V(-1,0,fmodf(Q[M],1));d=eV(1,0,Q[M]);}A S=D+cf;F->AddRectFilled(S,S+A(f,10),IM_COL32(d,e,d,255));J+=Q[M]*(Q[M]>0&&Q[M]<=1);}for(C L=0;L<50;++L){if(E)K[L]=A(R(A(T,L)),R(A(L,T)))*b;A S=K[L];B O=(R(ImFloor(S/f)*f+A(L,L))+(C(T*.17))+T*.27*(L%2?1:-1))*U;C a=I(S);B&N=Q[a];N-=.2*(N<=1);A P(cos(O),sin(O));K[L]=ImClamp(K[L]+P*(Q[I(S+P*4)]<=1),A(0,0),b);F->AddCircleFilled(D+S,4,0xFF003acc);}if(H ````
1022Kb, my backend is limited to 60 FPS, I hope the simulation runs well on other configs.

Thanks for ImGui, thanks for all entries, this was a marvellous week !

Thought I'd do something with hexagons! 1024 bytes exactly.

NB4GSN3Bfa

#define V2 ImVec2
#define PI 3.1415926535
#define HP(p,s,c,o) V2(cosf(p * PI / 3 + o) * s + c.x, sinf(p * PI / 3 + o) * s + c.y)
#define SQ(t) sinf(t) + sinf(3*t)/3 + sinf(5*t)/5 + sinf(7*t)/7
#define max(x,y) ((x)>(y)?x:y)
#define min(x,y) ((x)<(y)?x:y)
#define CI(i) ((int)(sinf(i) * 128 + 128)) % 256
#define Z 35.0
// Hexagons! Better make it 1024.
void FX(ImDrawList* d, V2 a, float t) {
    for (int x=-2;x<=5;x++) {
        for (float y = 0; y <= 4; y++) {
            V2 o = V2(a.x + sqrt(3) * Z * (x + y/2), a.y + y * 3 * Z / 2 + max(50*((4+((int)y+x)%5)-(15-15/t)),0));
            for (int s = 0; s <= Z; s += 5) {
                float h = max(0, t < 2.5 ? 0 : SQ(t - 1.5 + x * min(t-2.5,1) + s * 10));
                int l = 0;
                for (int p = 1; p <= 6; p++) {
                    d->AddLine(HP(p % 6, s, o, h + PI / 6), HP(l % 6, s, o, h + PI / 6), IM_COL32(CI(h), CI(h + 2), CI(h + 3), 255));
                    l = p;
                }
            }
        }
    }
}

I'm late to the party but here goes. seven segment timer (resizable).
I really had to cram everything together to fit it into 1015 bytes:

seven_segment

#define W 15
#define H 7.5
#define v ImVec2
#define fl float
#define dr(n,i)d->AddConvexPolyFilled(pp,6,(kd[n]>>(6-i))&1 ? 0xffffffff : 0xff222222)
char kd[]={0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B};void digit(ImDrawList*d,int n,v e,v p){fl r[7][4]={{-1,-1,H,H},{1,-1,-H,H},{1,0,-H,-H},{-1,1,H,-W*1.5},{-1,0,H,-H},{-1,-1,H,H},{-1,0,H,-H},};for(int i=0;i<7;i++){v a,b;if(i%3==0){a=v(p.x+r[i][0]*e.x+r[i][2],p.y+r[i][1]*e.y+r[i][3]-H);b=v(a.x+e.x*2-W,a.y+W);}else{a=v(p.x+r[i][0]*e.x+r[i][2]-H,p.y+r[i][1]*e.y+r[i][3]);b=v(a.x+W,a.y+e.y-W);}v q=b-a;fl s=W*0.6,u=s-H;if(q.x>q.y){v pp[]={{a.x+u,a.y+q.y*.5f},{a.x+s,a.y},{b.x-s,a.y},{b.x-u,a.y+q.y*.5f},{b.x-s,b.y},{a.x+s,b.y}};dr(n,i);}else{v pp[]={{a.x+q.x*.5f,a.y+u},{b.x,a.y+s},{b.x,b.y-s},{b.x-q.x*.5f,b.y-u},{a.x,b.y-s},{a.x,a.y+s}};dr(n,i);}}}void FX(ImDrawList*d,v a,v b,v sz,ImVec4,fl t){int _t=int(t/60)*100+fmod(t,60);fl p=0.02*sz.x,s=sz.x/4-p,x=s*.5,y=sz.y*.5;for(int i=0;i<4;i++){int _d=_t%10;_t/=10;digit(d,_d,v(s*.5,y),v(b.x-x,a.y+y));x+=s+p;}}

https://github.com/ocornut/imgui/issues/3606#issuecomment-735764957
I’m up with that

Might be a headache to put into place though, not all code snippets assumes the same compiler parameters (I had to modify about half of those I tested)
Not that that I’m familiar with emscripten, but if you need some tasking hands let me know

Was this page helpful?
0 / 5 - 0 ratings

Related issues

noche-x picture noche-x  ·  3Comments

ghost picture ghost  ·  3Comments

mnemode2 picture mnemode2  ·  3Comments

NPatch picture NPatch  ·  3Comments

dowit picture dowit  ·  3Comments