@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.
- package/demos/coordinates.html +698 -0
- package/demos/cube3d.html +23 -0
- package/demos/demos.css +17 -3
- package/demos/dino.html +42 -0
- package/demos/gameobjects.html +626 -0
- package/demos/index.html +17 -7
- package/demos/js/coordinates.js +840 -0
- package/demos/js/cube3d.js +789 -0
- package/demos/js/dino.js +1420 -0
- package/demos/js/gameobjects.js +176 -0
- package/demos/js/plane3d.js +256 -0
- package/demos/js/platformer.js +1579 -0
- package/demos/js/sphere3d.js +229 -0
- package/demos/js/sprite.js +473 -0
- package/demos/js/tde/accretiondisk.js +3 -3
- package/demos/js/tde/tidalstream.js +2 -2
- package/demos/plane3d.html +24 -0
- package/demos/platformer.html +43 -0
- package/demos/sphere3d.html +24 -0
- package/demos/sprite.html +18 -0
- package/docs/concepts/coordinate-system.md +384 -0
- package/docs/concepts/shapes-vs-gameobjects.md +187 -0
- package/docs/fluid-dynamics.md +99 -97
- package/package.json +1 -1
- package/src/game/game.js +11 -5
- package/src/game/objects/index.js +3 -0
- package/src/game/objects/platformer-scene.js +411 -0
- package/src/game/objects/scene.js +14 -0
- package/src/game/objects/sprite.js +529 -0
- package/src/game/pipeline.js +20 -16
- package/src/game/ui/theme.js +123 -121
- package/src/io/input.js +75 -45
- package/src/io/mouse.js +44 -19
- package/src/io/touch.js +35 -12
- package/src/shapes/cube3d.js +599 -0
- package/src/shapes/index.js +2 -0
- package/src/shapes/plane3d.js +687 -0
- package/src/shapes/sphere3d.js +75 -6
- package/src/util/camera2d.js +315 -0
- package/src/util/index.js +1 -0
- package/src/webgl/shaders/plane-shaders.js +332 -0
- 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
|
|
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;
|