Import, inline (and compress) GLSL shader files
Inspired by threejs-glsl-loader and vite-plugin-string, compatible with three.js and lygia.
npm i vite-plugin-glsl --save-dev
# or
yarn add vite-plugin-glsl --dev
# or
pnpm add -D vite-plugin-glsl
// vite.config.js
import glsl from 'vite-plugin-glsl';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [glsl()]
});
glsl({
include: [ // Glob pattern, or array of glob patterns to import
'**/*.glsl', '**/*.wgsl',
'**/*.vert', '**/*.frag',
'**/*.vs', '**/*.fs'
],
exclude: undefined, // Glob pattern, or array of glob patterns to ignore
warnDuplicatedImports: true, // Warn if the same chunk was imported multiple times
defaultExtension: 'glsl', // Shader suffix when no extension is specified
compress: false, // Compress output shader code
watch: true, // Recompile shader on change
root: '/' // Directory for root imports
})
root
├── src/
│ ├── glsl/
│ │ ├── chunk0.frag
│ │ ├── chunk3.frag
│ │ ├── main.frag
│ │ ├── main.vert
│ │ └── utils/
│ │ ├── chunk1.glsl
│ │ └── chunk2.frag
│ └── main.js
├── vite.config.js
└── package.json
// main.js
import fragment from './glsl/main.frag';
// main.frag
precision highp float;
#include chunk0.frag;
out highp vec4 fragColor;
void main (void) {
fragColor = chunkFn();
}
// chunk0.frag
// ".glsl" extension will be set automatically:
#include utils/chunk1;
highp vec4 chunkFn () {
return vec4(chunkRGB(), 1.0);
}
// utils/chunk1.glsl
#include chunk2.frag;
#include ../chunk3.frag;
highp vec3 chunkRGB () {
return vec3(chunkRed(), chunkGreen(), 0.0);
}
// utils/chunk2.frag
highp float chunkRed () {
return 0.0;
}
// chunk3.frag
highp float chunkGreen () {
return 0.8;
}
Will result in:
// main.frag
precision highp float;
highp float chunkRed () {
return 0.0;
}
highp float chunkGreen () {
return 0.8;
}
highp vec3 chunkRGB () {
return vec3(chunkRed(), chunkGreen(), 0.0);
}
highp vec4 chunkFn () {
return vec4(chunkRGB(), 1.0);
}
out highp vec4 fragColor;
void main (void) {
fragColor = chunkFn();
}
-
Starting from
v0.0.7
this plugin supports optional single and double quotation marks around file names. -
Starting from
v0.0.9
this plugin supports optional semicolons at the end of#include
statements. -
Starting from
v0.1.0
this plugin supports WebGPU shaders with.wgsl
extension. -
Starting from
v0.1.2
this plugin generates sourcemaps using vite esbuild when thesourcemap
option is set totrue
. -
Starting from
v0.1.5
this plugin warns about duplicated chunks imports and throws an error when a recursive loop occurres. -
Starting from
v0.2.0
this plugin uses a config object as a single argument toglsl
function and allows to disable import warnings with thewarnDuplicatedImports
param set tofalse
. -
Starting from
v0.2.2
this plugin supportscompress
option to optimize output shader length. You might consider setting this totrue
in production environment. -
Starting from
v0.3.0
this plugin is pure ESM. Consider updating your project to an ESM module by adding"type": "module"
in yourpackage.json
or consult this issue for possible workarounds. -
Starting from
v0.4.0
this plugin supports chunk imports from project root androot
option to override the default root directory. -
Starting from
v0.5.0
this plugin supports shaders hot reloading whenwatch
option is set totrue
. -
Starting from
v0.5.4
this plugin supports customcompress
callback function to optimize output shader length after all shader chunks have been included. -
Starting from
v1.0.0
this plugin is fully compatible withvite^4.0.0
. -
Starting from
v1.1.1
this plugin has a complete TypeScript support. You can add module declarations for shader files by using:/// <reference types="vite-plugin-glsl/ext" />
.
When used with three.js r0.99 and higher, it's possible to include shader chunks as specified in the documentation, those imports will be ignored by vite-plugin-glsl
since they are handled internally by the library itself:
precision highp float;
#include <common>
vec3 randVec3 (const in vec2 uv) {
return vec3(
rand(uv * 0.1), rand(uv * 2.5), rand(uv)
);
}