FreeVJ FULL AUTO VJ LOOP

FreeVJ / 루프 라이브러리 / 시퀀스

Ai Sigil Redraws Itself

A single luminous white sigil endlessly redraws its thin interlocking arcs on black.

Ai Sigil Redraws Itself
이 루프를 라이브로 켜기

내보내기는 이 브라우저에서 만들어 바로 저장합니다.

GLSL 소스

const float SEQ_N = 24.0;
const float SEQ_COLS = 5.0;
const float SEQ_ROWS = 5.0;
const float SEQ_LUMA_ALPHA = 1.0;
const float SEQ_COVER = 0.0;
// Sequence (seq@1) shared shader — plays the frames of a greyscale atlas (uTex) by mode.
// SEQ_N · SEQ_COLS · SEQ_ROWS · SEQ_LUMA_ALPHA · SEQ_COVER constants are prepended.
// uParams: x=mode (0 A→B · 1 B→A · 2 A→B→A · 3 random N s each · 4 sliced panes · 5 slot reel) y=speed (frames/beat) z=hold (s) w=panes (panes · reels)
// Neighbouring frames are crossfaded so even few frames flow — a morph melts A into B this way.

float seqCell(float f, vec2 p) {
    if (p.x < 0.0 || p.y < 0.0 || p.x > 1.0 || p.y > 1.0) return 0.0;
    f = mod(floor(f), SEQ_N);
    vec2 grid = vec2(SEQ_COLS, SEQ_ROWS);
    vec2 cell = vec2(mod(f, SEQ_COLS), floor(f / SEQ_COLS));
    vec2 inset = 0.75 / vec2(textureSize(uTex, 0)) * grid;      // keep samples off the neighbouring cells
    vec2 q = clamp(vec2(p.x, 1.0 - p.y), inset, 1.0 - inset);
    return texture(uTex, (cell + q) / grid).r;
}

float seqAt(float pos, vec2 p) {
    return mix(seqCell(pos, p), seqCell(pos + 1.0, p), smoothstep(0.0, 1.0, fract(pos)));
}

// window (aspect win) coords → frame coords. contain (masks · symbols: never cropped) · cover (video: fill)
vec2 seqFit(vec2 q, float win) {
    vec2 ts = vec2(textureSize(uTex, 0));
    float cell = (ts.x / SEQ_COLS) / max(1.0, ts.y / SEQ_ROWS);
    vec2 p = q - 0.5;
    bool wide = win > cell;
    if ((SEQ_COVER > 0.5) != wide) p.x *= win / cell;
    else p.y *= cell / win;
    return p + 0.5;
}

vec2 prim(vec2 uv) {
    float mode = floor(uParams.x + 0.5);
    float sp = max(0.05, uParams.y);
    float aspect = uResolution.x / max(1.0, uResolution.y);
    float n = SEQ_N;
    float l = 0.0;

    if (mode < 3.5) {
        float pos;
        if (mode < 0.5) pos = uBeat * sp;                                   // A → B
        else if (mode < 1.5) pos = -uBeat * sp;                             // B → A
        else if (mode < 2.5) {                                              // A → B → A
            float per = max(1.0, 2.0 * (n - 1.0));
            float x = mod(uBeat * sp, per);
            pos = x < n - 1.0 ? x : per - x;
        } else {                                                            // random N s each — every segment flows from a different start frame
            float hold = max(0.25, uParams.z);
            float k = floor(uTime / hold);
            float t = uTime - k * hold;
            pos = floor(h11(k * 7.13 + uSeed * 0.37) * n) + t * sp * 2.0;
            l = smoothstep(0.0, 0.06, t);                                   // dip very briefly at the cut (no flash)
        }
        float v = seqAt(pos, seqFit(uv, aspect));
        l = mode > 2.5 ? v * l : v;
    } else if (mode < 4.5) {                                                // panes — sliced into vertical panes with their own phase, flowing up and down alternately
        float k = clamp(floor(uParams.w + 0.5), 1.0, 8.0);
        float i = floor(uv.x * k);
        float lx = fract(uv.x * k);
        float dir = mod(i, 2.0) < 0.5 ? 1.0 : -1.0;
        vec2 q = vec2(uv.x, fract(uv.y + dir * uBeat * 0.125 * sp));
        l = seqAt(uBeat * sp + i * n / k, seqFit(q, aspect));
        l *= smoothstep(0.0, 0.02, lx) * smoothstep(1.0, 0.98, lx);        // gap between panes
    } else {                                                                // slot reel — reels spin, then stop one by one with a small bounce
        float k = clamp(floor(uParams.w + 0.5), 1.0, 8.0);
        float hold = max(0.5, uParams.z);
        float i = floor(uv.x * k);
        vec2 q = vec2(fract(uv.x * k), uv.y);
        float cyc = floor(uTime / hold);
        float t = fract(uTime / hold);
        float stopAt = min(0.92, 0.3 + i * 0.6 / k);
        float from = floor(h11((cyc - 1.0) * 3.1 + i * 17.7 + uSeed) * n);
        float to = floor(h11(cyc * 3.1 + i * 17.7 + uSeed) * n);
        float e = 1.0 - pow(1.0 - clamp(t / stopAt, 0.0, 1.0), 3.0);
        float bounce = sin(clamp((t - stopAt) / 0.1, 0.0, 1.0) * 3.14159) * 0.06;
        float s = from + e * (2.0 * n + mod(to - from + n, n)) - bounce;
        float y = q.y + s;
        float win = aspect / k;
        l = seqCell(floor(y), seqFit(vec2(q.x, fract(y)), win));
        float spin = 1.0 - smoothstep(0.55, 1.0, clamp(t / stopAt, 0.0, 1.0));
        l = mix(l, seqCell(floor(y - 0.18), seqFit(vec2(q.x, fract(y - 0.18)), win)), 0.45 * spin);   // blur while spinning
        l *= smoothstep(0.0, 0.025, q.x) * smoothstep(1.0, 0.975, q.x);
    }

    l = clamp(l, 0.0, 1.0);
    return vec2(l, SEQ_LUMA_ALPHA > 0.5 ? l : 1.0);
}

공통 유니폼 계약(uBeat · uBass · uKick …)을 받는 vec2 prim(vec2 uv) 하나입니다. 출력은 luma 와 alpha 뿐입니다.

비슷한 루프

☕ Buy me a coffee

FreeVJ 는 무료입니다. 마음에 드셨다면 커피 한 잔 값의 USDT 로 만드는 사람을 응원해 주세요.

USDT · TRON (TRC20) TRC20 네트워크로만

TVg11kWumyqNpRU9HXKo8a8u2fa8sdJtKh

☕ 3 USDT☕☕ 5 USDT☕☕☕ 10 USDT

바이낸스로 보내는 법
  1. 바이낸스 앱: 지갑 › 출금 › USDT › 주소 붙여 넣기(또는 QR 스캔) › 네트워크 TRC20 › 금액 › 확인. 받는 주소가 바이낸스 주소라 내부 이체로 수수료 없이 처리될 수 있습니다.
  2. 다른 지갑 · 거래소(Trust Wallet · OKX · Bybit 등): USDT 를 TRC20 네트워크로 같은 주소에 보내세요. 개인 지갑은 수수료로 TRX 가 조금 필요합니다.

반드시 TRC20 네트워크로 보내세요. 다른 네트워크로 보낸 USDT 는 되찾기 어렵습니다.