Open source from Noise Factor · more projects
⚠️ Note: The Portable Effects specification is still being finalized and may change.
The Portable Effects Format is an open standard for sharing shader effects across the Noise Factor ecosystem.
This repository serves as the canonical source of truth for the Portable Effects specification.
Portable Effects are self-contained shader packages that work across all Noise Factor applications.
The easiest way to create effects is with Foundry, a web-based shader editor with live preview. You can also work directly with the files in this repository. Effects you create can be imported into Noisedeck or other Noise Factor applications.
portable/
├── effect/ # Working example effect
│ ├── definition.json # Effect definition
│ ├── help.md # Effect documentation
│ ├── glsl/
│ │ └── gradientSweep.glsl # WebGL shader
│ └── wgsl/
│ └── gradientSweep.wgsl # WebGPU shader
├── viewer/ # Effect viewer
│ └── index.html # Full-page viewer with param controls
├── docs/ # Format specification
├── package.json # Dev server and packaging scripts
├── package-portable.sh # Bash packaging script
└── package-portable.mjs # Node.js packaging script
git clone https://github.com/noisefactorllc/portable.git
cd portableModify files in the effect/ directory:
definition.json- Effect definition and parametersglsl/*.glsl- WebGL shader codewgsl/*.wgsl- WebGPU shader codehelp.md- Effect documentation
The viewer needs a local HTTP server. From the project root:
npm install
npm run devOpen http://localhost:2999/viewer/. After you change effect files, click Reload Effect in the viewer or refresh the page.
Create a ZIP archive for sharing or importing into applications:
# Using bash
./package-portable.sh
# Or using Node.js
npm run packageThis creates effect.zip.
To use your effect in Noisedeck or other Noise Factor applications:
- Open the application
- In the menu bar, select file → import effect from zip...
- Select your
effect.zipfile - The effect's DSL program will load automatically
The included effect/ directory contains a complete portable effect. It draws a diagonal color gradient that rotates smoothly over time. The time uniform controls its seamless loop.
effect/definition.json:
{
"name": "Gradient Sweep",
"func": "gradientSweep",
"description": "A diagonal color gradient that rotates over time",
"tags": ["color"],
"starter": true,
"globals": {
"speed": {
"type": "float",
"default": 1.0,
"min": 0.0,
"max": 4.0,
"step": 0.1,
"uniform": "speed"
}
},
"defaultProgram": "search user\n\ngradientSweep(speed: 1.0)\n .write(o0)\n\nrender(o0)",
"passes": [
{
"name": "main",
"program": "gradientSweep",
"inputs": {},
"outputs": {
"color": "outputTex"
}
}
]
}effect/glsl/gradientSweep.glsl:
#version 300 es
precision highp float;
uniform vec2 resolution;
uniform float time;
uniform float speed;
out vec4 fragColor;
#define TAU 6.28318530718
void main() {
vec2 uv = gl_FragCoord.xy / resolution;
// Rotate the gradient direction over time
// time loops 0→1, so multiply by TAU for a full rotation per loop
float angle = time * TAU * speed;
vec2 dir = vec2(cos(angle), sin(angle));
// Project UV onto the rotating direction
float t = dot(uv - 0.5, dir) + 0.5;
// Map to a smooth color gradient
vec3 color = vec3(t, t * 0.6 + 0.2, 1.0 - t);
fragColor = vec4(color, 1.0);
}A portable effect needs only two files:
my-effect/
├── definition.json # Effect metadata and parameters
└── glsl/ # At least one shader directory required
└── main.glsl # Fragment shader source
For full interoperability, provide both GLSL and WGSL shaders and a help.md documentation file:
my-effect/
├── definition.json # Effect metadata and parameters
├── help.md # Effect documentation
├── glsl/
│ └── main.glsl # WebGL shader
└── wgsl/
└── main.wgsl # WebGPU shader
{
"name": "My Effect",
"func": "myEffect",
"description": "A simple shader effect",
"starter": true,
"tags": ["noise"],
"globals": {
"scale": {
"type": "float",
"default": 1.0,
"min": 0.1,
"max": 10.0
}
},
"passes": [
{
"name": "render",
"program": "main",
"inputs": {},
"outputs": { "color": "outputTex" }
}
]
}#version 300 es
precision highp float;
uniform vec2 resolution;
uniform float time;
uniform float scale;
out vec4 fragColor;
void main() {
vec2 uv = gl_FragCoord.xy / resolution * scale;
vec3 color = vec3(uv, sin(time) * 0.5 + 0.5);
fragColor = vec4(color, 1.0);
}Once loaded into Noisedeck or another application, use it in DSL programs:
search user
myEffect(scale: 2.0).write(o0)
render(o0)
| Document | Description |
|---|---|
| FORMAT.md | Complete specification of the effect format |
| PARAMETERS.md | Defining uniforms and UI controls |
| SHADERS.md | Writing GLSL and WGSL shaders |
| DSL.md | Using effects in the Polymorphic DSL |
| VIEWER.md | Using the effect viewer |
Portable effects are registered in the user namespace. Version 1.1 supports
2D effects and Noisemaker's volume/geometry pipeline:
| Type | starter |
Description |
|---|---|---|
| Starter | true |
Generates 2D imagery from scratch (called "synth" in Noisedeck) |
| Filter | false |
Transforms a 2D input texture |
| 3D starter | true |
Produces a volume atlas and optional geometry atlas |
| 3D filter | false |
Processes an upstream volume, preserving or replacing its geometry |
| Volume renderer | false |
Renders an upstream volume into color and screen-space geometry |
See the 3D contract for atlas
addressing, texture sizes, geometry outputs, and consumer requirements. The
working Portable Block 3D example renders through
Noisemaker's built-in voxel renderer on WebGL2 and WebGPU. Start the dev server
and open viewer/?effect=../examples/portableBlock3d/.
The Volume Color 3D example demonstrates an existing
shape3d() chain passing through a Portable filter and into render3d().
It preserves density and geometry while changing voxel colors.
npm test includes browser checks for both examples, volume-size inheritance,
geometry passthrough, and exact displayed-pixel agreement for the block.
The 3D checks require WebGL2 and WebGPU support and network access to the
Noisemaker shader CDN. On macOS and Windows they use installed Google Chrome.
Linux CI uses Playwright Chromium with SwiftShader under Xvfb; run
npx playwright install --with-deps chromium and xvfb-run -a npm test there.
Existing 2D packages are unchanged. Older app versions that discard volume or geometry metadata need updated importers before they can use 3D packages.
The following built-in effect types are not part of this volume extension:
| Type | Namespace | Description |
|---|---|---|
| Mixer | mixer |
Blends two input textures |
| Points | points |
Agent/particle simulations |
| Other render utilities | render |
Loops, meshes, and particle renderers |
This specification is released under the MIT License.
Effects you create are your own. Share them however you like.
