@codejen/pack-glsl

中文文档
2.6.1发布于 2026/11/02MIT-0 AND MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 1850

jen pack for GLSL: shader starters, SDF/raymarching, noise and lighting snippets (MIT-licensed, attributed)

原始使用文档
文档目录11 节
  1. Install
  2. WebGL playground
  3. Noise
  4. Signed distance fields and raymarching
  5. Lighting
  6. Filters
  7. Vertex displacement and matrices
  8. How functions get into your shader
  9. Where files go
  10. Licenses
  11. License

@codejen/pack-glsl

A jen pack for GLSL: fragment and vertex shader starters, plus functions you can drop into any shader. WebGL2's GLSL ES 3.00 is the default; everything also compiles as desktop GLSL 3.30 / 4.10 core, and glsl:port switches a shader's header when you move a prototype from the browser to C++/OpenGL.

Documentation: https://learosema.github.io/jen/glsl.html

Install

npm install --save-dev @codejen/pack-glsl   # or: npm install -g @codejen/jen @codejen/pack-glsl
jen glsl:frag --name=Clouds                                    # shaders/clouds.frag.glsl
jen glsl:util --fns=rot2,remap --into=shaders/clouds.frag.glsl # insert helpers before main()
jen glsl:port --file=shaders/clouds.frag.glsl --to=410         # ready for cpp:sdl3-opengl
jen cpp:shader --file=shaders/clouds.frag.glsl                 # (pack-cpp) embed it in the CMake build

WebGL playground

jen glsl:webgl --name=Clouds            # index.html, shader-canvas.js, shaders/clouds.frag.glsl
jen glsl:webgl --name=Clouds --inline   # shader inside index.html – opens straight from disk

<shader-canvas> is a single dependency-free script. It feeds uTime, uResolution and uMouse, shows compile errors with the original line numbers over the canvas, and with live recompiles whenever the shader file changes (fetching files needs any static server, e.g. npx serve). It also draws mesh="plane|sphere" with a custom vert shader (drag with orbit), binds texture0…texture3 to uTexture0…uTexture3, pauses offscreen and respects prefers-reduced-motion. Desktop shaders (#version 410 core) run unchanged, so the same file works in the browser and in cpp:sdl3-opengl. See its README for all attributes, uniforms and events.

Noise

jen glsl:noise --kind=fbm --into=shaders/clouds.frag.glsl                  # simplexFbm(p, octaves[, gain])
jen glsl:noise --kind=worley --dim=3 --into=shaders/cells.frag.glsl        # worleyNoise(vec3), worley(vec3) → F1, F2
jen glsl:noise --kind=warp --name=Marble --tile                             # preview shader, drawn 2×2 to show the seams
  • Base noises (--kind=value|perlin|simplex|worley): <kind>Noise(p), about [-1, 1]. Worley also has worley(p), the distances to the nearest two feature points.
  • Fractals (--kind=fbm|turbulence|ridged|warp): <base>Fbm(p, octaves) and friends, on any base noise via --base (default simplex). An optional gain (default 0.5) sets the roughness; warp takes a strength (default 2.0) instead. Different bases can share a shader: perlinFbm and simplexFbm don't clash.
  • Flow (--kind=curl): curlNoise(p, alpha), a divergence-free vector field for particles; animate alpha for swirling motion.

Everything comes in 2D and 3D (--dim=2|3), and every function has an overload with a period that tiles seamlessly, e.g. simplexFbm(p, vec2(4.0), 6). It's the same trick as SVG feTurbulence's stitchTiles, but for any noise: each octave doubles the period along with the frequency. Periods are positive whole numbers; 2D simplex wants an even period along y, and 3D simplex periods are limited to 289.

Signed distance fields and raymarching

jen glsl:raymarch --name=Scene                     # starter: scene(), orbiting camera, soft shadows, AO, fog
jen glsl:raymarch --name=Scene --minimal           # just march, normal and diffuse light
jen glsl:raymarch --name=Scene --materials         # sceneMaterial() also returns a material id per surface
jen glsl:raymarch --name=Scene --lighting=pbr      # lambert (default), blinn, toon or pbr
jen glsl:raymarch --name=Land --scene=terrain --water  # a flyover: noise terrain, water, sky, sun, fog
jen glsl:sdf --dim=3 --shapes=box,torus --ops=smooth-union --into=shaders/scene.frag.glsl
jen glsl:sdf --shapes=star --effects=fill,stroke,glow --into=shaders/logo.frag.glsl
jen glsl:sdf --dim=3 --shapes=all --name=Shapes    # preview: every shape side by side
  • Shapes (--shapes, previewed in the order given): 2D circle, box, round-box, segment, polygon, star, vesica, arch (a pointed arch); 3D sphere, box, round-box, torus, capsule, cylinder, plane. Named sdCircle, sdBox, … with overloads for 2D and 3D.
  • Operators (--ops): union, subtract, intersect and their smooth- variants, round, onion, repeat, repeat-limited, and extrude/revolve to turn 2D shapes into 3D ones.
  • 2D effects (--effects): antialiased fill and stroke, glow, drop shadow, inner-shadow – masks in [0, 1] from a distance.
  • Raymarching helpers (glsl:raymarch --into, pick with --parts): raymarch, calcNormal, softShadow, calcAO, cameraMatrix. They call your float scene(vec3 p), which they declare up front, so it can live anywhere in the shader. For materials, keep that function returning the distance and look the material up once at the hit point, as the --materials starter does: vec2 sceneMaterial(vec3 p) returns distance and id, scene() returns its .x.

Each list also takes all. The formulas follow Inigo Quilez's articles on distance functions, 2D distance functions, ray intersectors, smooth minimum, SDF normals and soft shadows, credited in each function – his snippets are MIT, and jen puts their notice next to your shader.

Lighting

jen glsl:lighting --models=pbr --tonemap=aces,srgb --into=shaders/scene.frag.glsl
jen glsl:lighting --models=toon --into=shaders/scene.frag.glsl
  • Models (--models): lambert(n, l, albedo), blinnPhong(n, v, l, albedo, shininess, specular), toon(n, v, l, albedo, bands) with a rim light, and pbr(n, v, l, albedo, metallic, roughness) – Cook-Torrance with GGX, Smith-Schlick and Schlick Fresnel, plus pbrAmbient(), a sky/ground ambient light that needs no environment map.
  • Environments (--env=sky|equirect|cube): envSky, envEquirect (a panorama in texture0) or envCube (cubemap0), each (…, dir, roughness), and pbrEnv() to light and reflect with them; glsl:raymarch --lighting=pbr --env=… writes a starter with it.
  • Color output (--tonemap): tonemapAces() (Stephen Hill's ACES fit), tonemapReinhard(), and linearToSrgb()/srgbToLinear() with the exact sRGB curve.

Every model takes the normal n, the direction to the viewer v and to the light l, and returns the reflected light for a white light of intensity 1: multiply by the light's color and shadow, sum over lights, tonemap, encode. jen glsl:raymarch --name=Scene --lighting=pbr shows a model in a full scene.

Filters

jen glsl:filter --name=Retro --kinds=crt,vignette
jen glsl:webgl --name=Retro --inline --shader=retro.frag.glsl --texture=test-pattern
  • Kinds (--kinds): grayscale, sepia, posterize, dither (Bayer), vignette, grain, chromatic, pixelate, sobel (edges), blur-box, blur-gaussian, sharpen, kuwahara (painterly) and crt after Timothy Lottes' public-domain CRT shader.
  • Input: texture0 on <shader-canvas> – an image or a video (both need a web server), camera, or test-pattern.
  • Post passes (--post): filter a whole scene – the starter reads uPrevious, and jen glsl:webgl --shader=scene.frag.glsl --post=retro.frag.glsl chains them.

Vertex displacement and matrices

jen glsl:displace --kind=noise --name=Blob    # shaders/blob.vert.glsl + blob.frag.glsl
jen glsl:displace --kind=waves --name=Sea     # Gerstner waves with exact normals
jen glsl:matrix --fns=rotate,look-at --into=shaders/mesh.vert.glsl
  • Displacement (glsl:displace): displace(position, normal) pushes a vertex along its normal by your float displacement(vec3 p) and recomputes the normal from two displaced neighbours, so lighting follows the new shape. --kind=noise drives it with 3D simplex noise, --kind=wobble with sines; --kind=waves sums gerstnerWave()s, whose normals are exact.

  • Previews (--name): a vertex/fragment pair using the attributes and uniforms of <shader-canvas>:

    <shader-canvas mesh="sphere" detail="96" vert="shaders/blob.vert.glsl" src="shaders/blob.frag.glsl" orbit></shader-canvas>
    

    For waves, use mesh="plane" detail="128".

  • Matrices (glsl:matrix): rotateX/Y/Z, rotateAxis, perspective, lookAt, translate, scale and transform (mat3 → mat4), following OpenGL conventions.

How functions get into your shader

GLSL has no #include, so functions ship as plain .glsl files under glsl/. With --into=<shader> (a .glsl file, or the page glsl:webgl --inline made), jen inserts the ones you pick – plus whatever they depend on – above a // jen:functions marker line. If your shader has none yet, the marker is added before its first function, so the inserted functions come before your own code that calls them (a raymarched scene(), say). Later runs add below what's already there. Anything already in the file is skipped, so running a generator twice, or two generators sharing a helper, never duplicates code. Without --into, each function is written as its own file under lib/ where the files go (--dir) for setups with an include mechanism (vite-plugin-glsl, glslify, three.js, …).

Inserted code is matched by its exact text: if you edit an inserted function and run a generator needing it again, it gets inserted a second time.

The pack needs jen 2 or newer; npm warns if your jen is older.

Where files go

The generators write into the current directory; --dir=<path> writes somewhere else. --into and --file are relative to the current directory too.

glsl:webgl creates a new project folder in the current directory (--dir names it), and --shaderDir names the shader subfolder inside it.

Licenses

The pack's own code – starters and functions – is MIT No Attribution (MIT-0): do whatever you want with it, no notice required. (Not the Unlicense or CC0: German copyright law can't release code into the public domain, but it can grant every right unconditionally.)

Functions by other authors are included only under the MIT license, which does require their notice, or released into the public domain: when jen inserts such a function, the author's full notice (or a line saying none is required) goes into a THIRD_PARTY_NOTICES.md next to your shader, once per source. See THIRD_PARTY_NOTICES.md for all authors and sources.

License

MIT-0 © Lea Rosema; third-party functions MIT © their authors

版本与发布记录

@codejen/pack-glsl 共发布 15 个版本,首次发布于 2026/10/05;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.6.1latest2026/11/028 天前
2.5.02026/10/2615 天前
2.4.02026/10/2515 天前
2.3.22026/10/2515 天前
2.3.12026/10/2318 天前
2.3.02026/10/2021 天前

关于 @codejen/pack-glsl 的常见问题

@codejen/pack-glsl 是什么?

jen pack for GLSL: shader starters, SDF/raymarching, noise and lighting snippets (MIT-licensed, attributed)

如何安装 @codejen/pack-glsl?

在项目目录运行 npm install @codejen/pack-glsl,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@codejen/jen(^3.2.0 || ^4.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@codejen/pack-glsl 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@codejen/pack-glsl 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@codejen/pack-glsl 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@codejen/pack-glsl 可以商用吗?

@codejen/pack-glsl 使用 MIT-0 AND MIT 许可。声明的许可为 MIT-0 AND MIT,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@codejen/pack-glsl 的下载量有多少?

根据 npm 官方下载统计,@codejen/pack-glsl 在 2026/10/10 – 2026/11/08 这 30 天内被下载 1,850 次,日均约 62 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@codejen/pack-glsl 还在维护吗?

最新版本 2.6.1 发布于 2026/11/02(8 天前);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/10/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。