junkpile

04 · Tauri v1 External GLSL Single Window

A focused raw-WebGL example where the fragment shader is stored as a real external project file and can be replaced at runtime without rebuilding the Tauri application.

This folder intentionally retains its original repository name:

glsl-tauri-v1-single-template

The visible example number is 04 so it aligns with the complete Junkpile Tauri v1 Essentials sequence.

What this example teaches

Signal flow

src/shader.frag or local .frag/.glsl file
                    ↓
             fetch() / FileReader
                    ↓
       WebGL compile + program link
                    ↓
HTML controls → params → uniforms
                    ↓
             gl.drawArrays()
                    ↓
        WebGL canvas in one WebView

There is no WebSocket, second window, p5.js renderer, or native GPU surface.

Run

npm install
npm run dev

Production build

npm run build

On macOS, generated bundles are placed under:

src-tauri/target/release/bundle/

Unsigned applications can trigger Gatekeeper on another Mac. Public distribution generally requires Apple signing and notarization.

External shader workflow

The default fragment shader is:

src/shader.frag

At startup, src/sketch.js requests that file with fetch() and compiles it. You can then:

If a replacement fails, the diagnostics panel reports the compiler output and the previous valid shader continues rendering.

Shader contract

A replacement fragment shader must target GLSL ES 1.00 / WebGL 1 and should include:

precision highp float;
varying vec2 vTexCoord;

void main() {
    gl_FragColor = vec4(vTexCoord, 0.0, 1.0);
}

The renderer supplies these uniforms:

uniform float u_time;
uniform vec2  u_resolution;
uniform float u_hue;
uniform float u_saturation;
uniform float u_brightness;
uniform float u_zoom;
uniform float u_distortion;
uniform float u_rotate;
uniform float u_complexity;
uniform float u_symmetry;
uniform float u_glow;
uniform float u_invert;
uniform float u_pulse;

A shader does not need to use every uniform. WebGL optimizes unused uniforms away, and the renderer safely skips missing locations.

Common compatibility problems

The diagnostics panel recognizes several common reasons an imported shader may fail:

The dedicated shader-playground examples later add full source editing and richer line navigation.

Controls

Section Parameter Purpose
Color Hue shift Rotates the default shader palette
Color Saturation Moves from monochrome to vivid color
Color Brightness Multiplies final output brightness
Motion Zoom Scales shader coordinates
Motion Speed Advances the accumulated animation clock
Motion Distortion Strengthens domain warping
Pattern Complexity Changes the default fBm octave count
Pattern Symmetry Changes rotational folding
Pattern Glow Brightens the center of the field
Switches Invert Inverts the default shader output
Switches Pulse Enables rhythmic brightness modulation
Switches Rotate Rotates the complete coordinate field

Loaded shaders can ignore or reinterpret these values.

Keyboard shortcuts:

Key Action
Space Pause or resume animation
R Restore uniform defaults and reset time
C Recompile the loaded shader source
O Open the shader-file picker
F Toggle native-window fullscreen

Project structure

glsl-tauri-v1-single-template/
├── README.md
├── MODERNIZATION-NOTES.md
├── package.json
├── src/
│   ├── index.html
│   ├── shader.frag
│   ├── sketch.js
│   └── styles.css
└── src-tauri/
    ├── Cargo.toml
    ├── tauri.conf.json
    └── src/main.rs

Why this remains a separate example

Example 02 embeds its fragment source directly in JavaScript. Example 04 establishes the external-asset workflow used by larger shader projects:

Known limitations