pixospritz-core 0.10.1 → 1.0.1

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.
Files changed (157) hide show
  1. package/README.md +36 -286
  2. package/dist/bundle.js +13 -3
  3. package/dist/bundle.js.map +1 -1
  4. package/dist/style.css +1 -0
  5. package/package.json +43 -44
  6. package/src/components/WebGLView.jsx +318 -0
  7. package/src/css/pixos.css +372 -0
  8. package/src/engine/actions/animate.js +41 -0
  9. package/src/engine/actions/changezone.js +135 -0
  10. package/src/engine/actions/chat.js +109 -0
  11. package/src/engine/actions/dialogue.js +90 -0
  12. package/src/engine/actions/face.js +22 -0
  13. package/src/engine/actions/greeting.js +28 -0
  14. package/src/engine/actions/interact.js +86 -0
  15. package/src/engine/actions/move.js +67 -0
  16. package/src/engine/actions/patrol.js +109 -0
  17. package/src/engine/actions/prompt.js +185 -0
  18. package/src/engine/actions/script.js +42 -0
  19. package/src/engine/core/audio/AudioSystem.js +543 -0
  20. package/src/engine/core/cutscene/PxcPlayer.js +956 -0
  21. package/src/engine/core/cutscene/manager.js +243 -0
  22. package/src/engine/core/database/index.js +75 -0
  23. package/src/engine/core/debug/index.js +371 -0
  24. package/src/engine/core/hud/index.js +765 -0
  25. package/src/engine/core/index.js +540 -0
  26. package/src/engine/core/input/gamepad/Controller.js +71 -0
  27. package/src/engine/core/input/gamepad/ControllerButtons.js +231 -0
  28. package/src/engine/core/input/gamepad/ControllerStick.js +173 -0
  29. package/src/engine/core/input/gamepad/index.js +592 -0
  30. package/src/engine/core/input/keyboard.js +196 -0
  31. package/src/engine/core/input/manager.js +485 -0
  32. package/src/engine/core/input/mouse.js +203 -0
  33. package/src/engine/core/input/touch.js +175 -0
  34. package/src/engine/core/mode/manager.js +199 -0
  35. package/src/engine/core/net/manager.js +535 -0
  36. package/src/engine/core/queue/action.js +83 -0
  37. package/src/engine/core/queue/event.js +82 -0
  38. package/src/engine/core/queue/index.js +44 -0
  39. package/src/engine/core/queue/loadable.js +33 -0
  40. package/src/engine/core/render/CameraEffects.js +494 -0
  41. package/src/engine/core/render/FrustumCuller.js +417 -0
  42. package/src/engine/core/render/LODManager.js +285 -0
  43. package/src/engine/core/render/ParticleManager.js +529 -0
  44. package/src/engine/core/render/TextureAtlas.js +465 -0
  45. package/src/engine/core/render/camera.js +338 -0
  46. package/src/engine/core/render/light.js +197 -0
  47. package/src/engine/core/render/manager.js +1079 -0
  48. package/src/engine/core/render/shaders.js +110 -0
  49. package/src/engine/core/render/skybox.js +342 -0
  50. package/src/engine/core/resource/manager.js +133 -0
  51. package/src/engine/core/resource/object.js +611 -0
  52. package/src/engine/core/resource/texture.js +103 -0
  53. package/src/engine/core/resource/tileset.js +177 -0
  54. package/src/engine/core/scene/avatar.js +215 -0
  55. package/src/engine/core/scene/speech.js +138 -0
  56. package/src/engine/core/scene/sprite.js +702 -0
  57. package/src/engine/core/scene/spritz.js +189 -0
  58. package/src/engine/core/scene/world.js +681 -0
  59. package/src/engine/core/scene/zone.js +1167 -0
  60. package/src/engine/core/store/index.js +110 -0
  61. package/src/engine/dynamic/animatedSprite.js +64 -0
  62. package/src/engine/dynamic/animatedTile.js +98 -0
  63. package/src/engine/dynamic/avatar.js +110 -0
  64. package/src/engine/dynamic/map.js +174 -0
  65. package/src/engine/dynamic/sprite.js +255 -0
  66. package/src/engine/dynamic/spritz.js +119 -0
  67. package/src/engine/events/EventSystem.js +609 -0
  68. package/src/engine/events/camera.js +142 -0
  69. package/src/engine/events/chat.js +75 -0
  70. package/src/engine/events/menu.js +186 -0
  71. package/src/engine/scripting/CallbackManager.js +514 -0
  72. package/src/engine/scripting/PixoScriptInterpreter.js +81 -0
  73. package/src/engine/scripting/PixoScriptLibrary.js +704 -0
  74. package/src/engine/shaders/effects/index.js +450 -0
  75. package/src/engine/shaders/fs.js +222 -0
  76. package/src/engine/shaders/particles/fs.js +41 -0
  77. package/src/engine/shaders/particles/vs.js +61 -0
  78. package/src/engine/shaders/picker/fs.js +34 -0
  79. package/src/engine/shaders/picker/init.js +62 -0
  80. package/src/engine/shaders/picker/vs.js +42 -0
  81. package/src/engine/shaders/pxsl/README.md +250 -0
  82. package/src/engine/shaders/pxsl/index.js +25 -0
  83. package/src/engine/shaders/pxsl/library.js +608 -0
  84. package/src/engine/shaders/pxsl/manager.js +338 -0
  85. package/src/engine/shaders/pxsl/specification.js +363 -0
  86. package/src/engine/shaders/pxsl/transpiler.js +753 -0
  87. package/src/engine/shaders/skybox/cosmic/fs.js +147 -0
  88. package/src/engine/shaders/skybox/cosmic/vs.js +23 -0
  89. package/src/engine/shaders/skybox/matrix/fs.js +127 -0
  90. package/src/engine/shaders/skybox/matrix/vs.js +23 -0
  91. package/src/engine/shaders/skybox/morning/fs.js +109 -0
  92. package/src/engine/shaders/skybox/morning/vs.js +23 -0
  93. package/src/engine/shaders/skybox/neon/fs.js +119 -0
  94. package/src/engine/shaders/skybox/neon/vs.js +23 -0
  95. package/src/engine/shaders/skybox/sky/fs.js +114 -0
  96. package/src/engine/shaders/skybox/sky/vs.js +23 -0
  97. package/src/engine/shaders/skybox/sunset/fs.js +101 -0
  98. package/src/engine/shaders/skybox/sunset/vs.js +23 -0
  99. package/src/engine/shaders/transition/blur/fs.js +42 -0
  100. package/src/engine/shaders/transition/blur/vs.js +26 -0
  101. package/src/engine/shaders/transition/cross/fs.js +36 -0
  102. package/src/engine/shaders/transition/cross/vs.js +26 -0
  103. package/src/engine/shaders/transition/crossBlur/fs.js +41 -0
  104. package/src/engine/shaders/transition/crossBlur/vs.js +25 -0
  105. package/src/engine/shaders/transition/dissolve/fs.js +78 -0
  106. package/src/engine/shaders/transition/dissolve/vs.js +24 -0
  107. package/src/engine/shaders/transition/fade/fs.js +31 -0
  108. package/src/engine/shaders/transition/fade/vs.js +27 -0
  109. package/src/engine/shaders/transition/iris/fs.js +52 -0
  110. package/src/engine/shaders/transition/iris/vs.js +24 -0
  111. package/src/engine/shaders/transition/pixelate/fs.js +44 -0
  112. package/src/engine/shaders/transition/pixelate/vs.js +24 -0
  113. package/src/engine/shaders/transition/slide/fs.js +53 -0
  114. package/src/engine/shaders/transition/slide/vs.js +24 -0
  115. package/src/engine/shaders/transition/swirl/fs.js +39 -0
  116. package/src/engine/shaders/transition/swirl/vs.js +26 -0
  117. package/src/engine/shaders/transition/wipe/fs.js +50 -0
  118. package/src/engine/shaders/transition/wipe/vs.js +24 -0
  119. package/src/engine/shaders/vs.js +60 -0
  120. package/src/engine/utils/CameraController.js +506 -0
  121. package/src/engine/utils/ObjHelper.js +551 -0
  122. package/src/engine/utils/debug-logger.js +110 -0
  123. package/src/engine/utils/enums.js +305 -0
  124. package/src/engine/utils/generator.js +156 -0
  125. package/src/engine/utils/index.js +21 -0
  126. package/src/engine/utils/loaders/ActionLoader.js +77 -0
  127. package/src/engine/utils/loaders/AudioLoader.js +157 -0
  128. package/src/engine/utils/loaders/EventLoader.js +66 -0
  129. package/src/engine/utils/loaders/ObjectLoader.js +67 -0
  130. package/src/engine/utils/loaders/SpriteLoader.js +77 -0
  131. package/src/engine/utils/loaders/TilesetLoader.js +103 -0
  132. package/src/engine/utils/loaders/index.js +21 -0
  133. package/src/engine/utils/math/matrix4.js +367 -0
  134. package/src/engine/utils/math/vector.js +458 -0
  135. package/src/engine/utils/obj/_old_js/index.js +46 -0
  136. package/src/engine/utils/obj/_old_js/layout.js +308 -0
  137. package/src/engine/utils/obj/_old_js/material.js +711 -0
  138. package/src/engine/utils/obj/_old_js/mesh.js +761 -0
  139. package/src/engine/utils/obj/_old_js/utils.js +647 -0
  140. package/src/engine/utils/obj/index.js +24 -0
  141. package/src/engine/utils/obj/js/index.js +277 -0
  142. package/src/engine/utils/obj/js/loader.js +232 -0
  143. package/src/engine/utils/obj/layout.js +246 -0
  144. package/src/engine/utils/obj/material.js +665 -0
  145. package/src/engine/utils/obj/mesh.js +657 -0
  146. package/src/engine/utils/obj/ts/index.ts +72 -0
  147. package/src/engine/utils/obj/ts/layout.ts +265 -0
  148. package/src/engine/utils/obj/ts/material.ts +760 -0
  149. package/src/engine/utils/obj/ts/mesh.ts +785 -0
  150. package/src/engine/utils/obj/ts/utils.ts +501 -0
  151. package/src/engine/utils/obj/utils.js +428 -0
  152. package/src/engine/utils/resources.js +18 -0
  153. package/src/index.jsx +55 -0
  154. package/src/spritz/player.js +18 -0
  155. package/src/spritz/readme.md +18 -0
  156. package/LICENSE +0 -437
  157. package/dist/bundle.js.LICENSE.txt +0 -31
@@ -0,0 +1,338 @@
1
+ /**
2
+ * ═══════════════════════════════════════════════════════════════════════════
3
+ * PXSL Shader Manager
4
+ * ═══════════════════════════════════════════════════════════════════════════
5
+ * Copyright (c) 2020-2025 Kyle Derby MacInnis
6
+ *
7
+ * Unified shader management system that supports:
8
+ * - PXSL (.pxsl) - PixoSpritz Shader Language
9
+ * - GLSL (.glsl, .vert, .frag) - Standard WebGL shaders
10
+ * - JavaScript shader functions (legacy support)
11
+ *
12
+ * Features:
13
+ * - Automatic format detection
14
+ * - Shader caching
15
+ * - Hot-reload support
16
+ * - Error handling with helpful messages
17
+ * ═══════════════════════════════════════════════════════════════════════════
18
+ */
19
+
20
+ import { PXSLTranspiler } from './transpiler.js';
21
+
22
+ /**
23
+ * Shader cache entry
24
+ * @typedef {Object} CachedShader
25
+ * @property {string} name - Shader name
26
+ * @property {string} vs - Vertex shader source
27
+ * @property {string} fs - Fragment shader source
28
+ * @property {WebGLProgram} [program] - Compiled program (if compiled)
29
+ * @property {number} timestamp - Cache timestamp
30
+ */
31
+
32
+ /**
33
+ * Shader Manager - Handles loading, caching, and compiling shaders
34
+ */
35
+ export class ShaderManager {
36
+ /**
37
+ * @param {WebGL2RenderingContext} gl - WebGL context
38
+ */
39
+ constructor(gl) {
40
+ /** @type {WebGL2RenderingContext} */
41
+ this.gl = gl;
42
+
43
+ /** @type {Map<string, CachedShader>} */
44
+ this.cache = new Map();
45
+
46
+ /** @type {Map<string, WebGLProgram>} */
47
+ this.programs = new Map();
48
+
49
+ /** @type {boolean} */
50
+ this.debug = process.env.NODE_ENV === 'development';
51
+ }
52
+
53
+ /**
54
+ * Load shader from source code (auto-detects format)
55
+ * @param {string} name - Shader identifier
56
+ * @param {string|{vs: string, fs: string}} source - Shader source(s)
57
+ * @returns {CachedShader}
58
+ */
59
+ load(name, source) {
60
+ // Check cache first
61
+ if (this.cache.has(name)) {
62
+ return this.cache.get(name);
63
+ }
64
+
65
+ let shader;
66
+
67
+ if (typeof source === 'string') {
68
+ // Single source - could be PXSL (combined) or needs separate files
69
+ if (PXSLTranspiler.isPXSL(source)) {
70
+ // PXSL format - transpile
71
+ shader = this.loadPXSL(name, source);
72
+ } else {
73
+ throw new Error(`ShaderManager: Single source must be PXSL format. Use {vs, fs} for separate GLSL.`);
74
+ }
75
+ } else if (source.vs && source.fs) {
76
+ // Separate vertex and fragment shaders
77
+ shader = this.loadGLSL(name, source.vs, source.fs);
78
+ } else {
79
+ throw new Error(`ShaderManager: Invalid source format for shader "${name}"`);
80
+ }
81
+
82
+ this.cache.set(name, shader);
83
+ return shader;
84
+ }
85
+
86
+ /**
87
+ * Load and transpile PXSL shader
88
+ * @param {string} name - Shader name
89
+ * @param {string} source - PXSL source code
90
+ * @returns {CachedShader}
91
+ */
92
+ loadPXSL(name, source) {
93
+ try {
94
+ const result = PXSLTranspiler.transpile(source);
95
+
96
+ if (this.debug) {
97
+ console.log(`[ShaderManager] Transpiled PXSL shader "${result.name || name}"`);
98
+ }
99
+
100
+ return {
101
+ name: result.name || name,
102
+ vs: result.vs,
103
+ fs: result.fs,
104
+ timestamp: Date.now(),
105
+ format: 'pxsl',
106
+ };
107
+ } catch (error) {
108
+ throw new Error(`PXSL Transpilation Error in "${name}": ${error.message}`);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Load GLSL shaders directly
114
+ * @param {string} name - Shader name
115
+ * @param {string} vs - Vertex shader source
116
+ * @param {string} fs - Fragment shader source
117
+ * @returns {CachedShader}
118
+ */
119
+ loadGLSL(name, vs, fs) {
120
+ return {
121
+ name,
122
+ vs,
123
+ fs,
124
+ timestamp: Date.now(),
125
+ format: 'glsl',
126
+ };
127
+ }
128
+
129
+ /**
130
+ * Compile a cached shader into a WebGL program
131
+ * @param {string} name - Shader name
132
+ * @returns {WebGLProgram}
133
+ */
134
+ compile(name) {
135
+ // Check if already compiled
136
+ if (this.programs.has(name)) {
137
+ return this.programs.get(name);
138
+ }
139
+
140
+ const shader = this.cache.get(name);
141
+ if (!shader) {
142
+ throw new Error(`ShaderManager: Shader "${name}" not loaded`);
143
+ }
144
+
145
+ const program = this.createProgram(shader.vs, shader.fs, name);
146
+ this.programs.set(name, program);
147
+
148
+ return program;
149
+ }
150
+
151
+ /**
152
+ * Load and compile shader in one step
153
+ * @param {string} name - Shader name
154
+ * @param {string|{vs: string, fs: string}} source - Shader source
155
+ * @returns {WebGLProgram}
156
+ */
157
+ loadAndCompile(name, source) {
158
+ this.load(name, source);
159
+ return this.compile(name);
160
+ }
161
+
162
+ /**
163
+ * Create a WebGL shader program from source
164
+ * @param {string} vsSource - Vertex shader source
165
+ * @param {string} fsSource - Fragment shader source
166
+ * @param {string} name - Shader name (for error messages)
167
+ * @returns {WebGLProgram}
168
+ */
169
+ createProgram(vsSource, fsSource, name = 'unnamed') {
170
+ const { gl } = this;
171
+
172
+ // Compile vertex shader
173
+ const vertexShader = this.compileShader(gl.VERTEX_SHADER, vsSource, `${name}.vert`);
174
+
175
+ // Compile fragment shader
176
+ const fragmentShader = this.compileShader(gl.FRAGMENT_SHADER, fsSource, `${name}.frag`);
177
+
178
+ // Create program
179
+ const program = gl.createProgram();
180
+ gl.attachShader(program, vertexShader);
181
+ gl.attachShader(program, fragmentShader);
182
+ gl.linkProgram(program);
183
+
184
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
185
+ const log = gl.getProgramInfoLog(program);
186
+ gl.deleteProgram(program);
187
+ throw new Error(`Shader link error in "${name}": ${log}`);
188
+ }
189
+
190
+ // Clean up individual shaders (they're now part of the program)
191
+ gl.deleteShader(vertexShader);
192
+ gl.deleteShader(fragmentShader);
193
+
194
+ // Auto-detect and store attribute/uniform locations
195
+ this.introspectProgram(program);
196
+
197
+ return program;
198
+ }
199
+
200
+ /**
201
+ * Compile a single shader
202
+ * @param {number} type - gl.VERTEX_SHADER or gl.FRAGMENT_SHADER
203
+ * @param {string} source - Shader source code
204
+ * @param {string} name - Shader name for errors
205
+ * @returns {WebGLShader}
206
+ */
207
+ compileShader(type, source, name) {
208
+ const { gl } = this;
209
+ const shader = gl.createShader(type);
210
+
211
+ gl.shaderSource(shader, source);
212
+ gl.compileShader(shader);
213
+
214
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
215
+ const log = gl.getShaderInfoLog(shader);
216
+ gl.deleteShader(shader);
217
+
218
+ // Add line numbers to source for debugging
219
+ const numberedSource = source.split('\n')
220
+ .map((line, i) => `${(i + 1).toString().padStart(3)}: ${line}`)
221
+ .join('\n');
222
+
223
+ throw new Error(
224
+ `Shader compile error in "${name}":\n${log}\n\nSource:\n${numberedSource}`
225
+ );
226
+ }
227
+
228
+ return shader;
229
+ }
230
+
231
+ /**
232
+ * Introspect a program to find all attributes and uniforms
233
+ * @param {WebGLProgram} program - The compiled program
234
+ */
235
+ introspectProgram(program) {
236
+ const { gl } = this;
237
+
238
+ // Get active attributes
239
+ const numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
240
+ program._attributes = {};
241
+
242
+ for (let i = 0; i < numAttribs; i++) {
243
+ const info = gl.getActiveAttrib(program, i);
244
+ const location = gl.getAttribLocation(program, info.name);
245
+ program._attributes[info.name] = { location, type: info.type, size: info.size };
246
+ program[info.name] = location;
247
+ }
248
+
249
+ // Get active uniforms
250
+ const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
251
+ program._uniforms = {};
252
+
253
+ for (let i = 0; i < numUniforms; i++) {
254
+ const info = gl.getActiveUniform(program, i);
255
+ // Handle array uniforms (name ends with [0])
256
+ const baseName = info.name.replace(/\[0\]$/, '');
257
+ const location = gl.getUniformLocation(program, info.name);
258
+ program._uniforms[baseName] = { location, type: info.type, size: info.size };
259
+ program[baseName] = location;
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Get a compiled program by name
265
+ * @param {string} name - Shader name
266
+ * @returns {WebGLProgram|null}
267
+ */
268
+ get(name) {
269
+ return this.programs.get(name) || null;
270
+ }
271
+
272
+ /**
273
+ * Use a shader program
274
+ * @param {string|WebGLProgram} nameOrProgram - Shader name or program
275
+ */
276
+ use(nameOrProgram) {
277
+ const program = typeof nameOrProgram === 'string'
278
+ ? this.programs.get(nameOrProgram)
279
+ : nameOrProgram;
280
+
281
+ if (program) {
282
+ this.gl.useProgram(program);
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Reload a shader (for hot-reload support)
288
+ * @param {string} name - Shader name
289
+ * @param {string|{vs: string, fs: string}} source - New source
290
+ * @returns {WebGLProgram}
291
+ */
292
+ reload(name, source) {
293
+ // Delete old program
294
+ const oldProgram = this.programs.get(name);
295
+ if (oldProgram) {
296
+ this.gl.deleteProgram(oldProgram);
297
+ this.programs.delete(name);
298
+ }
299
+
300
+ // Remove from cache
301
+ this.cache.delete(name);
302
+
303
+ // Load and compile new version
304
+ return this.loadAndCompile(name, source);
305
+ }
306
+
307
+ /**
308
+ * Clear all cached shaders and programs
309
+ */
310
+ clear() {
311
+ // Delete all programs
312
+ for (const program of this.programs.values()) {
313
+ this.gl.deleteProgram(program);
314
+ }
315
+
316
+ this.programs.clear();
317
+ this.cache.clear();
318
+ }
319
+
320
+ /**
321
+ * Get shader source (for debugging/editing)
322
+ * @param {string} name - Shader name
323
+ * @returns {CachedShader|null}
324
+ */
325
+ getSource(name) {
326
+ return this.cache.get(name) || null;
327
+ }
328
+
329
+ /**
330
+ * List all loaded shaders
331
+ * @returns {string[]}
332
+ */
333
+ list() {
334
+ return Array.from(this.cache.keys());
335
+ }
336
+ }
337
+
338
+ export default ShaderManager;
@@ -0,0 +1,363 @@
1
+ /**
2
+ * ═══════════════════════════════════════════════════════════════════════════
3
+ * PXSL - PixoSpritz Shader Language
4
+ * ═══════════════════════════════════════════════════════════════════════════
5
+ *
6
+ * A user-friendly domain-specific language for WebGL shaders.
7
+ * PXSL transpiles to standard GLSL while providing:
8
+ * - Simplified syntax
9
+ * - Built-in common operations
10
+ * - Automatic uniform/varying management
11
+ * - Human-readable effect names
12
+ *
13
+ * ═══════════════════════════════════════════════════════════════════════════
14
+ * LANGUAGE SPECIFICATION
15
+ * ═══════════════════════════════════════════════════════════════════════════
16
+ *
17
+ * FILE EXTENSION: .pxsl
18
+ *
19
+ * ───────────────────────────────────────────────────────────────────────────
20
+ * SHADER DECLARATION
21
+ * ───────────────────────────────────────────────────────────────────────────
22
+ *
23
+ * @vertex // Marks start of vertex shader
24
+ * @fragment // Marks start of fragment shader
25
+ * @shader "name" // Combined shader with name
26
+ *
27
+ * ───────────────────────────────────────────────────────────────────────────
28
+ * VARIABLE DECLARATIONS
29
+ * ───────────────────────────────────────────────────────────────────────────
30
+ *
31
+ * input position: vec3 // Vertex attribute (in vertex shader)
32
+ * input normal: vec3 // Automatically creates aVertexNormal
33
+ * input uv: vec2 // Texture coordinates
34
+ *
35
+ * uniform modelMatrix: mat4 // Uniform from JavaScript
36
+ * uniform time: float // Animation time
37
+ * uniform color: vec3 // Material color
38
+ *
39
+ * output fragColor: vec4 // Fragment output
40
+ * output worldPos: vec3 // Passed to fragment shader (varying)
41
+ *
42
+ * const PI = 3.14159 // Constants
43
+ * let temp: vec3 // Local variable
44
+ *
45
+ * ───────────────────────────────────────────────────────────────────────────
46
+ * BUILT-IN FUNCTIONS (Simplified Names)
47
+ * ───────────────────────────────────────────────────────────────────────────
48
+ *
49
+ * // Lighting
50
+ * diffuse(normal, lightDir) -> dot(normal, lightDir)
51
+ * specular(normal, lightDir, viewDir, power) -> Blinn-Phong specular
52
+ * fresnel(normal, viewDir, power) -> Fresnel effect
53
+ *
54
+ * // Color Operations
55
+ * brighten(color, amount) -> color * (1 + amount)
56
+ * darken(color, amount) -> color * (1 - amount)
57
+ * saturate(color, amount) -> Adjust saturation
58
+ * contrast(color, amount) -> Adjust contrast
59
+ * tint(color, tintColor, amount) -> Mix with tint
60
+ *
61
+ * // Effects
62
+ * fog(color, depth, fogColor, density) -> Apply fog
63
+ * glow(color, intensity) -> Add bloom/glow
64
+ * outline(uv, texture, color, width) -> Edge detection
65
+ * pixelate(uv, resolution) -> Pixelation effect
66
+ *
67
+ * // Math Helpers
68
+ * remap(value, inMin, inMax, outMin, outMax) -> Remap range
69
+ * smoothstep(edge0, edge1, x) -> Smooth interpolation
70
+ * pulse(value, frequency) -> sin-based pulse
71
+ * noise(uv) -> Simple noise
72
+ * fbm(uv, octaves) -> Fractal Brownian Motion
73
+ *
74
+ * // Transforms
75
+ * rotateUV(uv, angle, center) -> Rotate UVs
76
+ * scaleUV(uv, scale, center) -> Scale UVs
77
+ * waveUV(uv, amplitude, frequency, time) -> Wave distortion
78
+ *
79
+ * ───────────────────────────────────────────────────────────────────────────
80
+ * EFFECTS (Automatic Shader Generation)
81
+ * ───────────────────────────────────────────────────────────────────────────
82
+ *
83
+ * @effect "water" {
84
+ * wave: { amplitude: 0.1, frequency: 2.0 }
85
+ * reflection: 0.5
86
+ * transparency: 0.3
87
+ * }
88
+ *
89
+ * @effect "fire" {
90
+ * distortion: 0.2
91
+ * colorGradient: [orange, red, yellow]
92
+ * speed: 1.5
93
+ * }
94
+ *
95
+ * ───────────────────────────────────────────────────────────────────────────
96
+ * EXAMPLE SHADER
97
+ * ───────────────────────────────────────────────────────────────────────────
98
+ *
99
+ * @shader "glow_effect"
100
+ *
101
+ * @vertex
102
+ * input position: vec3
103
+ * input uv: vec2
104
+ * uniform modelMatrix: mat4
105
+ * uniform viewMatrix: mat4
106
+ * uniform projectionMatrix: mat4
107
+ * output vUV: vec2
108
+ *
109
+ * main {
110
+ * vUV = uv
111
+ * gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0)
112
+ * }
113
+ *
114
+ * @fragment
115
+ * input vUV: vec2
116
+ * uniform texture: sampler2D
117
+ * uniform time: float
118
+ * uniform glowColor: vec3
119
+ * uniform glowIntensity: float
120
+ * output fragColor: vec4
121
+ *
122
+ * main {
123
+ * let baseColor = sample(texture, vUV)
124
+ * let glow = pulse(time, 2.0) * glowIntensity
125
+ * fragColor = baseColor + vec4(glowColor * glow, 0.0)
126
+ * }
127
+ *
128
+ * ═══════════════════════════════════════════════════════════════════════════
129
+ */
130
+
131
+ // Built-in GLSL snippets that get injected based on usage
132
+ export const PXSL_BUILTINS = {
133
+ // ─────────────────────────────────────────────────────────────────────────
134
+ // Lighting Functions
135
+ // ─────────────────────────────────────────────────────────────────────────
136
+ diffuse: `
137
+ float pxsl_diffuse(vec3 normal, vec3 lightDir) {
138
+ return max(dot(normalize(normal), normalize(lightDir)), 0.0);
139
+ }`,
140
+
141
+ specular: `
142
+ float pxsl_specular(vec3 normal, vec3 lightDir, vec3 viewDir, float power) {
143
+ vec3 n = normalize(normal);
144
+ vec3 l = normalize(lightDir);
145
+ vec3 v = normalize(viewDir);
146
+ vec3 h = normalize(l + v);
147
+ return pow(max(dot(n, h), 0.0), power);
148
+ }`,
149
+
150
+ fresnel: `
151
+ float pxsl_fresnel(vec3 normal, vec3 viewDir, float power) {
152
+ return pow(1.0 - max(dot(normalize(normal), normalize(viewDir)), 0.0), power);
153
+ }`,
154
+
155
+ // ─────────────────────────────────────────────────────────────────────────
156
+ // Color Functions
157
+ // ─────────────────────────────────────────────────────────────────────────
158
+ brighten: `
159
+ vec3 pxsl_brighten(vec3 color, float amount) {
160
+ return color * (1.0 + amount);
161
+ }
162
+ vec4 pxsl_brighten(vec4 color, float amount) {
163
+ return vec4(color.rgb * (1.0 + amount), color.a);
164
+ }`,
165
+
166
+ darken: `
167
+ vec3 pxsl_darken(vec3 color, float amount) {
168
+ return color * (1.0 - clamp(amount, 0.0, 1.0));
169
+ }
170
+ vec4 pxsl_darken(vec4 color, float amount) {
171
+ return vec4(color.rgb * (1.0 - clamp(amount, 0.0, 1.0)), color.a);
172
+ }`,
173
+
174
+ saturate: `
175
+ vec3 pxsl_saturate(vec3 color, float amount) {
176
+ float gray = dot(color, vec3(0.299, 0.587, 0.114));
177
+ return mix(vec3(gray), color, amount);
178
+ }`,
179
+
180
+ contrast: `
181
+ vec3 pxsl_contrast(vec3 color, float amount) {
182
+ return (color - 0.5) * amount + 0.5;
183
+ }`,
184
+
185
+ tint: `
186
+ vec3 pxsl_tint(vec3 color, vec3 tintColor, float amount) {
187
+ return mix(color, color * tintColor, amount);
188
+ }`,
189
+
190
+ // ─────────────────────────────────────────────────────────────────────────
191
+ // Effect Functions
192
+ // ─────────────────────────────────────────────────────────────────────────
193
+ fog: `
194
+ vec3 pxsl_fog(vec3 color, float depth, vec3 fogColor, float density) {
195
+ float fogFactor = 1.0 - exp(-density * depth);
196
+ return mix(color, fogColor, clamp(fogFactor, 0.0, 1.0));
197
+ }
198
+ vec4 pxsl_fog(vec4 color, float depth, vec3 fogColor, float density) {
199
+ float fogFactor = 1.0 - exp(-density * depth);
200
+ return vec4(mix(color.rgb, fogColor, clamp(fogFactor, 0.0, 1.0)), color.a);
201
+ }`,
202
+
203
+ glow: `
204
+ vec3 pxsl_glow(vec3 color, float intensity) {
205
+ float luminance = dot(color, vec3(0.299, 0.587, 0.114));
206
+ return color + color * luminance * intensity;
207
+ }
208
+ vec4 pxsl_glow(vec4 color, float intensity) {
209
+ float luminance = dot(color.rgb, vec3(0.299, 0.587, 0.114));
210
+ return vec4(color.rgb + color.rgb * luminance * intensity, color.a);
211
+ }`,
212
+
213
+ outline: `
214
+ vec4 pxsl_outline(vec2 uv, sampler2D tex, vec3 outlineColor, float width) {
215
+ vec2 texelSize = vec2(1.0 / 512.0); // Adjust based on texture size
216
+ vec4 center = texture2D(tex, uv);
217
+ float edge = 0.0;
218
+ edge += texture2D(tex, uv + vec2(-width, 0.0) * texelSize).a;
219
+ edge += texture2D(tex, uv + vec2(width, 0.0) * texelSize).a;
220
+ edge += texture2D(tex, uv + vec2(0.0, -width) * texelSize).a;
221
+ edge += texture2D(tex, uv + vec2(0.0, width) * texelSize).a;
222
+ edge = clamp(edge - center.a * 4.0, 0.0, 1.0);
223
+ return mix(center, vec4(outlineColor, 1.0), edge * (1.0 - center.a));
224
+ }`,
225
+
226
+ pixelate: `
227
+ vec2 pxsl_pixelate(vec2 uv, float resolution) {
228
+ return floor(uv * resolution) / resolution;
229
+ }`,
230
+
231
+ // ─────────────────────────────────────────────────────────────────────────
232
+ // Math Helpers
233
+ // ─────────────────────────────────────────────────────────────────────────
234
+ remap: `
235
+ float pxsl_remap(float value, float inMin, float inMax, float outMin, float outMax) {
236
+ return outMin + (value - inMin) * (outMax - outMin) / (inMax - inMin);
237
+ }`,
238
+
239
+ pulse: `
240
+ float pxsl_pulse(float value, float frequency) {
241
+ return (sin(value * frequency * 6.28318) + 1.0) * 0.5;
242
+ }`,
243
+
244
+ noise: `
245
+ float pxsl_noise(vec2 uv) {
246
+ return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453);
247
+ }`,
248
+
249
+ fbm: `
250
+ float pxsl_fbm(vec2 uv, int octaves) {
251
+ float value = 0.0;
252
+ float amplitude = 0.5;
253
+ float frequency = 1.0;
254
+ for(int i = 0; i < 8; i++) {
255
+ if(i >= octaves) break;
256
+ value += amplitude * pxsl_noise(uv * frequency);
257
+ amplitude *= 0.5;
258
+ frequency *= 2.0;
259
+ }
260
+ return value;
261
+ }`,
262
+
263
+ // ─────────────────────────────────────────────────────────────────────────
264
+ // UV Transform Functions
265
+ // ─────────────────────────────────────────────────────────────────────────
266
+ rotateUV: `
267
+ vec2 pxsl_rotateUV(vec2 uv, float angle, vec2 center) {
268
+ float s = sin(angle);
269
+ float c = cos(angle);
270
+ uv -= center;
271
+ return vec2(uv.x * c - uv.y * s, uv.x * s + uv.y * c) + center;
272
+ }`,
273
+
274
+ scaleUV: `
275
+ vec2 pxsl_scaleUV(vec2 uv, vec2 scale, vec2 center) {
276
+ return (uv - center) * scale + center;
277
+ }`,
278
+
279
+ waveUV: `
280
+ vec2 pxsl_waveUV(vec2 uv, float amplitude, float frequency, float time) {
281
+ return uv + vec2(
282
+ sin(uv.y * frequency + time) * amplitude,
283
+ sin(uv.x * frequency + time) * amplitude
284
+ );
285
+ }`,
286
+
287
+ // ─────────────────────────────────────────────────────────────────────────
288
+ // Utility Functions
289
+ // ─────────────────────────────────────────────────────────────────────────
290
+ linearizeDepth: `
291
+ float pxsl_linearizeDepth(float depth, float near, float far) {
292
+ float z = depth * 2.0 - 1.0;
293
+ return (2.0 * near * far) / (far + near - z * (far - near));
294
+ }`,
295
+
296
+ sample: `
297
+ #define pxsl_sample(tex, uv) texture2D(tex, uv)`,
298
+ };
299
+
300
+ // Standard precision and version headers
301
+ export const PXSL_HEADERS = {
302
+ vertex: `precision mediump float;
303
+ precision mediump int;
304
+ `,
305
+ fragment: `precision mediump float;
306
+ precision mediump int;
307
+ `,
308
+ };
309
+
310
+ // Type mappings for cleaner syntax
311
+ export const PXSL_TYPE_ALIASES = {
312
+ float: 'float',
313
+ int: 'int',
314
+ bool: 'bool',
315
+ vec2: 'vec2',
316
+ vec3: 'vec3',
317
+ vec4: 'vec4',
318
+ mat2: 'mat2',
319
+ mat3: 'mat3',
320
+ mat4: 'mat4',
321
+ sampler: 'sampler2D',
322
+ samplerCube: 'samplerCube',
323
+ // User-friendly aliases
324
+ color: 'vec4',
325
+ color3: 'vec3',
326
+ point: 'vec3',
327
+ point2: 'vec2',
328
+ direction: 'vec3',
329
+ normal: 'vec3',
330
+ matrix: 'mat4',
331
+ texture: 'sampler2D',
332
+ cubemap: 'samplerCube',
333
+ };
334
+
335
+ // Standard input name mappings (what user writes -> what GLSL expects)
336
+ export const PXSL_INPUT_MAPPINGS = {
337
+ position: 'aVertexPosition',
338
+ normal: 'aVertexNormal',
339
+ uv: 'aTextureCoord',
340
+ texcoord: 'aTextureCoord',
341
+ color: 'aVertexColor',
342
+ tangent: 'aVertexTangent',
343
+ };
344
+
345
+ // Standard uniform name mappings
346
+ export const PXSL_UNIFORM_MAPPINGS = {
347
+ modelMatrix: 'uModelMatrix',
348
+ viewMatrix: 'uViewMatrix',
349
+ projectionMatrix: 'uProjectionMatrix',
350
+ normalMatrix: 'uNormalMatrix',
351
+ cameraPosition: 'uCameraPosition',
352
+ time: 'uTime',
353
+ resolution: 'uResolution',
354
+ // Lights are auto-handled
355
+ };
356
+
357
+ export default {
358
+ PXSL_BUILTINS,
359
+ PXSL_HEADERS,
360
+ PXSL_TYPE_ALIASES,
361
+ PXSL_INPUT_MAPPINGS,
362
+ PXSL_UNIFORM_MAPPINGS,
363
+ };