@guinetik/gcanvas 1.0.1 → 1.0.2

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 (42) hide show
  1. package/demos/coordinates.html +698 -0
  2. package/demos/cube3d.html +23 -0
  3. package/demos/demos.css +17 -3
  4. package/demos/dino.html +42 -0
  5. package/demos/gameobjects.html +626 -0
  6. package/demos/index.html +17 -7
  7. package/demos/js/coordinates.js +840 -0
  8. package/demos/js/cube3d.js +789 -0
  9. package/demos/js/dino.js +1420 -0
  10. package/demos/js/gameobjects.js +176 -0
  11. package/demos/js/plane3d.js +256 -0
  12. package/demos/js/platformer.js +1579 -0
  13. package/demos/js/sphere3d.js +229 -0
  14. package/demos/js/sprite.js +473 -0
  15. package/demos/js/tde/accretiondisk.js +3 -3
  16. package/demos/js/tde/tidalstream.js +2 -2
  17. package/demos/plane3d.html +24 -0
  18. package/demos/platformer.html +43 -0
  19. package/demos/sphere3d.html +24 -0
  20. package/demos/sprite.html +18 -0
  21. package/docs/concepts/coordinate-system.md +384 -0
  22. package/docs/concepts/shapes-vs-gameobjects.md +187 -0
  23. package/docs/fluid-dynamics.md +99 -97
  24. package/package.json +1 -1
  25. package/src/game/game.js +11 -5
  26. package/src/game/objects/index.js +3 -0
  27. package/src/game/objects/platformer-scene.js +411 -0
  28. package/src/game/objects/scene.js +14 -0
  29. package/src/game/objects/sprite.js +529 -0
  30. package/src/game/pipeline.js +20 -16
  31. package/src/game/ui/theme.js +123 -121
  32. package/src/io/input.js +75 -45
  33. package/src/io/mouse.js +44 -19
  34. package/src/io/touch.js +35 -12
  35. package/src/shapes/cube3d.js +599 -0
  36. package/src/shapes/index.js +2 -0
  37. package/src/shapes/plane3d.js +687 -0
  38. package/src/shapes/sphere3d.js +75 -6
  39. package/src/util/camera2d.js +315 -0
  40. package/src/util/index.js +1 -0
  41. package/src/webgl/shaders/plane-shaders.js +332 -0
  42. package/src/webgl/shaders/sphere-shaders.js +4 -2
@@ -0,0 +1,332 @@
1
+ /**
2
+ * Plane Shaders for WebGL Rendering
3
+ *
4
+ * These shaders render 2D patterns onto a plane quad.
5
+ * Unlike sphere shaders which use ray-sphere intersection,
6
+ * these shaders work directly with UV coordinates.
7
+ */
8
+
9
+ // =============================================================================
10
+ // VERTEX SHADER
11
+ // =============================================================================
12
+
13
+ /**
14
+ * Standard vertex shader for plane rendering
15
+ * Simply passes through position and UV coordinates
16
+ */
17
+ export const PLANE_VERTEX = `
18
+ precision highp float;
19
+
20
+ attribute vec2 aPosition;
21
+ attribute vec2 aUv;
22
+
23
+ varying vec2 vUv;
24
+
25
+ void main() {
26
+ vUv = aUv;
27
+ gl_Position = vec4(aPosition, 0.0, 1.0);
28
+ }
29
+ `;
30
+
31
+ // =============================================================================
32
+ // COMMON SHADER FUNCTIONS
33
+ // =============================================================================
34
+
35
+ /**
36
+ * Common functions included in all plane fragment shaders
37
+ */
38
+ export const PLANE_COMMON = `
39
+ precision highp float;
40
+
41
+ varying vec2 vUv;
42
+
43
+ uniform float uTime;
44
+ uniform vec2 uResolution;
45
+
46
+ // =============================================================================
47
+ // NOISE FUNCTIONS
48
+ // =============================================================================
49
+
50
+ float hash(float n) {
51
+ return fract(sin(n) * 43758.5453123);
52
+ }
53
+
54
+ float hash2(vec2 p) {
55
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
56
+ }
57
+
58
+ // 2D Value noise
59
+ float noise2D(vec2 x) {
60
+ vec2 i = floor(x);
61
+ vec2 f = fract(x);
62
+ f = f * f * (3.0 - 2.0 * f);
63
+
64
+ float a = hash2(i);
65
+ float b = hash2(i + vec2(1.0, 0.0));
66
+ float c = hash2(i + vec2(0.0, 1.0));
67
+ float d = hash2(i + vec2(1.0, 1.0));
68
+
69
+ return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
70
+ }
71
+
72
+ // FBM (Fractional Brownian Motion)
73
+ float fbm2D(vec2 p, int octaves) {
74
+ float value = 0.0;
75
+ float amplitude = 0.5;
76
+ float frequency = 1.0;
77
+
78
+ for (int i = 0; i < 8; i++) {
79
+ if (i >= octaves) break;
80
+ value += amplitude * noise2D(p * frequency);
81
+ frequency *= 2.0;
82
+ amplitude *= 0.5;
83
+ }
84
+
85
+ return value;
86
+ }
87
+ `;
88
+
89
+ // =============================================================================
90
+ // GRADIENT SHADER
91
+ // =============================================================================
92
+
93
+ /**
94
+ * Linear gradient shader
95
+ * Uniforms:
96
+ * - uColor1: Start color [r, g, b] (0-1)
97
+ * - uColor2: End color [r, g, b] (0-1)
98
+ * - uAngle: Gradient angle in radians (0 = horizontal, PI/2 = vertical)
99
+ */
100
+ export const GRADIENT_FRAGMENT = `
101
+ ${PLANE_COMMON}
102
+
103
+ uniform vec3 uColor1;
104
+ uniform vec3 uColor2;
105
+ uniform float uAngle;
106
+
107
+ void main() {
108
+ vec2 uv = vUv;
109
+
110
+ // Calculate gradient direction from angle
111
+ vec2 dir = vec2(cos(uAngle), sin(uAngle));
112
+
113
+ // Project UV onto gradient direction
114
+ // Center at 0.5 so gradient goes through middle
115
+ float t = dot(uv - 0.5, dir) + 0.5;
116
+ t = clamp(t, 0.0, 1.0);
117
+
118
+ // Interpolate colors
119
+ vec3 color = mix(uColor1, uColor2, t);
120
+
121
+ gl_FragColor = vec4(color, 1.0);
122
+ }
123
+ `;
124
+
125
+ // =============================================================================
126
+ // GRID SHADER
127
+ // =============================================================================
128
+
129
+ /**
130
+ * Grid pattern shader
131
+ * Uniforms:
132
+ * - uLineColor: Grid line color [r, g, b] (0-1)
133
+ * - uBackgroundColor: Background color [r, g, b] (0-1)
134
+ * - uGridSize: Number of grid cells (e.g., 8.0 = 8x8 grid)
135
+ * - uLineWidth: Line width as fraction of cell (e.g., 0.05)
136
+ */
137
+ export const GRID_FRAGMENT = `
138
+ ${PLANE_COMMON}
139
+
140
+ uniform vec3 uLineColor;
141
+ uniform vec3 uBackgroundColor;
142
+ uniform float uGridSize;
143
+ uniform float uLineWidth;
144
+
145
+ void main() {
146
+ vec2 uv = vUv;
147
+
148
+ // Scale UV to grid space
149
+ vec2 grid = fract(uv * uGridSize);
150
+
151
+ // Calculate distance to nearest grid line
152
+ float lineX = min(grid.x, 1.0 - grid.x);
153
+ float lineY = min(grid.y, 1.0 - grid.y);
154
+
155
+ // Smoothstep for anti-aliased lines
156
+ float halfWidth = uLineWidth * 0.5;
157
+ float edgeSmooth = 0.01;
158
+
159
+ float lineAlphaX = 1.0 - smoothstep(halfWidth - edgeSmooth, halfWidth + edgeSmooth, lineX);
160
+ float lineAlphaY = 1.0 - smoothstep(halfWidth - edgeSmooth, halfWidth + edgeSmooth, lineY);
161
+ float lineAlpha = max(lineAlphaX, lineAlphaY);
162
+
163
+ // Mix colors
164
+ vec3 color = mix(uBackgroundColor, uLineColor, lineAlpha);
165
+
166
+ gl_FragColor = vec4(color, 1.0);
167
+ }
168
+ `;
169
+
170
+ // =============================================================================
171
+ // CHECKERBOARD SHADER
172
+ // =============================================================================
173
+
174
+ /**
175
+ * Checkerboard pattern shader
176
+ * Uniforms:
177
+ * - uColor1: First square color [r, g, b] (0-1)
178
+ * - uColor2: Second square color [r, g, b] (0-1)
179
+ * - uSize: Number of squares per side (e.g., 8.0 = 8x8)
180
+ */
181
+ export const CHECKERBOARD_FRAGMENT = `
182
+ ${PLANE_COMMON}
183
+
184
+ uniform vec3 uColor1;
185
+ uniform vec3 uColor2;
186
+ uniform float uSize;
187
+
188
+ void main() {
189
+ vec2 uv = vUv;
190
+
191
+ // Calculate which square we're in
192
+ vec2 cell = floor(uv * uSize);
193
+
194
+ // Alternating pattern based on cell coordinates
195
+ float checker = mod(cell.x + cell.y, 2.0);
196
+
197
+ // Select color
198
+ vec3 color = mix(uColor1, uColor2, checker);
199
+
200
+ gl_FragColor = vec4(color, 1.0);
201
+ }
202
+ `;
203
+
204
+ // =============================================================================
205
+ // NOISE SHADER
206
+ // =============================================================================
207
+
208
+ /**
209
+ * Animated noise pattern shader
210
+ * Uniforms:
211
+ * - uColor1: Base color [r, g, b] (0-1)
212
+ * - uColor2: Secondary color [r, g, b] (0-1)
213
+ * - uNoiseScale: Scale of the noise pattern (e.g., 4.0)
214
+ * - uAnimSpeed: Animation speed (e.g., 0.5)
215
+ */
216
+ export const NOISE_FRAGMENT = `
217
+ ${PLANE_COMMON}
218
+
219
+ uniform vec3 uColor1;
220
+ uniform vec3 uColor2;
221
+ uniform float uNoiseScale;
222
+ uniform float uAnimSpeed;
223
+
224
+ void main() {
225
+ vec2 uv = vUv;
226
+
227
+ // Animated noise
228
+ float n = fbm2D(uv * uNoiseScale + uTime * uAnimSpeed, 4);
229
+
230
+ // Map noise to colors
231
+ vec3 color = mix(uColor1, uColor2, n);
232
+
233
+ gl_FragColor = vec4(color, 1.0);
234
+ }
235
+ `;
236
+
237
+ // =============================================================================
238
+ // RADIAL GRADIENT SHADER
239
+ // =============================================================================
240
+
241
+ /**
242
+ * Radial gradient shader
243
+ * Uniforms:
244
+ * - uColor1: Center color [r, g, b] (0-1)
245
+ * - uColor2: Edge color [r, g, b] (0-1)
246
+ * - uCenterX: Center X position (0-1, default 0.5)
247
+ * - uCenterY: Center Y position (0-1, default 0.5)
248
+ * - uRadius: Gradient radius (default 0.5)
249
+ */
250
+ export const RADIAL_GRADIENT_FRAGMENT = `
251
+ ${PLANE_COMMON}
252
+
253
+ uniform vec3 uColor1;
254
+ uniform vec3 uColor2;
255
+ uniform float uCenterX;
256
+ uniform float uCenterY;
257
+ uniform float uRadius;
258
+
259
+ void main() {
260
+ vec2 uv = vUv;
261
+ vec2 center = vec2(uCenterX, uCenterY);
262
+
263
+ // Calculate distance from center
264
+ float dist = length(uv - center);
265
+
266
+ // Normalize by radius
267
+ float t = clamp(dist / uRadius, 0.0, 1.0);
268
+
269
+ // Interpolate colors
270
+ vec3 color = mix(uColor1, uColor2, t);
271
+
272
+ gl_FragColor = vec4(color, 1.0);
273
+ }
274
+ `;
275
+
276
+ // =============================================================================
277
+ // STRIPES SHADER
278
+ // =============================================================================
279
+
280
+ /**
281
+ * Stripe pattern shader
282
+ * Uniforms:
283
+ * - uColor1: First stripe color [r, g, b] (0-1)
284
+ * - uColor2: Second stripe color [r, g, b] (0-1)
285
+ * - uStripeCount: Number of stripes
286
+ * - uAngle: Stripe angle in radians
287
+ */
288
+ export const STRIPES_FRAGMENT = `
289
+ ${PLANE_COMMON}
290
+
291
+ uniform vec3 uColor1;
292
+ uniform vec3 uColor2;
293
+ uniform float uStripeCount;
294
+ uniform float uAngle;
295
+
296
+ void main() {
297
+ vec2 uv = vUv;
298
+
299
+ // Rotate UV by angle
300
+ vec2 center = vec2(0.5);
301
+ vec2 rotated = uv - center;
302
+ float c = cos(uAngle);
303
+ float s = sin(uAngle);
304
+ rotated = vec2(rotated.x * c - rotated.y * s, rotated.x * s + rotated.y * c);
305
+ rotated += center;
306
+
307
+ // Create stripes along one axis
308
+ float stripe = floor(mod(rotated.x * uStripeCount, 2.0));
309
+
310
+ // Select color
311
+ vec3 color = mix(uColor1, uColor2, stripe);
312
+
313
+ gl_FragColor = vec4(color, 1.0);
314
+ }
315
+ `;
316
+
317
+ // =============================================================================
318
+ // SHADER EXPORT
319
+ // =============================================================================
320
+
321
+ export const PLANE_SHADERS = {
322
+ vertex: PLANE_VERTEX,
323
+ common: PLANE_COMMON,
324
+ gradient: GRADIENT_FRAGMENT,
325
+ grid: GRID_FRAGMENT,
326
+ checkerboard: CHECKERBOARD_FRAGMENT,
327
+ noise: NOISE_FRAGMENT,
328
+ radialGradient: RADIAL_GRADIENT_FRAGMENT,
329
+ stripes: STRIPES_FRAGMENT,
330
+ };
331
+
332
+ export default PLANE_SHADERS;
@@ -904,6 +904,7 @@ ${SPHERE_COMMON}
904
904
  uniform vec3 uBaseColor;
905
905
  uniform float uSeed;
906
906
  uniform float uStormIntensity; // 0-1
907
+ uniform float uRotationSpeed; // rotation speed multiplier (default ~0.1)
907
908
 
908
909
  void main() {
909
910
  // Setup ray - camera looking at sphere from fixed position
@@ -930,8 +931,9 @@ void main() {
930
931
  float latitude = asin(rotatedNormal.y); // -PI/2 to PI/2
931
932
  float longitude = atan(rotatedNormal.z, rotatedNormal.x); // -PI to PI
932
933
 
933
- // Animated rotation
934
- float time = uTime * 0.1;
934
+ // Animated rotation (use uRotationSpeed, default to 0.1 if not set)
935
+ float rotSpeed = uRotationSpeed > 0.0 ? uRotationSpeed : 0.1;
936
+ float time = uTime * rotSpeed;
935
937
 
936
938
  // Create bands based on latitude
937
939
  float bands = sin(latitude * 15.0 + time) * 0.5 + 0.5;