Preview GLSL shaders on Obsidian.

Same syntax as Shadertoy - easily port your creations and reuse code snippets between platforms

Load images from your vault as textures (iChannel0-3)

Use templates to simplify complex shaders - write minimal code, get maximum results
Use standard glsl code blocks with @viewer directive:
Single-line comments:
```glsl
// @viewer
// @aspect: 0.75
// @autoplay: true
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 col = 0.5 + 0.5 * cos(iTime + uv.xxy + vec3(0, 2, 4));
fragColor = vec4(col, 1.0);
}
```
Multi-line comments:
```glsl
/*
@viewer
@aspect: 0.75
@autoplay: true
@hideCode: true
@iChannel0: assets/texture.png
*/
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 col = 0.5 + 0.5 * cos(iTime + uv.xxy + vec3(0, 2, 4));
fragColor = vec4(col, 1.0);
}
```
```glsl
// @viewer
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 col = 0.5 + 0.5 * cos(iTime + uv.xxy + vec3(0, 2, 4));
fragColor = vec4(col, 1.0);
}
```
```glsl
// @viewer
// @aspect: 1.0
// @autoplay: true
// @iChannel0: assets/images/texture.jpg
// @hideCode: true
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord-iResolution.xy*.5) / iResolution.y;
uv+=vec2(sin(iTime),cos(iTime));
vec3 texColor = texture(iChannel0, uv * 2.0).rgb;
vec3 col = texColor;
fragColor = vec4(col, 1.0);
}
```
Templates enable the creation of complex shader patterns with minimal code.
Create custom templates in your configured templates folder (default: GLSL Templates/).
Share complex setups across multiple shaders.
```glsl
// @viewer
// @template: raymarching.glsl
vec4 map(vec3 p) {
float d = length(p) - .5; // Sphere distance function
return vec4(d, COL_S2); // Return distance and material color
}
```
Three ways to specify textures:
tex1 (configured in settings)wood.png (when Texture Folder is set)images/wood.png (relative to vault root)Create shortcuts for frequently used textures in plugin settings.
Shortcuts are always relative to your Texture Folder setting:
```glsl
// @viewer
// @iChannel0: tex1 // Uses shortcut 'tex1' → {TextureFolder}/wood.png
// @iChannel1: noise // Uses shortcut 'noise' → {TextureFolder}/noise.jpg
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec3 tex = texture(iChannel0, uv).rgb; // wood texture
vec3 n = texture(iChannel1, uv).rgb; // noise texture
fragColor = vec4(mix(tex, n, 0.5), 1.0);
}
```
Configure shortcuts in Settings → GLSL Viewer → Texture Shortcuts
| Setting | Description | Default |
|---|---|---|
@viewer |
Enable viewer for glsl code blocks |
- |
@aspect: number |
Canvas aspect ratio (height/width) | 0.5625 |
@autoplay: true/false |
Auto-start animation | false |
@hideCode: true/false |
Hide code block, show viewer only | false |
@template: filename |
Use template from templates folder | - |
Note: @viewer directive is required only for glsl code blocks. glsl-viewer blocks are always processed.
vec3 iResolution - Screen resolution ✅float iTime - Elapsed time ✅float iTimeDelta - Frame delta time ✅int iFrame - Frame number ✅vec4 iMouse - Mouse position (Shadertoy-compatible) ✅vec4 iDate - Date info (year, month, day, seconds) ✅sampler2D iChannel0-3 - Textures ✅vec3 iChannelResolution[4] - Texture resolutions (width, height, 1.0) ✅mainImage(out vec4 fragColor, in vec2 fragCoord)@TEMPLATE_LINES placeholder replacementAccess via Settings → Community plugins → GLSL Viewer:
Display Settings:
Folders: (in setup priority order)
GLSL Thumbnails)GLSL Templates)Texture Shortcuts:
tex1, noise).glsl file in your Templates Folder (default: GLSL Templates/)@TEMPLATE_LINES where your code should be inserted// @template: filename.glsl
npm install
npm run dev # Development mode
npm run build # Production build
MIT License