@clypra/shader-library 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.releaserc.json +16 -0
- package/package.json +45 -0
- package/src/index.ts +18 -0
- package/src/noise/index.ts +167 -0
- package/src/utils/index.ts +109 -0
- package/tsconfig.json +21 -0
- package/tsup.config.ts +15 -0
package/.releaserc.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"branches": ["main"],
|
|
3
|
+
"plugins": [
|
|
4
|
+
"@semantic-release/commit-analyzer",
|
|
5
|
+
"@semantic-release/release-notes-generator",
|
|
6
|
+
"@semantic-release/npm",
|
|
7
|
+
[
|
|
8
|
+
"@semantic-release/git",
|
|
9
|
+
{
|
|
10
|
+
"assets": ["package.json"],
|
|
11
|
+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"@semantic-release/github"
|
|
15
|
+
]
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clypra/shader-library",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Reusable GLSL shader library for video effects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/index.js",
|
|
10
|
+
"./color": "./dist/color/index.js",
|
|
11
|
+
"./blur": "./dist/blur/index.js",
|
|
12
|
+
"./distortion": "./dist/distortion/index.js",
|
|
13
|
+
"./composite": "./dist/composite/index.js",
|
|
14
|
+
"./noise": "./dist/noise/index.js",
|
|
15
|
+
"./utils": "./dist/utils/index.js"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"dev": "tsup --watch",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"clean": "rm -rf dist",
|
|
23
|
+
"lint": "tsc --noEmit"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^22.14.0",
|
|
28
|
+
"tsup": "^8.3.5",
|
|
29
|
+
"typescript": "~5.8.2",
|
|
30
|
+
"vitest": "^3.2.4"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/AIEraDev/clypra-studio.git",
|
|
35
|
+
"directory": "packages/shader-library"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/AIEraDev/clypra-studio/tree/main/packages/shader-library#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/AIEraDev/clypra-studio/issues"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public",
|
|
43
|
+
"registry": "https://registry.npmjs.org/"
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clypra/shader-library
|
|
3
|
+
*
|
|
4
|
+
* Reusable GLSL shader library for video effects.
|
|
5
|
+
* All shaders are organized by category for easy reuse across effects.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Utilities
|
|
9
|
+
export * from "./utils";
|
|
10
|
+
|
|
11
|
+
// Noise functions
|
|
12
|
+
export * from "./noise";
|
|
13
|
+
|
|
14
|
+
// Note: Other shader categories will be added in subsequent phases
|
|
15
|
+
// export * from './color';
|
|
16
|
+
// export * from './blur';
|
|
17
|
+
// export * from './distortion';
|
|
18
|
+
// export * from './composite';
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clypra/shader-library — Noise Shaders
|
|
3
|
+
*
|
|
4
|
+
* Various noise generation functions for procedural effects
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Film grain shader
|
|
9
|
+
*/
|
|
10
|
+
export const filmGrainShader = `
|
|
11
|
+
uniform sampler2D uTexture;
|
|
12
|
+
uniform float uIntensity;
|
|
13
|
+
uniform float uSize;
|
|
14
|
+
uniform float uTime;
|
|
15
|
+
|
|
16
|
+
float filmGrain(vec2 uv, float time) {
|
|
17
|
+
vec2 p = uv * uSize;
|
|
18
|
+
p += time * 1000.0;
|
|
19
|
+
|
|
20
|
+
float n = hash(p);
|
|
21
|
+
n = n * 2.0 - 1.0;
|
|
22
|
+
|
|
23
|
+
return n * uIntensity;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void main() {
|
|
27
|
+
vec2 uv = vTextureCoord;
|
|
28
|
+
vec4 color = texture2D(uTexture, uv);
|
|
29
|
+
|
|
30
|
+
float grain = filmGrain(uv, uTime);
|
|
31
|
+
color.rgb += grain;
|
|
32
|
+
|
|
33
|
+
gl_FragColor = color;
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Perlin noise shader
|
|
39
|
+
*/
|
|
40
|
+
export const perlinNoiseShader = `
|
|
41
|
+
vec2 fade(vec2 t) {
|
|
42
|
+
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
float perlinNoise(vec2 p) {
|
|
46
|
+
vec2 i = floor(p);
|
|
47
|
+
vec2 f = fract(p);
|
|
48
|
+
|
|
49
|
+
vec2 u = fade(f);
|
|
50
|
+
|
|
51
|
+
float a = hash(i);
|
|
52
|
+
float b = hash(i + vec2(1.0, 0.0));
|
|
53
|
+
float c = hash(i + vec2(0.0, 1.0));
|
|
54
|
+
float d = hash(i + vec2(1.0, 1.0));
|
|
55
|
+
|
|
56
|
+
return mix(
|
|
57
|
+
mix(a, b, u.x),
|
|
58
|
+
mix(c, d, u.x),
|
|
59
|
+
u.y
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
float fbm(vec2 p) {
|
|
64
|
+
float value = 0.0;
|
|
65
|
+
float amplitude = 0.5;
|
|
66
|
+
float frequency = 1.0;
|
|
67
|
+
|
|
68
|
+
for (int i = 0; i < 5; i++) {
|
|
69
|
+
value += amplitude * perlinNoise(p * frequency);
|
|
70
|
+
amplitude *= 0.5;
|
|
71
|
+
frequency *= 2.0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Simplex noise (approximation)
|
|
80
|
+
*/
|
|
81
|
+
export const simplexNoiseShader = `
|
|
82
|
+
vec3 mod289(vec3 x) {
|
|
83
|
+
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
vec2 mod289(vec2 x) {
|
|
87
|
+
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
vec3 permute(vec3 x) {
|
|
91
|
+
return mod289(((x * 34.0) + 1.0) * x);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
float simplexNoise(vec2 v) {
|
|
95
|
+
const vec4 C = vec4(
|
|
96
|
+
0.211324865405187, // (3.0-sqrt(3.0))/6.0
|
|
97
|
+
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
|
|
98
|
+
-0.577350269189626, // -1.0 + 2.0 * C.x
|
|
99
|
+
0.024390243902439 // 1.0 / 41.0
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
vec2 i = floor(v + dot(v, C.yy));
|
|
103
|
+
vec2 x0 = v - i + dot(i, C.xx);
|
|
104
|
+
|
|
105
|
+
vec2 i1;
|
|
106
|
+
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
|
107
|
+
vec4 x12 = x0.xyxy + C.xxzz;
|
|
108
|
+
x12.xy -= i1;
|
|
109
|
+
|
|
110
|
+
i = mod289(i);
|
|
111
|
+
vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0))
|
|
112
|
+
+ i.x + vec3(0.0, i1.x, 1.0));
|
|
113
|
+
|
|
114
|
+
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
|
|
115
|
+
m = m * m;
|
|
116
|
+
m = m * m;
|
|
117
|
+
|
|
118
|
+
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
|
119
|
+
vec3 h = abs(x) - 0.5;
|
|
120
|
+
vec3 ox = floor(x + 0.5);
|
|
121
|
+
vec3 a0 = x - ox;
|
|
122
|
+
|
|
123
|
+
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
|
|
124
|
+
|
|
125
|
+
vec3 g;
|
|
126
|
+
g.x = a0.x * x0.x + h.x * x0.y;
|
|
127
|
+
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
|
128
|
+
return 130.0 * dot(m, g);
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Cellular/Worley noise
|
|
134
|
+
*/
|
|
135
|
+
export const cellularNoiseShader = `
|
|
136
|
+
vec2 random2(vec2 p) {
|
|
137
|
+
return fract(sin(vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)))) * 43758.5453);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
float cellularNoise(vec2 p) {
|
|
141
|
+
vec2 i_p = floor(p);
|
|
142
|
+
vec2 f_p = fract(p);
|
|
143
|
+
|
|
144
|
+
float minDist = 1.0;
|
|
145
|
+
|
|
146
|
+
for (int y = -1; y <= 1; y++) {
|
|
147
|
+
for (int x = -1; x <= 1; x++) {
|
|
148
|
+
vec2 neighbor = vec2(float(x), float(y));
|
|
149
|
+
vec2 point = random2(i_p + neighbor);
|
|
150
|
+
|
|
151
|
+
vec2 diff = neighbor + point - f_p;
|
|
152
|
+
float dist = length(diff);
|
|
153
|
+
|
|
154
|
+
minDist = min(minDist, dist);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return minDist;
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
export const noiseShaders = {
|
|
163
|
+
filmGrain: filmGrainShader,
|
|
164
|
+
perlin: perlinNoiseShader,
|
|
165
|
+
simplex: simplexNoiseShader,
|
|
166
|
+
cellular: cellularNoiseShader,
|
|
167
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clypra/shader-library — GLSL Utility Functions
|
|
3
|
+
*
|
|
4
|
+
* Common utility functions used across shaders
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Common GLSL utility functions as a string
|
|
9
|
+
*/
|
|
10
|
+
export const glslUtils = `
|
|
11
|
+
// Hash function for random number generation
|
|
12
|
+
float hash(vec2 p) {
|
|
13
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 2D noise function
|
|
17
|
+
float noise(vec2 p) {
|
|
18
|
+
vec2 i = floor(p);
|
|
19
|
+
vec2 f = fract(p);
|
|
20
|
+
|
|
21
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
22
|
+
|
|
23
|
+
float a = hash(i);
|
|
24
|
+
float b = hash(i + vec2(1.0, 0.0));
|
|
25
|
+
float c = hash(i + vec2(0.0, 1.0));
|
|
26
|
+
float d = hash(i + vec2(1.0, 1.0));
|
|
27
|
+
|
|
28
|
+
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Smooth minimum
|
|
32
|
+
float smin(float a, float b, float k) {
|
|
33
|
+
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
|
|
34
|
+
return mix(b, a, h) - k * h * (1.0 - h);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Smooth step with adjustable edge
|
|
38
|
+
float smootherstep(float edge0, float edge1, float x) {
|
|
39
|
+
x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
|
|
40
|
+
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Luminance calculation
|
|
44
|
+
float luminance(vec3 color) {
|
|
45
|
+
return dot(color, vec3(0.299, 0.587, 0.114));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// RGB to HSV
|
|
49
|
+
vec3 rgb2hsv(vec3 c) {
|
|
50
|
+
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
|
51
|
+
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
|
52
|
+
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
|
53
|
+
|
|
54
|
+
float d = q.x - min(q.w, q.y);
|
|
55
|
+
float e = 1.0e-10;
|
|
56
|
+
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// HSV to RGB
|
|
60
|
+
vec3 hsv2rgb(vec3 c) {
|
|
61
|
+
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
62
|
+
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
63
|
+
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Vignette effect
|
|
67
|
+
float vignette(vec2 uv, float intensity, float extent) {
|
|
68
|
+
vec2 center = uv * 2.0 - 1.0;
|
|
69
|
+
float dist = length(center);
|
|
70
|
+
return 1.0 - smoothstep(extent, extent + intensity, dist);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Posterize
|
|
74
|
+
vec3 posterize(vec3 color, float levels) {
|
|
75
|
+
return floor(color * levels) / levels;
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create a complete fragment shader with utilities
|
|
81
|
+
*/
|
|
82
|
+
export function createFragmentShader(mainCode: string): string {
|
|
83
|
+
return `
|
|
84
|
+
precision highp float;
|
|
85
|
+
|
|
86
|
+
varying vec2 vTextureCoord;
|
|
87
|
+
|
|
88
|
+
${glslUtils}
|
|
89
|
+
|
|
90
|
+
${mainCode}
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Standard vertex shader
|
|
96
|
+
*/
|
|
97
|
+
export const standardVertexShader = `
|
|
98
|
+
attribute vec2 aVertexPosition;
|
|
99
|
+
attribute vec2 aTextureCoord;
|
|
100
|
+
|
|
101
|
+
uniform mat3 projectionMatrix;
|
|
102
|
+
|
|
103
|
+
varying vec2 vTextureCoord;
|
|
104
|
+
|
|
105
|
+
void main() {
|
|
106
|
+
gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
|
|
107
|
+
vTextureCoord = aTextureCoord;
|
|
108
|
+
}
|
|
109
|
+
`;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"resolveJsonModule": true,
|
|
8
|
+
"allowJs": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"declarationMap": true,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"outDir": "./dist",
|
|
17
|
+
"rootDir": "./src"
|
|
18
|
+
},
|
|
19
|
+
"include": ["src/**/*"],
|
|
20
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
21
|
+
}
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineConfig } from "tsup";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
entry: {
|
|
5
|
+
index: "src/index.ts",
|
|
6
|
+
"utils/index": "src/utils/index.ts",
|
|
7
|
+
"noise/index": "src/noise/index.ts",
|
|
8
|
+
},
|
|
9
|
+
format: ["esm"],
|
|
10
|
+
dts: true,
|
|
11
|
+
sourcemap: true,
|
|
12
|
+
clean: true,
|
|
13
|
+
splitting: false,
|
|
14
|
+
treeshake: true,
|
|
15
|
+
});
|