尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Parametric 3D/4D Perlin animations in the browser — vanilla JS, no build, seamless loop, WebM export. Worker-accelerated.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Parametric 3D/4D Perlin animations in the browser — worker-accelerated, video export, seamless loop. Fully client-side, no dependencies, no build.
Grown out of two older hobby projects (_archiv/texturizer.ipynb from
early 2023 + _archiv/perlin_noise/ from May 2023) into a focused
browser tool. Designed for static hosting, embedding on a homepage, and
as the basis for an Obsidian plugin.
# Variant A — just double-click
open index.html # macOS
start index.html # Windows
xdg-open index.html # Linux
# Variant B — local server (handy for hot-reload during development)
python3 -m http.server 8000
# → http://localhost:8000
Hit ▶ or Space, click a preset chip, or move any slider — the live preview updates after every input.
a + b·cos(2π(c·t+d)),
fully editable), Flow (renders the noise as a vector field — hue = local
gradient direction)Tile X / Tile Y make the noise wrap modulo a
configurable cell period, so the output repeats seamlessly as a
background texture(z, w), closes
mathematically without any "breathing" artifactMediaRecorderEvery image is a single frame from a built-in preset, rendered by the tool
itself — and reproducible from the presets via
scripts/render-readme-images.js. Together
they show the range of colour modes and features.
Three seamless 2.5-second loops, rendered from the built-in presets via
scripts/render-readme-videos.js.
The WebMs live under docs/examples/ and are directly
linkable from the live demo
(handy for embedding into other docs).
New here? Start with Getting started. Every parameter and control: control reference.
Short version of the most important controls:
| Element | Function |
|---|---|
| Left sidebar | All parameters (resolution, noise, loop, color, presets, export) |
| Large canvas | Live preview (always matches the current slider/input state) |
| ▶ / Space | Play / pause |
| ⏮ | Slider back to 0 |
| t slider | Time scrub (loop: [0, 1), otherwise free) |
| fps / frames | Only used for video export |
Drop the looping animation onto any page with the <perlin-noise> custom
element — renderer only, no controls:
<script src="perlin.js"></script>
<script src="perlin-presets.js"></script>
<script src="perlin-engine.js"></script>
<script src="perlin-element.js"></script>
<perlin-noise preset="aurora" autoplay></perlin-noise>
Configure it with a built-in preset name, a src pointing at a preset
JSON exported from the studio, or the params JS property. It fills its
container responsively (render resolution capped via max-resolution,
default 1280), respects prefers-reduced-motion, and pauses while
off-screen. Works from file:// too — except src, which needs an HTTP
server (use preset or .params locally).
▶ See it live: pages.jkaindl.de/perlin-studio/examples/embed.html — source in examples/embed.html.
Main thread (UI) Web Worker
┌─────────────────┐ ┌────────────────┐
│ RAF loop │ params/t │ makePermutation│
│ gatherParams() │──────────▶│ fbm3/fbm4 │
│ │ │ colorize() │
│ putImageData │ ImageData │ │
│ (zero-copy) │◀──────────│ postMessage │
│ │ │ (transferable)│
└─────────────────┘ └────────────────┘
Full technical docs (math, pipeline, edge cases): docs/explanation/architecture.md.
There is nothing to compile, bundle, or install. The seven scripts you see in
Project layout are the shipped artifact: plain ES5-compatible
JavaScript, each attaching one window global, loaded in order by
index.html. No package.json, no node_modules, no transpiler, no
framework.
That is a deliberate design constraint, not a gap:
file://. Double-clicking index.html gives you the full
tool — no server, no toolchain, no network. The Perlin worker is loaded from
an inline Blob (MTPerlin.WORKER_SOURCE), with an automatic main-thread
fallback where a browser's CSP blocks it.rsync the directory onto any webhost and
it works. No CI step stands between the source and what visitors run.<perlin-noise> drops into any page with four
<script> tags — no build tooling imposed on whoever embeds it.The cost is a deliberate one: no TypeScript, no npm ecosystem, and hand-rolled
solutions where a dependency would be quicker. Quality is gated by
scripts/check-syntax.mjs (parses every deployable script) and
scripts/smoke-test.js (Perlin math invariants) rather than by a compiler —
both run before the site is published.
If you want to change this, talk to the maintainer first — see AGENTS.md.
| Browser | Status |
|---|---|
| Chrome / Edge (Chromium) ≥ 90 | ✅ full incl. worker; exports MP4/H.264 (Chrome ≥ 126) or VP9 WebM |
| Firefox ≥ 90 | ✅ full; exports WebM (VP8/VP9) — no MP4 muxer |
| Safari ≥ 14 | ✅ live preview; exports MP4/H.264 (Safari ≥ 14.1 / iOS ≥ 14.5); some versions block the worker under file:// → falls back to main thread |
| Mobile Safari / Chrome Mobile | ✅ live preview; MP4 export (iOS ≥ 14.5); may require a longer touch gesture |
The app is responsive and works on mobile — the worker path keeps the animation smooth even at low resolutions.
.
├── index.html # UI markup
├── styles.css # theme (dark + light, system-following with topbar toggle override)
├── perlin.js # math/API (3D + 4D noise, color modes, worker source)
├── perlin-presets.js # gradients, built-in presets, resolveParams (shared)
├── perlin-engine.js # headless render engine (worker + RAF loop)
├── perlin-gl.js # optional WebGL2 renderer (port of the noise maths)
├── perlin-studio.js # controller (UI, recording, presets, events)
├── perlin-element.js # <perlin-noise> embeddable custom element
├── manifest.webmanifest # PWA manifest (installable)
├── assets/ # static assets (favicon, PWA icons, README images)
├── examples/
│ └── embed.html # <perlin-noise> embedding demo
├── docs/ # documentation, see docs/README.md (Diátaxis)
│ ├── tutorials/ # getting started
│ ├── how-to/ # task guides, troubleshooting
│ ├── reference/ # controls, colour modes, preset format, element
│ ├── explanation/ # architecture, design choices
│ ├── internal/ # notes for contributors and agents
│ └── examples/ # rendered WebM loops (for README + embedding)
├── scripts/
│ ├── render-readme-images.js # renders assets/*.png from perlin.js
│ └── render-readme-videos.js # renders docs/examples/*.webm (Node → ffmpeg)
├── _archiv/ # historical predecessors (READ-ONLY)
│ ├── perlin_noise/ # Python original
│ ├── texturizer.ipynb # Texturizer notebook
│ └── old_texturizer_combined/ # first browser version, incl. Texturizer
├── LICENSE # AGPL-3.0
├── CHANGELOG.md
├── CONTRIBUTING.md
├── SECURITY.md # threat model + reporting
└── AGENTS.md # context file for AI assistants
The documentation is split by what you need it for (index):
<perlin-noise> element.Issues and PRs welcome. Developer quickstart: CONTRIBUTING.md.
Security-related reports — please don't file them publicly. See SECURITY.md.
AI assistants (Claude Code, etc.) get their orientation in AGENTS.md.
Shipped since the original list:
Tile X / Tile Y make the output repeat (v0.10.0)<perlin-noise> renderer element (v0.12.0)Still on the wishlist:
main.ts with a modal + canvas embed (separate repo)<perlin-studio> element — the full editor (controls + canvas) as a
single embeddable tag, building on the shared PerlinEngineConsidered and explicitly deferred:
gif.js would be
the project's first JavaScript dependency. The Discord/Slack
reach gain doesn't justify breaking the "no dependencies"
principle.Perlin Studio is dual-licensed — see LICENSING.md for the full picture:
The Perlin permutation table and the "Improved Noise" algorithm come from Ken Perlin's freely published Java reference (2002), reimplemented here in JS.