junkpile

05 · Tauri v1 External GLSL WebSocket

A two-window raw-WebGL example where the fragment shader is stored as an external project file, selected from the controls window, sent through an embedded Rust WebSocket relay, and compiled in a separate output WebView.

The repository folder remains:

glsl-tauri-v1-ws-template

The visible number is 05 in the Junkpile Tauri v1 Essentials sequence.

What this example teaches

Signal flow

src/shader.frag or local shader file
                  ↓
           Controls WebView
                  ↓ JSON source + uniforms
     ws://127.0.0.1:2727
                  ↓
          Embedded Rust relay
                  ↓
            Output WebView
                  ↓
       WebGL compile + link
                  ↓
             gl.drawArrays()

Run

npm install
npm run dev

Production build

npm run build

On macOS, bundles are written under:

src-tauri/target/release/bundle/

Public distribution usually requires Apple signing and notarization.

Shader workflow

The default shader is:

src/shader.frag

The controls window can:

A failed shader does not replace the active program. The output window displays the compiler error while the previous valid shader continues rendering.

Shader contract

Replacement source targets 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:

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;

Unused uniforms are safe; WebGL simply optimizes them away.

Common imported-shader problems

The controls terminal points out common mismatches:

State recovery

When the output reconnects it sends request_state. The controls respond with:

  1. the complete uniform snapshot;
  2. paused/running state;
  3. the current shader source and metadata.

This prevents an output reload from silently returning to stale controls or the wrong shader.

Keyboard shortcuts

Key Action
Space Pause/resume
R Reset uniforms and time
S Resend all state and shader source
O Open shader picker
C Recompile current shader
F Toggle output fullscreen

Project structure

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

Why this remains separate

Example 03 demonstrates two-window raw WebGL with an inline shader. Example 05 adds a transferable external-shader workflow: shader source can be edited, generated, exchanged, rejected safely, and re-synchronized independently of the application code.

Known limitations