@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.
@@ -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
+ });