Loading playground
Input
Additional Settings
Customize your input with more control.
Result
Idle
Customize your input with more control.
Customize your input with more control.
Hint: Drag and drop video files from your computer, video from web pages, paste from clipboard (Ctrl/Cmd+V), or provide a URL. Accepted file types: mp4, mov, webm, m4v, gif
Hint: Drag and drop image files from your computer, images from web pages, paste from clipboard (Ctrl/Cmd+V), or provide a URL. Accepted file types: jpg, jpeg, png, webp, gif, avif, heic, heif
Hint: Drag and drop audio files from your computer, audio from web pages, paste from clipboard (Ctrl/Cmd+V), or provide a URL. Accepted file types: mp3, ogg, wav, m4a, aac
Customize your input with more control.
{
"code": "// Shot list (6 s loop, DURATION = 6)\n// 0.00-1.50s The push starts at once. A warm, sunlit cumulus mass sits on the left and\n// dark backlit towers on the right. A low sun sits just right of centre, in\n// the gap between them.\n// 1.50-3.00s The push speeds up and the left masses swell toward the lens.\n// 3.00-4.25s Fastest stretch. Wisps stream past and the sun flares through the gap.\n// 4.25-6.00s A new valley opens toward the sun. The move eases into the loop point.\n// The cloud field is periodic in z with period P. The camera travels exactly P per loop.\n\n#define DURATION 6.0\n#define PI 3.14159265\n#define PERIOD 16.0\n\nvec3 gRo; // camera position, shared with the density function\nvec3 gSun; // sun direction\n\n// cheap 3D hash\nfloat hash3(vec3 p){\n p = fract(p*0.3183099 + 0.1);\n p *= 17.0;\n return fract(p.x*p.y*p.z*(p.x+p.y+p.z));\n}\n\n// value noise whose lattice wraps in z every 'per' cells\nfloat noiseP(vec3 x, float per){\n vec3 i = floor(x), f = fract(x);\n f = f*f*(3.0-2.0*f);\n float z0 = mod(i.z, per), z1 = mod(i.z+1.0, per);\n float a = hash3(vec3(i.x, i.y, z0)), b = hash3(vec3(i.x+1.0, i.y, z0));\n float c = hash3(vec3(i.x, i.y+1.0, z0)), d = hash3(vec3(i.x+1.0, i.y+1.0, z0));\n float e = hash3(vec3(i.x, i.y, z1)), g = hash3(vec3(i.x+1.0, i.y, z1));\n float h = hash3(vec3(i.x, i.y+1.0, z1)), k = hash3(vec3(i.x+1.0, i.y+1.0, z1));\n return mix(mix(mix(a,b,f.x), mix(c,d,f.x), f.y),\n mix(mix(e,g,f.x), mix(h,k,f.x), f.y), f.z);\n}\n\n// z-periodic fbm, at most 4 octaves\nfloat fbm(vec3 q, int oct){\n float s = 0.0, a = 0.5, per = PERIOD*0.5;\n for(int i = 0; i < 4; i++){\n if(i >= oct) break;\n s += a*noiseP(q, per);\n q = q*2.0 + vec3(1.7, 9.2, 0.0);\n per *= 2.0; a *= 0.5;\n }\n return s;\n}\n\n// position relative to the camera-to-sun line: x = side of the gap, y = height above it\nvec2 sunFrame(vec3 p){\n float dz = p.z - gRo.z;\n return vec2(p.x - gRo.x - gSun.x/gSun.z*dz, p.y - gRo.y - gSun.y/gSun.z*dz);\n}\n\n// cumulus density: lit mass on the left, tall towers on the right, a low gap toward the sun\nfloat cloudDensity(vec3 p, int oct){\n vec2 s = sunFrame(p);\n float leftTop = 1.0*smoothstep(-0.6, -2.6, s.x);\n float rightTop = 1.7*smoothstep(0.35, 1.9, s.x);\n float h = -0.45 + max(leftTop, rightTop); // cloud-top height profile\n float n = fbm(p*0.55, oct);\n float d = n - 0.47 + 0.55*clamp(h - s.y, -1.0, 1.0);\n return clamp(d*6.0, 0.0, 1.0);\n}\n\n// sky: lavender top, peach horizon, sun glow and thin cirrus streaks\nvec3 skyColor(vec3 rd, vec3 sun){\n vec3 top = vec3(0.36, 0.34, 0.45);\n vec3 hor = vec3(0.92, 0.55, 0.30);\n vec3 col = mix(hor, top, smoothstep(0.0, 0.5, rd.y));\n float s = max(dot(rd, sun), 0.0);\n col += vec3(1.0, 0.62, 0.30)*(pow(s, 8.0)*0.6 + pow(s, 120.0)*1.6);\n col += vec3(4.0, 3.2, 2.2)*smoothstep(0.99975, 0.99990, s);\n float streak = fbm(vec3(rd.x*3.0, rd.y*28.0, 0.5), 3);\n float band = smoothstep(0.5, 0.75, streak)*smoothstep(0.05, 0.2, rd.y)*smoothstep(0.6, 0.25, rd.y);\n col = mix(col, vec3(0.75, 0.55, 0.50)*(0.6 + 1.2*pow(s, 4.0)), band*0.6);\n return col;\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord){\n vec2 uv = (2.0*fragCoord - iResolution.xy) / iResolution.y;\n float t = mod(iTime, DURATION);\n float u = t / DURATION;\n\n // eased travel: moving from frame 0, wraps exactly at u = 1\n float z = PERIOD*(u - 0.35*sin(2.0*PI*u)/(2.0*PI));\n gRo = vec3(0.12*sin(2.0*PI*u), 0.05*sin(2.0*PI*u + 1.0), z);\n gSun = normalize(vec3(0.28, 0.12, 1.6));\n vec3 ro = gRo, sun = gSun;\n\n vec3 fw = normalize(vec3(0.0, 0.04, 1.0));\n vec3 rt = normalize(cross(vec3(0,1,0), fw));\n vec3 up = cross(fw, rt);\n vec3 rd = normalize(fw*1.6 + rt*uv.x + up*uv.y);\n\n vec3 sky = skyColor(rd, sun);\n vec3 hazeC = vec3(0.85, 0.52, 0.34);\n vec3 litC = vec3(1.00, 0.55, 0.30);\n vec3 edgeC = vec3(1.40, 0.95, 0.55);\n vec3 darkC = vec3(0.075, 0.062, 0.095);\n vec3 midC = vec3(0.20, 0.13, 0.15);\n\n // volumetric march\n vec3 acc = vec3(0.0);\n float T = 1.0;\n float d = 0.1 + 0.12*hash3(vec3(fragCoord, 1.0));\n float ph = max(dot(rd, sun), 0.0);\n for(int i = 0; i < 72; i++){\n if(T < 0.02) break;\n vec3 p = ro + rd*d;\n float st = 0.12 + d*0.04;\n float den = cloudDensity(p, 4);\n if(den > 0.005){\n float ld = cloudDensity(p + sun*0.5, 2) + cloudDensity(p + sun*1.3, 2);\n float sh = exp(-ld*2.2);\n vec2 s = sunFrame(p);\n float warmSide = 0.25 + 0.75*smoothstep(-0.4, -2.2, s.x);\n vec3 c = mix(darkC, midC, smoothstep(-1.5, 1.0, s.y));\n c = mix(c, litC, sh*warmSide);\n c += edgeC*sh*pow(ph, 8.0)*2.0*(1.0 - den); // silver lining\n float fog = 1.0 - exp(-d*0.035);\n c = mix(c, hazeC, fog);\n float a = 1.0 - exp(-den*st*7.0);\n acc += T*a*c;\n T *= 1.0 - a;\n }\n d += st;\n }\n vec3 col = acc + T*sky;\n\n // soft crepuscular rays, mostly where sky shows through\n vec3 sc = vec3(dot(sun, rt), dot(sun, up), dot(sun, fw));\n vec2 sp = sc.xy/sc.z*1.6;\n vec2 dv = uv - sp;\n float r = length(dv);\n float ang = atan(dv.y, dv.x);\n float rays = pow(0.5 + 0.5*sin(ang*23.0 + sin(ang*9.0)*3.0), 6.0)\n * (0.5 + 0.5*sin(ang*5.0 + 1.3));\n col += edgeC*(rays*exp(-r*2.6)*0.25*(0.2 + 0.8*T) + exp(-r*5.0)*0.25);\n\n // tone map, vignette, gamma\n col = 1.0 - exp(-col*1.4);\n col *= 1.0 - 0.22*dot(uv*0.5, uv*0.5);\n col = pow(max(col, 0.0), vec3(0.4545));\n fragColor = vec4(col, 1.0);\n}",
"html": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Shader</title>\n<style>\n html, body { margin: 0; height: 100%; background: #000; overflow: hidden }\n canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block }\n</style>\n</head>\n<body>\n<canvas id=\"stage\"></canvas>\n<script>\n// Shadertoy-style host: window.anim = { duration, seek(t), play(from), pause() }.\n// ?external=1 does not autoplay; data-ready=\"1\" once frame 0 is drawn.\n(() => {\nconst SHADER = \"// Shot list (6 s loop, DURATION = 6)\\n// 0.00-1.50s The push starts at once. A warm, sunlit cumulus mass sits on the left and\\n// dark backlit towers on the right. A low sun sits just right of centre, in\\n// the gap between them.\\n// 1.50-3.00s The push speeds up and the left masses swell toward the lens.\\n// 3.00-4.25s Fastest stretch. Wisps stream past and the sun flares through the gap.\\n// 4.25-6.00s A new valley opens toward the sun. The move eases into the loop point.\\n// The cloud field is periodic in z with period P. The camera travels exactly P per loop.\\n\\n#define DURATION 6.0\\n#define PI 3.14159265\\n#define PERIOD 16.0\\n\\nvec3 gRo; // camera position, shared with the density function\\nvec3 gSun; // sun direction\\n\\n// cheap 3D hash\\nfloat hash3(vec3 p){\\n p = fract(p*0.3183099 + 0.1);\\n p *= 17.0;\\n return fract(p.x*p.y*p.z*(p.x+p.y+p.z));\\n}\\n\\n// value noise whose lattice wraps in z every 'per' cells\\nfloat noiseP(vec3 x, float per){\\n vec3 i = floor(x), f = fract(x);\\n f = f*f*(3.0-2.0*f);\\n float z0 = mod(i.z, per), z1 = mod(i.z+1.0, per);\\n float a = hash3(vec3(i.x, i.y, z0)), b = hash3(vec3(i.x+1.0, i.y, z0));\\n float c = hash3(vec3(i.x, i.y+1.0, z0)), d = hash3(vec3(i.x+1.0, i.y+1.0, z0));\\n float e = hash3(vec3(i.x, i.y, z1)), g = hash3(vec3(i.x+1.0, i.y, z1));\\n float h = hash3(vec3(i.x, i.y+1.0, z1)), k = hash3(vec3(i.x+1.0, i.y+1.0, z1));\\n return mix(mix(mix(a,b,f.x), mix(c,d,f.x), f.y),\\n mix(mix(e,g,f.x), mix(h,k,f.x), f.y), f.z);\\n}\\n\\n// z-periodic fbm, at most 4 octaves\\nfloat fbm(vec3 q, int oct){\\n float s = 0.0, a = 0.5, per = PERIOD*0.5;\\n for(int i = 0; i \\u003c 4; i++){\\n if(i >= oct) break;\\n s += a*noiseP(q, per);\\n q = q*2.0 + vec3(1.7, 9.2, 0.0);\\n per *= 2.0; a *= 0.5;\\n }\\n return s;\\n}\\n\\n// position relative to the camera-to-sun line: x = side of the gap, y = height above it\\nvec2 sunFrame(vec3 p){\\n float dz = p.z - gRo.z;\\n return vec2(p.x - gRo.x - gSun.x/gSun.z*dz, p.y - gRo.y - gSun.y/gSun.z*dz);\\n}\\n\\n// cumulus density: lit mass on the left, tall towers on the right, a low gap toward the sun\\nfloat cloudDensity(vec3 p, int oct){\\n vec2 s = sunFrame(p);\\n float leftTop = 1.0*smoothstep(-0.6, -2.6, s.x);\\n float rightTop = 1.7*smoothstep(0.35, 1.9, s.x);\\n float h = -0.45 + max(leftTop, rightTop); // cloud-top height profile\\n float n = fbm(p*0.55, oct);\\n float d = n - 0.47 + 0.55*clamp(h - s.y, -1.0, 1.0);\\n return clamp(d*6.0, 0.0, 1.0);\\n}\\n\\n// sky: lavender top, peach horizon, sun glow and thin cirrus streaks\\nvec3 skyColor(vec3 rd, vec3 sun){\\n vec3 top = vec3(0.36, 0.34, 0.45);\\n vec3 hor = vec3(0.92, 0.55, 0.30);\\n vec3 col = mix(hor, top, smoothstep(0.0, 0.5, rd.y));\\n float s = max(dot(rd, sun), 0.0);\\n col += vec3(1.0, 0.62, 0.30)*(pow(s, 8.0)*0.6 + pow(s, 120.0)*1.6);\\n col += vec3(4.0, 3.2, 2.2)*smoothstep(0.99975, 0.99990, s);\\n float streak = fbm(vec3(rd.x*3.0, rd.y*28.0, 0.5), 3);\\n float band = smoothstep(0.5, 0.75, streak)*smoothstep(0.05, 0.2, rd.y)*smoothstep(0.6, 0.25, rd.y);\\n col = mix(col, vec3(0.75, 0.55, 0.50)*(0.6 + 1.2*pow(s, 4.0)), band*0.6);\\n return col;\\n}\\n\\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord){\\n vec2 uv = (2.0*fragCoord - iResolution.xy) / iResolution.y;\\n float t = mod(iTime, DURATION);\\n float u = t / DURATION;\\n\\n // eased travel: moving from frame 0, wraps exactly at u = 1\\n float z = PERIOD*(u - 0.35*sin(2.0*PI*u)/(2.0*PI));\\n gRo = vec3(0.12*sin(2.0*PI*u), 0.05*sin(2.0*PI*u + 1.0), z);\\n gSun = normalize(vec3(0.28, 0.12, 1.6));\\n vec3 ro = gRo, sun = gSun;\\n\\n vec3 fw = normalize(vec3(0.0, 0.04, 1.0));\\n vec3 rt = normalize(cross(vec3(0,1,0), fw));\\n vec3 up = cross(fw, rt);\\n vec3 rd = normalize(fw*1.6 + rt*uv.x + up*uv.y);\\n\\n vec3 sky = skyColor(rd, sun);\\n vec3 hazeC = vec3(0.85, 0.52, 0.34);\\n vec3 litC = vec3(1.00, 0.55, 0.30);\\n vec3 edgeC = vec3(1.40, 0.95, 0.55);\\n vec3 darkC = vec3(0.075, 0.062, 0.095);\\n vec3 midC = vec3(0.20, 0.13, 0.15);\\n\\n // volumetric march\\n vec3 acc = vec3(0.0);\\n float T = 1.0;\\n float d = 0.1 + 0.12*hash3(vec3(fragCoord, 1.0));\\n float ph = max(dot(rd, sun), 0.0);\\n for(int i = 0; i \\u003c 72; i++){\\n if(T \\u003c 0.02) break;\\n vec3 p = ro + rd*d;\\n float st = 0.12 + d*0.04;\\n float den = cloudDensity(p, 4);\\n if(den > 0.005){\\n float ld = cloudDensity(p + sun*0.5, 2) + cloudDensity(p + sun*1.3, 2);\\n float sh = exp(-ld*2.2);\\n vec2 s = sunFrame(p);\\n float warmSide = 0.25 + 0.75*smoothstep(-0.4, -2.2, s.x);\\n vec3 c = mix(darkC, midC, smoothstep(-1.5, 1.0, s.y));\\n c = mix(c, litC, sh*warmSide);\\n c += edgeC*sh*pow(ph, 8.0)*2.0*(1.0 - den); // silver lining\\n float fog = 1.0 - exp(-d*0.035);\\n c = mix(c, hazeC, fog);\\n float a = 1.0 - exp(-den*st*7.0);\\n acc += T*a*c;\\n T *= 1.0 - a;\\n }\\n d += st;\\n }\\n vec3 col = acc + T*sky;\\n\\n // soft crepuscular rays, mostly where sky shows through\\n vec3 sc = vec3(dot(sun, rt), dot(sun, up), dot(sun, fw));\\n vec2 sp = sc.xy/sc.z*1.6;\\n vec2 dv = uv - sp;\\n float r = length(dv);\\n float ang = atan(dv.y, dv.x);\\n float rays = pow(0.5 + 0.5*sin(ang*23.0 + sin(ang*9.0)*3.0), 6.0)\\n * (0.5 + 0.5*sin(ang*5.0 + 1.3));\\n col += edgeC*(rays*exp(-r*2.6)*0.25*(0.2 + 0.8*T) + exp(-r*5.0)*0.25);\\n\\n // tone map, vignette, gamma\\n col = 1.0 - exp(-col*1.4);\\n col *= 1.0 - 0.22*dot(uv*0.5, uv*0.5);\\n col = pow(max(col, 0.0), vec3(0.4545));\\n fragColor = vec4(col, 1.0);\\n}\";\nconst DURATION = 6.0;\nconst canvas = document.getElementById('stage');\nconst gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true });\nconst vert = `#version 300 es\nin vec2 p; void main() { gl_Position = vec4(p, 0.0, 1.0); }`;\nconst frag = `#version 300 es\nprecision highp float;\nuniform vec3 iResolution; uniform float iTime; uniform int iFrame; uniform vec4 iMouse;\nout vec4 outColor;\n${SHADER}\nvoid main() { vec4 c = vec4(0.0, 0.0, 0.0, 1.0); mainImage(c, gl_FragCoord.xy); outColor = vec4(c.rgb, 1.0); }`;\nfunction compile(type, source) {\n const shader = gl.createShader(type);\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(shader));\n return shader;\n}\nconst program = gl.createProgram();\ngl.attachShader(program, compile(gl.VERTEX_SHADER, vert));\ngl.attachShader(program, compile(gl.FRAGMENT_SHADER, frag));\ngl.linkProgram(program);\nif (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(gl.getProgramInfoLog(program));\ngl.useProgram(program);\ngl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());\ngl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);\nconst loc = gl.getAttribLocation(program, 'p');\ngl.enableVertexAttribArray(loc);\ngl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);\nconst u = name => gl.getUniformLocation(program, name);\nfunction resize() {\n const ratio = window.devicePixelRatio || 1;\n canvas.width = Math.round(canvas.clientWidth * ratio);\n canvas.height = Math.round(canvas.clientHeight * ratio);\n gl.viewport(0, 0, canvas.width, canvas.height);\n}\nfunction seek(t) {\n gl.uniform3f(u('iResolution'), canvas.width, canvas.height, 1);\n gl.uniform1f(u('iTime'), t);\n gl.uniform1i(u('iFrame'), Math.round(t * 60));\n gl.uniform4f(u('iMouse'), 0, 0, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n gl.finish();\n}\nlet start = null, raf = 0;\nfunction tick(now) { seek(((now - start) / 1000) % DURATION); raf = requestAnimationFrame(tick); }\nfunction play(from = 0) { cancelAnimationFrame(raf); start = performance.now() - from * 1000; raf = requestAnimationFrame(tick); }\nfunction pause() { cancelAnimationFrame(raf); }\nwindow.anim = { duration: DURATION, seek, play, pause };\nresize();\nwindow.addEventListener('resize', resize);\nseek(0);\ndocument.documentElement.dataset.ready = '1';\nif (!new URLSearchParams(location.search).has('external')) play(0);\n})();\n</script>\n</body>\n</html>\n",
"video": {
"url": "https://v3b.fal.media/files/b/0ab01c83/nQA1cbpg3TZ69It4bRyNN_WCgGJA9s.mp4",
"content_type": "video/mp4",
"file_name": "nQA1cbpg3TZ69It4bRyNN_WCgGJA9s.mp4",
"file_size": 925544,
"width": 640,
"height": 360,
"fps": 12,
"duration": 6,
"num_frames": 72
},
"contact_sheet": {
"url": "https://v3b.fal.media/files/b/0ab01c83/rI0Y4kEG9HGPzN0TOWrPs_WUYEtZGJ.png",
"content_type": "image/png",
"file_name": "rI0Y4kEG9HGPzN0TOWrPs_WUYEtZGJ.png",
"file_size": null,
"width": null,
"height": null
},
"reference_video": {
"url": "https://v3b.fal.media/files/b/0ab01c68/vwuhox9UKluKLlRNXRtY__minimax-h3.mp4",
"content_type": "video/mp4",
"file_name": null,
"file_size": null,
"width": null,
"height": null,
"fps": null,
"duration": null,
"num_frames": null
},
"duration": 6,
"rounds": 2,
"timings": {
"source": 15.55,
"study": 24.13,
"generate": 54.52,
"render": 96.35,
"refine": 85.64,
"encode": 19.43
}
}Your request will cost $0.30 per second of animation when MiniMax H3 Max animates your prompt or image first, or $0.20 per second from your own video, with a 5-second minimum: a 6-second loop from a prompt costs $1.80, a 10-second clip rebuilt from your video $2.00.