@call-me-sensei/toonlab 0.1.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 (146) hide show
  1. package/ATTRIBUTION.md +40 -0
  2. package/LICENSE +21 -0
  3. package/README.md +125 -0
  4. package/package.json +97 -0
  5. package/src/character/characterRig.js +353 -0
  6. package/src/character/freestyleSwimClip.js +541 -0
  7. package/src/character/index.js +4 -0
  8. package/src/character/modelLoader.js +433 -0
  9. package/src/core/materialRoles.js +438 -0
  10. package/src/core/presetDocuments.js +110 -0
  11. package/src/core/shaderBackend.js +24 -0
  12. package/src/debrisgen/debrisFields.js +544 -0
  13. package/src/debrisgen/debrisGenerator.js +1929 -0
  14. package/src/debrisgen/debrisPalettes.js +71 -0
  15. package/src/debrisgen/debrisPhysics.js +198 -0
  16. package/src/debrisgen/debrisPresets.js +155 -0
  17. package/src/debrisgen/debrisSettings.js +333 -0
  18. package/src/debrisgen/debrisTextures.js +380 -0
  19. package/src/debrisgen/index.js +5 -0
  20. package/src/debug/fieldValues.js +95 -0
  21. package/src/debug/index.js +7 -0
  22. package/src/debug/settingsPanel.js +170 -0
  23. package/src/environment/environmentAmbientProbe.js +160 -0
  24. package/src/environment/environmentMaterialAdapter.js +336 -0
  25. package/src/environment/environmentMaterialClassifier.js +178 -0
  26. package/src/environment/environmentPlanarReflection.js +201 -0
  27. package/src/environment/environmentPresets.js +443 -0
  28. package/src/environment/environmentRigs.js +684 -0
  29. package/src/environment/environmentSettings.js +504 -0
  30. package/src/environment/environmentShaderMaterials.js +318 -0
  31. package/src/environment/environmentSunShadowPass.js +268 -0
  32. package/src/environment/environmentTextureResolver.js +161 -0
  33. package/src/environment/environmentTimeOfDay.js +167 -0
  34. package/src/environment/environmentVertexAo.js +188 -0
  35. package/src/environment/index.js +8 -0
  36. package/src/environment/scanAssetStylize.js +103 -0
  37. package/src/index.js +21 -0
  38. package/src/loaders/index.js +1 -0
  39. package/src/post/index.js +2 -0
  40. package/src/post/postProcessing.js +1087 -0
  41. package/src/rockgen/export/glbExport.js +177 -0
  42. package/src/rockgen/heightfield/heightfieldErosion.js +7 -0
  43. package/src/rockgen/heightfield/heightfieldPatch.js +183 -0
  44. package/src/rockgen/heightfield/stylizedErosionSim.js +356 -0
  45. package/src/rockgen/index.js +14 -0
  46. package/src/rockgen/mesh/meshAttributes.js +374 -0
  47. package/src/rockgen/mesh/meshDocument.js +158 -0
  48. package/src/rockgen/mesh/surfaceNets.js +329 -0
  49. package/src/rockgen/noise/cellularNoise3.js +92 -0
  50. package/src/rockgen/noise/prng.js +62 -0
  51. package/src/rockgen/noise/simplexNoise3.js +89 -0
  52. package/src/rockgen/noise/valueNoise3.js +87 -0
  53. package/src/rockgen/rockDocument.js +255 -0
  54. package/src/rockgen/rockHelpers.js +8 -0
  55. package/src/rockgen/rockgenPresets.js +559 -0
  56. package/src/rockgen/rockgenSettings.js +756 -0
  57. package/src/rockgen/sdf/fieldCompiler.js +544 -0
  58. package/src/rockgen/sdf/sculptEdits.js +66 -0
  59. package/src/rockgen/sdf/sdfModifiers.js +45 -0
  60. package/src/rockgen/sdf/sdfOps.js +37 -0
  61. package/src/rockgen/sdf/sdfPrimitives.js +88 -0
  62. package/src/shaders-tsl/anime.js +963 -0
  63. package/src/shaders-tsl/chunks/character-color.js +64 -0
  64. package/src/shaders-tsl/chunks/character-highlights.js +174 -0
  65. package/src/shaders-tsl/chunks/character-lighting.js +309 -0
  66. package/src/shaders-tsl/chunks/character-material-maps.js +146 -0
  67. package/src/shaders-tsl/chunks/character-roles.js +52 -0
  68. package/src/shaders-tsl/chunks/character-scene-lights.js +270 -0
  69. package/src/shaders-tsl/chunks/character-shadow-color.js +61 -0
  70. package/src/shaders-tsl/chunks/character-skinning.js +140 -0
  71. package/src/shaders-tsl/chunks/environment-color.js +47 -0
  72. package/src/shaders-tsl/chunks/environment-debug.js +79 -0
  73. package/src/shaders-tsl/chunks/environment-lighting.js +260 -0
  74. package/src/shaders-tsl/chunks/environment-sun-shadow.js +87 -0
  75. package/src/shaders-tsl/chunks/foliage-fog.js +60 -0
  76. package/src/shaders-tsl/chunks/pass-depth-color.js +89 -0
  77. package/src/shaders-tsl/chunks/stylized-cloud-shadow.js +70 -0
  78. package/src/shaders-tsl/chunks/water-color.js +190 -0
  79. package/src/shaders-tsl/chunks/water-common.js +124 -0
  80. package/src/shaders-tsl/chunks/water-foam.js +93 -0
  81. package/src/shaders-tsl/chunks/water-lighting.js +116 -0
  82. package/src/shaders-tsl/chunks/water-ripple.js +64 -0
  83. package/src/shaders-tsl/chunks/water-waves.js +100 -0
  84. package/src/shaders-tsl/environment-ao-overlay.js +60 -0
  85. package/src/shaders-tsl/environment.js +680 -0
  86. package/src/shaders-tsl/flower.js +267 -0
  87. package/src/shaders-tsl/grass.js +193 -0
  88. package/src/shaders-tsl/post-composite.js +461 -0
  89. package/src/shaders-tsl/sky.js +175 -0
  90. package/src/shaders-tsl/tree-leaf.js +264 -0
  91. package/src/shaders-tsl/water-breaker.js +423 -0
  92. package/src/shaders-tsl/water-kelp.js +171 -0
  93. package/src/shaders-tsl/water-rain.js +107 -0
  94. package/src/shaders-tsl/water-simulation.js +140 -0
  95. package/src/shaders-tsl/water-splash.js +298 -0
  96. package/src/shaders-tsl/water.js +509 -0
  97. package/src/sky/index.js +2 -0
  98. package/src/sky/stylizedSky.js +341 -0
  99. package/src/toon/characterRenderPasses.js +646 -0
  100. package/src/toon/index.js +4 -0
  101. package/src/toon/settings/alphaSettings.js +170 -0
  102. package/src/toon/settings/averageShadowSettings.js +181 -0
  103. package/src/toon/settings/baseTextureSettings.js +133 -0
  104. package/src/toon/settings/celShadeSettings.js +96 -0
  105. package/src/toon/settings/contactShadowSettings.js +114 -0
  106. package/src/toon/settings/eyeHighlightSettings.js +187 -0
  107. package/src/toon/settings/faceLightingSettings.js +135 -0
  108. package/src/toon/settings/furSettings.js +112 -0
  109. package/src/toon/settings/glitterSettings.js +102 -0
  110. package/src/toon/settings/hairHighlightSettings.js +325 -0
  111. package/src/toon/settings/indirectLightSettings.js +244 -0
  112. package/src/toon/settings/localLightSettings.js +176 -0
  113. package/src/toon/settings/materialMapSettings.js +299 -0
  114. package/src/toon/settings/outlineSettings.js +263 -0
  115. package/src/toon/settings/perspectiveRemovalSettings.js +60 -0
  116. package/src/toon/settings/rimLightSettings.js +268 -0
  117. package/src/toon/settings/sceneShadowSettings.js +147 -0
  118. package/src/toon/settings/selfShadowSettings.js +221 -0
  119. package/src/toon/settings/shadowColorSettings.js +238 -0
  120. package/src/toon/settings/skinToneSettings.js +150 -0
  121. package/src/toon/settings/specularSettings.js +314 -0
  122. package/src/toon/settings/stickerSettings.js +102 -0
  123. package/src/toon/toonMaterialAdapter.js +2235 -0
  124. package/src/toon/toonSettings.js +860 -0
  125. package/src/vegetation/flowerSpecies.js +260 -0
  126. package/src/vegetation/index.js +10 -0
  127. package/src/vegetation/stylizedBush.js +136 -0
  128. package/src/vegetation/stylizedFlower.js +213 -0
  129. package/src/vegetation/stylizedFlowers.js +297 -0
  130. package/src/vegetation/stylizedGrass.js +491 -0
  131. package/src/vegetation/stylizedTree.js +2449 -0
  132. package/src/vegetation/stylizedTreeFoliage.js +691 -0
  133. package/src/vegetation/treeExport.js +300 -0
  134. package/src/vegetation/treeRecipe.js +647 -0
  135. package/src/water/index.js +2 -0
  136. package/src/water/water.js +20 -0
  137. package/src/water/waterBreakerSystem.js +591 -0
  138. package/src/water/waterInteraction.js +193 -0
  139. package/src/water/waterMaterial.js +263 -0
  140. package/src/water/waterRain.js +136 -0
  141. package/src/water/waterRippleSimulation.js +227 -0
  142. package/src/water/waterScenePasses.js +415 -0
  143. package/src/water/waterSettings.js +1138 -0
  144. package/src/water/waterSplashSystem.js +251 -0
  145. package/src/water/waterSurface.js +475 -0
  146. package/src/water/waterVegetation.js +83 -0
@@ -0,0 +1,341 @@
1
+ import * as THREE from 'three';
2
+
3
+ import { createSkyNodeMaterial } from '../shaders-tsl/sky.js';
4
+
5
+ // Procedural stylized sky dome: vertical gradient, sun disc, painterly
6
+ // two-tone clouds, and stars — no texture assets. Designed as the companion
7
+ // backdrop for the stylized water (it appears in the water's planar
8
+ // reflections automatically), but works standalone with any scene.
9
+ //
10
+ // const sky = new StylizedSky({ preset-ish options });
11
+ // scene.add(sky);
12
+ // sky.update(delta, camera); // each frame
13
+ // sky.applySettings({ sunDirection: [..], cloudCoverage: 0.6 });
14
+
15
+ /**
16
+ * Default sky settings. Every value equals the historical hardcoded/
17
+ * constructor default, so `new StylizedSky()` renders identically to
18
+ * previous releases. `radius` is construction-only (dome geometry).
19
+ */
20
+ export const DEFAULT_SKY_SETTINGS = Object.freeze({
21
+ radius: 100,
22
+ zenithColor: [0.28, 0.56, 0.92],
23
+ horizonColor: [0.78, 0.92, 1.0],
24
+ groundColor: [0.42, 0.48, 0.55],
25
+ sunDirection: [0.35, 0.8, 0.45],
26
+ sunColor: [1.0, 0.95, 0.82],
27
+ sunSize: 0.026,
28
+ sunGlowStrength: 1.0,
29
+ horizonScattering: 0.5,
30
+ cloudCoverage: 0.42,
31
+ cloudScale: 1.6,
32
+ cloudSpeed: 1.0,
33
+ cloudColor: [1.0, 1.0, 1.0],
34
+ cloudShadeColor: [0.68, 0.78, 0.92],
35
+ starsStrength: 0.0,
36
+ });
37
+
38
+ function finiteNumber(value, fallback) {
39
+ const number = Number(value);
40
+ return Number.isFinite(number) ? number : fallback;
41
+ }
42
+
43
+ function colorArray(value, fallback) {
44
+ if (value?.isColor) return [value.r, value.g, value.b];
45
+ if (Array.isArray(value) && value.length >= 3) {
46
+ const next = value.slice(0, 3).map(Number);
47
+ return next.every(Number.isFinite) ? next : fallback.slice();
48
+ }
49
+ if (typeof value === 'number' || typeof value === 'string') {
50
+ try {
51
+ const color = new THREE.Color(value);
52
+ return [color.r, color.g, color.b];
53
+ } catch {
54
+ return fallback.slice();
55
+ }
56
+ }
57
+ return fallback.slice();
58
+ }
59
+
60
+ function vector3Array(value, fallback) {
61
+ if (value?.isVector3) return [value.x, value.y, value.z];
62
+ if (Array.isArray(value) && value.length >= 3) {
63
+ const next = value.slice(0, 3).map(Number);
64
+ return next.every(Number.isFinite) ? next : fallback.slice();
65
+ }
66
+ return fallback.slice();
67
+ }
68
+
69
+ /**
70
+ * Validates and merges partial sky options over {@link DEFAULT_SKY_SETTINGS}.
71
+ * Unknown keys are ignored; malformed values fall back to their defaults.
72
+ * `createSkySettings()` deep-equals the defaults object.
73
+ *
74
+ * @param {Object} [options] Partial settings (legacy constructor options are
75
+ * the same flat shape, so they work unchanged).
76
+ * @returns {Object} A complete, plain sky settings object.
77
+ */
78
+ export function createSkySettings(options = {}) {
79
+ const source = options && typeof options === 'object' ? options : {};
80
+ const base = DEFAULT_SKY_SETTINGS;
81
+ return {
82
+ radius: Math.max(finiteNumber(source.radius, base.radius), 0.1),
83
+ zenithColor: colorArray(source.zenithColor, base.zenithColor),
84
+ horizonColor: colorArray(source.horizonColor, base.horizonColor),
85
+ groundColor: colorArray(source.groundColor, base.groundColor),
86
+ sunDirection: vector3Array(source.sunDirection, base.sunDirection),
87
+ sunColor: colorArray(source.sunColor, base.sunColor),
88
+ sunSize: finiteNumber(source.sunSize, base.sunSize),
89
+ sunGlowStrength: finiteNumber(source.sunGlowStrength, base.sunGlowStrength),
90
+ horizonScattering: finiteNumber(source.horizonScattering, base.horizonScattering),
91
+ cloudCoverage: finiteNumber(source.cloudCoverage, base.cloudCoverage),
92
+ cloudScale: finiteNumber(source.cloudScale, base.cloudScale),
93
+ cloudSpeed: finiteNumber(source.cloudSpeed, base.cloudSpeed),
94
+ cloudColor: colorArray(source.cloudColor, base.cloudColor),
95
+ cloudShadeColor: colorArray(source.cloudShadeColor, base.cloudShadeColor),
96
+ starsStrength: finiteNumber(source.starsStrength, base.starsStrength),
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Panel group metadata for the sky settings, in display order. Settings
102
+ * themselves stay flat; each group lists which flat keys it owns via
103
+ * {@link SKY_SETTING_FIELD_SCHEMA}.
104
+ */
105
+ export const SKY_SETTING_GROUPS = Object.freeze([
106
+ Object.freeze({
107
+ description: 'Sky dome geometry. Construction-only.',
108
+ id: 'dome',
109
+ label: 'Dome',
110
+ }),
111
+ Object.freeze({
112
+ description: 'Vertical zenith-to-horizon-to-ground gradient and horizon scattering.',
113
+ id: 'gradient',
114
+ label: 'Gradient',
115
+ }),
116
+ Object.freeze({
117
+ description: 'Sun disc position, size, tint, and glow halo.',
118
+ id: 'sun',
119
+ label: 'Sun',
120
+ }),
121
+ Object.freeze({
122
+ description: 'Painterly two-tone procedural clouds.',
123
+ id: 'clouds',
124
+ label: 'Clouds',
125
+ }),
126
+ Object.freeze({
127
+ description: 'Procedural star field for night skies.',
128
+ id: 'stars',
129
+ label: 'Stars',
130
+ }),
131
+ ]);
132
+
133
+ const SKY_FIELD_DEFINITIONS = Object.freeze({
134
+ dome: {
135
+ radius: {
136
+ description: 'Sphere radius of the sky dome in meters. Construction-only: baked into the dome geometry; applySettings stores but does not rebuild it.',
137
+ label: 'Radius',
138
+ range: { max: 1000, min: 10, step: 1 },
139
+ type: 'number',
140
+ },
141
+ },
142
+ gradient: {
143
+ zenithColor: {
144
+ description: 'Sky color straight up at the top of the dome.',
145
+ label: 'Zenith Color',
146
+ type: 'color',
147
+ },
148
+ horizonColor: {
149
+ description: 'Sky color at the horizon band.',
150
+ label: 'Horizon Color',
151
+ type: 'color',
152
+ },
153
+ groundColor: {
154
+ description: 'Dome color below the horizon.',
155
+ label: 'Ground Color',
156
+ type: 'color',
157
+ },
158
+ horizonScattering: {
159
+ description: 'How far the bright horizon band bleeds up into the sky.',
160
+ label: 'Horizon Scattering',
161
+ range: { max: 1, min: 0, step: 0.01 },
162
+ type: 'number',
163
+ },
164
+ },
165
+ sun: {
166
+ sunDirection: {
167
+ description: 'World-space direction toward the sun (normalized on apply). Match your main directional light.',
168
+ label: 'Sun Direction',
169
+ type: 'vector3',
170
+ },
171
+ sunColor: {
172
+ description: 'Tint of the sun disc and its glow.',
173
+ label: 'Sun Color',
174
+ type: 'color',
175
+ },
176
+ sunSize: {
177
+ description: 'Angular size of the sun disc.',
178
+ label: 'Sun Size',
179
+ range: { max: 0.2, min: 0, step: 0.001 },
180
+ type: 'number',
181
+ },
182
+ sunGlowStrength: {
183
+ description: 'Intensity of the soft glow halo around the sun disc.',
184
+ label: 'Sun Glow Strength',
185
+ range: { max: 4, min: 0, step: 0.01 },
186
+ type: 'number',
187
+ },
188
+ },
189
+ clouds: {
190
+ cloudCoverage: {
191
+ description: 'Fraction of the sky filled by clouds. 0 clears the sky.',
192
+ label: 'Cloud Coverage',
193
+ range: { max: 1, min: 0, step: 0.01 },
194
+ type: 'number',
195
+ },
196
+ cloudScale: {
197
+ description: 'Noise scale of the cloud shapes; higher gives smaller, busier clouds.',
198
+ label: 'Cloud Scale',
199
+ range: { max: 6, min: 0.1, step: 0.01 },
200
+ type: 'number',
201
+ },
202
+ cloudSpeed: {
203
+ description: 'How fast clouds drift across the dome.',
204
+ label: 'Cloud Speed',
205
+ range: { max: 4, min: 0, step: 0.01 },
206
+ type: 'number',
207
+ },
208
+ cloudColor: {
209
+ description: 'Lit tone of the two-tone painterly clouds.',
210
+ label: 'Cloud Color',
211
+ type: 'color',
212
+ },
213
+ cloudShadeColor: {
214
+ description: 'Shaded underside tone of the two-tone painterly clouds.',
215
+ label: 'Cloud Shade Color',
216
+ type: 'color',
217
+ },
218
+ },
219
+ stars: {
220
+ starsStrength: {
221
+ description: 'Brightness of the procedural star field. 0 (default) hides stars for daytime skies.',
222
+ label: 'Stars Strength',
223
+ range: { max: 2, min: 0, step: 0.01 },
224
+ type: 'number',
225
+ },
226
+ },
227
+ });
228
+
229
+ function createSkyFieldMetadata(group, key, field) {
230
+ const defaultValue = DEFAULT_SKY_SETTINGS[key];
231
+ return Object.freeze({
232
+ defaultValue: Array.isArray(defaultValue) ? [...defaultValue] : defaultValue,
233
+ description: field.description,
234
+ group: group.id,
235
+ id: `${group.id}.${key}`,
236
+ key,
237
+ label: field.label,
238
+ optionLabels: field.optionLabels ?? null,
239
+ options: field.options ?? null,
240
+ range: field.range ?? null,
241
+ serializable: field.serializable ?? true,
242
+ type: field.type,
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Field metadata (id/group/key/label/description/type/range/defaultValue/
248
+ * serializable) per settings group, in the shape consumed by
249
+ * `createSettingsPanel`. Keys are the flat {@link DEFAULT_SKY_SETTINGS} keys.
250
+ */
251
+ export const SKY_SETTING_FIELD_SCHEMA = Object.freeze(
252
+ Object.fromEntries(
253
+ SKY_SETTING_GROUPS.map((group) => [
254
+ group.id,
255
+ Object.freeze(
256
+ Object.fromEntries(
257
+ Object.entries(SKY_FIELD_DEFINITIONS[group.id] ?? {})
258
+ .map(([key, field]) => [key, createSkyFieldMetadata(group, key, field)]),
259
+ ),
260
+ ),
261
+ ]),
262
+ ),
263
+ );
264
+
265
+ function setSrgbColorUniform(uniform, rgb) {
266
+ uniform.value.setRGB(rgb[0], rgb[1], rgb[2], THREE.SRGBColorSpace);
267
+ }
268
+
269
+ export function applySkySettingsToMaterial(material, options = {}) {
270
+ // Both backends expose `.uniforms` under the same names: ShaderMaterial
271
+ // natively, the TSL factory via same-name UniformNodes (`.value` on both).
272
+ const uniforms = material?.uniforms;
273
+ if (!uniforms) return material;
274
+ const settings = createSkySettings(options);
275
+ setSrgbColorUniform(uniforms.uZenithColor, settings.zenithColor);
276
+ setSrgbColorUniform(uniforms.uHorizonColor, settings.horizonColor);
277
+ setSrgbColorUniform(uniforms.uGroundColor, settings.groundColor);
278
+ uniforms.uSunDirection.value.set(...settings.sunDirection).normalize();
279
+ setSrgbColorUniform(uniforms.uSunColor, settings.sunColor);
280
+ uniforms.uSunSize.value = settings.sunSize;
281
+ uniforms.uSunGlowStrength.value = settings.sunGlowStrength;
282
+ uniforms.uHorizonScattering.value = settings.horizonScattering;
283
+ uniforms.uCloudCoverage.value = settings.cloudCoverage;
284
+ uniforms.uCloudScale.value = settings.cloudScale;
285
+ uniforms.uCloudSpeed.value = settings.cloudSpeed;
286
+ setSrgbColorUniform(uniforms.uCloudColor, settings.cloudColor);
287
+ setSrgbColorUniform(uniforms.uCloudShadeColor, settings.cloudShadeColor);
288
+ uniforms.uStarsStrength.value = settings.starsStrength;
289
+ material.userData.skySettings = settings;
290
+ return material;
291
+ }
292
+
293
+ export function createSkyMaterial(options = {}) {
294
+ return applySkySettingsToMaterial(createSkyNodeMaterial(), options);
295
+ }
296
+
297
+ export class StylizedSky extends THREE.Mesh {
298
+ /**
299
+ * @param {Object} [options] Flat sky settings (see
300
+ * {@link DEFAULT_SKY_SETTINGS}); legacy individual constructor options
301
+ * are the same keys, so existing callers keep working unchanged.
302
+ */
303
+ constructor(options = {}) {
304
+ const settings = createSkySettings(options);
305
+ super(new THREE.SphereGeometry(settings.radius, 48, 24), createSkyMaterial(settings));
306
+ this.name = 'StylizedSky';
307
+ this.frustumCulled = false;
308
+ this.renderOrder = -100;
309
+ }
310
+
311
+ get settings() {
312
+ return this.material.userData.skySettings;
313
+ }
314
+
315
+ /**
316
+ * Runtime re-tune: merges `options` into the current settings and pushes
317
+ * every value into the material uniforms. `radius` is construction-only
318
+ * (baked into the dome geometry); a new value is stored but the dome is
319
+ * not rebuilt.
320
+ *
321
+ * @param {Object} [options] Partial flat settings, same keys as
322
+ * {@link DEFAULT_SKY_SETTINGS}.
323
+ * @returns {Object} The updated settings object.
324
+ */
325
+ applySettings(options = {}) {
326
+ applySkySettingsToMaterial(this.material, { ...this.settings, ...options });
327
+ return this.settings;
328
+ }
329
+
330
+ // Advances cloud/star animation and keeps the dome centered on the camera.
331
+ update(delta, camera) {
332
+ this.material.uniforms.uTime.value += Math.min(Math.max(delta ?? 0.016, 0), 0.1);
333
+ if (camera) camera.getWorldPosition(this.position);
334
+ return this;
335
+ }
336
+
337
+ dispose() {
338
+ this.geometry.dispose();
339
+ this.material.dispose();
340
+ }
341
+ }