@call-me-sensei/toonlab 0.2.0 → 0.3.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.
- package/AGENTS.md +127 -4
- package/ATTRIBUTION.md +41 -3
- package/README.md +234 -34
- package/docs/characters.md +144 -0
- package/docs/debug-panel.md +126 -0
- package/docs/docs.css +589 -0
- package/docs/environment.md +186 -0
- package/docs/getting-started.md +180 -0
- package/docs/index.html +14 -0
- package/docs/lab-architecture.md +100 -0
- package/docs/lighting.md +825 -0
- package/docs/main.jsx +739 -0
- package/docs/mcp.md +97 -0
- package/docs/post-processing.md +98 -0
- package/docs/settings-reference.md +1878 -0
- package/docs/shader-constants.md +77 -0
- package/docs/sky.md +182 -0
- package/docs/style-labs.md +309 -0
- package/docs/texture-lab.md +135 -0
- package/docs/toon-shading.md +183 -0
- package/docs/tsl-conventions.md +167 -0
- package/docs/vegetation-sky.md +275 -0
- package/docs/water.md +430 -0
- package/docs/weather.md +200 -0
- package/docs/world-scale.md +111 -0
- package/mcp/server.mjs +610 -0
- package/mcp/style-lab-tools.mjs +371 -0
- package/mcp/vite-plugin.mjs +174 -0
- package/mcp/workspace.mjs +397 -0
- package/package.json +64 -5
- package/src/ambientfx/INTEGRATION.md +164 -0
- package/src/ambientfx/ambientFxPresets.js +83 -0
- package/src/ambientfx/ambientFxSettings.js +368 -0
- package/src/ambientfx/emitters.js +169 -0
- package/src/ambientfx/index.js +5 -0
- package/src/ambientfx/particleBackbone.js +493 -0
- package/src/ambientfx/stylizedAmbientFx.js +450 -0
- package/src/assetlib/ambientcg.js +117 -0
- package/src/assetlib/assetRef.js +91 -0
- package/src/assetlib/importedEntry.js +40 -0
- package/src/assetlib/index.js +23 -0
- package/src/assetlib/kaykit.js +192 -0
- package/src/assetlib/kaykitStaticIndex.js +700 -0
- package/src/assetlib/loadImported.js +143 -0
- package/src/assetlib/opensource3d.js +113 -0
- package/src/assetlib/polyhaven.js +182 -0
- package/src/assetlib/polypizza.js +115 -0
- package/src/assetlib/smithsonian.js +214 -0
- package/src/assetlib/sources.js +279 -0
- package/src/assetlib/zip.js +58 -0
- package/src/biome/biomeGenerator.js +385 -0
- package/src/biome/biomeRuntime.js +299 -0
- package/src/biome/index.js +2 -0
- package/src/buildinggen/buildingAsset.js +44 -0
- package/src/buildinggen/buildingGrammar.js +311 -0
- package/src/buildinggen/buildingMesh.js +451 -0
- package/src/buildinggen/buildingPresets.js +46 -0
- package/src/buildinggen/buildingRecipe.js +100 -0
- package/src/buildinggen/buildingSettings.js +238 -0
- package/src/buildinggen/index.js +6 -0
- package/src/camera/cameraDirector.js +157 -0
- package/src/camera/cameraGenerator.js +367 -0
- package/src/camera/cameraRig.js +570 -0
- package/src/camera/cameraSettings.js +236 -0
- package/src/camera/index.js +7 -0
- package/src/catalog/builtinEntries.js +245 -0
- package/src/catalog/catalog.js +210 -0
- package/src/catalog/index.js +3 -0
- package/src/catalog/manifest.js +84 -0
- package/src/core/generation.js +529 -0
- package/src/environment/environmentRigs.js +21 -1
- package/src/environment/environmentSettings.js +4 -0
- package/src/environment/environmentSunShadowPass.js +8 -0
- package/src/fauna/INTEGRATION.md +174 -0
- package/src/fauna/boids.js +861 -0
- package/src/fauna/faunaBodies.js +492 -0
- package/src/fauna/faunaPresets.js +52 -0
- package/src/fauna/faunaSettings.js +525 -0
- package/src/fauna/index.js +5 -0
- package/src/fauna/stylizedFauna.js +395 -0
- package/src/game-feel/gameFeelGenerator.js +402 -0
- package/src/game-feel/gameFeelRuntime.js +549 -0
- package/src/game-feel/index.js +2 -0
- package/src/index.js +17 -6
- package/src/lighting/colorIntensity.js +177 -0
- package/src/lighting/index.js +161 -0
- package/src/lighting/lightDescriptors.js +249 -0
- package/src/lighting/lightingCapabilities.js +79 -0
- package/src/lighting/lightingDocuments.js +247 -0
- package/src/lighting/lightingFixtures.js +446 -0
- package/src/lighting/lightingGenerator.js +449 -0
- package/src/lighting/lightingPresets.js +319 -0
- package/src/lighting/lightingRuntime.js +723 -0
- package/src/lighting/lightingStyle.js +386 -0
- package/src/lighting/lightingSystem.js +774 -0
- package/src/lighting/unrealExport.js +186 -0
- package/src/lighting/utils.js +87 -0
- package/src/motion/index.js +5 -0
- package/src/motion/motionClip.js +441 -0
- package/src/motion/motionController.js +628 -0
- package/src/motion/motionDocuments.js +225 -0
- package/src/motion/motionGraph.js +307 -0
- package/src/motion/motionSettings.js +222 -0
- package/src/pathgen/index.js +7 -0
- package/src/pathgen/pathBridge.js +232 -0
- package/src/pathgen/pathPresets.js +35 -0
- package/src/pathgen/pathRibbon.js +410 -0
- package/src/pathgen/pathRouter.js +380 -0
- package/src/pathgen/pathSettings.js +335 -0
- package/src/pathgen/pathTextures.js +123 -0
- package/src/pathgen/stylizedPaths.js +453 -0
- package/src/post/index.js +1 -0
- package/src/post/postGenerator.js +177 -0
- package/src/post/postProcessing.js +41 -0
- package/src/propgen/generatorsWave1.js +379 -0
- package/src/propgen/generatorsWave2.js +462 -0
- package/src/propgen/index.js +5 -0
- package/src/propgen/propAsset.js +323 -0
- package/src/propgen/propParts.js +170 -0
- package/src/propgen/propPlacement.js +459 -0
- package/src/propgen/propPresets.js +82 -0
- package/src/propgen/propSettings.js +395 -0
- package/src/shaders-tsl/chunks/projected-water-caustics.js +242 -0
- package/src/shaders-tsl/chunks/vegetation-style.js +360 -0
- package/src/shaders-tsl/chunks/water-shore-state.js +31 -0
- package/src/shaders-tsl/chunks/water-waves.js +90 -11
- package/src/shaders-tsl/environment.js +15 -1
- package/src/shaders-tsl/flower.js +279 -30
- package/src/shaders-tsl/grass.js +60 -33
- package/src/shaders-tsl/sky.js +125 -31
- package/src/shaders-tsl/tree-leaf.js +61 -25
- package/src/shaders-tsl/water-breaker.js +7 -4
- package/src/shaders-tsl/water-shore-state-simulation.js +523 -0
- package/src/shaders-tsl/water.js +439 -49
- package/src/shaders-tsl/woody-surface.js +154 -0
- package/src/sky/sceneOverrideLayers.js +10 -0
- package/src/sky/skyQuality.js +26 -0
- package/src/sky/stylizedSky.js +753 -45
- package/src/soundscape/index.js +4 -0
- package/src/soundscape/soundscapeGenerator.js +179 -0
- package/src/soundscape/soundscapeRuntime.js +806 -0
- package/src/soundscape/soundscapeSettings.js +292 -0
- package/src/styles/index.js +13 -0
- package/src/styles/styleBundle.js +325 -0
- package/src/stylizedTerrain.js +32 -2
- package/src/stylizedWorld.js +423 -20
- package/src/texgen/evaluateTexture.js +675 -0
- package/src/texgen/index.js +60 -0
- package/src/texgen/noise2.js +210 -0
- package/src/texgen/textureAi.js +436 -0
- package/src/texgen/textureGenerators.js +516 -0
- package/src/texgen/texturePresets.js +490 -0
- package/src/texgen/textureSettings.js +342 -0
- package/src/texgen/textureThree.js +59 -0
- package/src/vegetation/flowerSpecies.js +15 -3
- package/src/vegetation/grassPalettes.js +153 -0
- package/src/vegetation/index.js +6 -0
- package/src/vegetation/stylizedBush.js +2 -0
- package/src/vegetation/stylizedFlower.js +82 -0
- package/src/vegetation/stylizedFlowers.js +48 -7
- package/src/vegetation/stylizedForest.js +29 -1
- package/src/vegetation/stylizedGrass.js +291 -56
- package/src/vegetation/stylizedTree.js +38 -2
- package/src/vegetation/stylizedTreeFoliage.js +2 -1
- package/src/vegetation/vegetationShaders.js +1110 -0
- package/src/vfxgen/INTEGRATION.md +145 -0
- package/src/vfxgen/core/burstBackbone.js +380 -0
- package/src/vfxgen/core/projectileCore.js +92 -0
- package/src/vfxgen/core/spriteShapes.js +98 -0
- package/src/vfxgen/core/trailRibbon.js +272 -0
- package/src/vfxgen/core/vfxRandom.js +29 -0
- package/src/vfxgen/effects/emitHelpers.js +37 -0
- package/src/vfxgen/effects/magicEffects.js +162 -0
- package/src/vfxgen/effects/movementEffects.js +87 -0
- package/src/vfxgen/effects/weaponEffects.js +118 -0
- package/src/vfxgen/index.js +18 -0
- package/src/vfxgen/moves/moveController.js +146 -0
- package/src/vfxgen/moves/moveLibrary.js +335 -0
- package/src/vfxgen/vfxPresets.js +98 -0
- package/src/vfxgen/vfxSettings.js +384 -0
- package/src/vfxgen/vfxSystem.js +449 -0
- package/src/vfxgen/weapons/stylizedWeapons.js +137 -0
- package/src/villagegen/index.js +4 -0
- package/src/villagegen/stylizedVillage.js +490 -0
- package/src/villagegen/villageArchetypes.js +160 -0
- package/src/villagegen/villageNames.js +40 -0
- package/src/villagegen/villageSites.js +105 -0
- package/src/water/sceneOverrideLayers.js +23 -0
- package/src/water/water.js +5 -0
- package/src/water/waterBreakerSystem.js +15 -1
- package/src/water/waterCurrentField.js +447 -0
- package/src/water/waterMaterial.js +12 -0
- package/src/water/waterNearshorePhase.js +320 -0
- package/src/water/waterScenePasses.js +83 -30
- package/src/water/waterSettings.js +325 -13
- package/src/water/waterShoreMaterial.js +322 -0
- package/src/water/waterShoreStateField.js +605 -0
- package/src/water/waterSurface.js +797 -28
- package/src/weather/index.js +6 -0
- package/src/weather/weatherPrecipitation.js +221 -0
- package/src/weather/weatherPresets.js +258 -0
- package/src/weather/weatherSettings.js +269 -0
- package/src/weather/weatherSystem.js +871 -0
- package/src/worldMinimap.js +62 -0
- package/src/worldPresets.js +4 -1
package/src/shaders-tsl/sky.js
CHANGED
|
@@ -33,30 +33,63 @@ import {
|
|
|
33
33
|
step,
|
|
34
34
|
uniform,
|
|
35
35
|
vec2,
|
|
36
|
-
vec3,
|
|
37
36
|
vec4,
|
|
38
37
|
} from 'three/tsl';
|
|
39
38
|
import { MeshBasicNodeMaterial } from 'three/webgpu';
|
|
40
39
|
|
|
41
40
|
import { waterFbm, waterHash12, waterToonStep, waterVoronoi2 } from './chunks/water-common.js';
|
|
41
|
+
import { resolveSkyQuality } from '../sky/skyQuality.js';
|
|
42
42
|
|
|
43
|
-
export function createSkyNodeMaterial() {
|
|
43
|
+
export function createSkyNodeMaterial({ quality = 'high' } = {}) {
|
|
44
|
+
const qualitySettings = resolveSkyQuality(quality);
|
|
44
45
|
const uniforms = {
|
|
45
46
|
uCloudColor: uniform(new THREE.Color()),
|
|
46
47
|
uCloudCoverage: uniform(0),
|
|
48
|
+
uCloudDirection: uniform(new THREE.Vector2(1, 0.2857142857)),
|
|
49
|
+
uCloudEdgeOpacity: uniform(0),
|
|
50
|
+
uCloudHorizonFade: uniform(0),
|
|
51
|
+
uCloudLightOffset: uniform(0),
|
|
52
|
+
uCloudOpacity: uniform(0),
|
|
53
|
+
uCloudProjection: uniform(0),
|
|
47
54
|
uCloudScale: uniform(0),
|
|
55
|
+
uCloudSeed: uniform(0),
|
|
48
56
|
uCloudShadeColor: uniform(new THREE.Color()),
|
|
57
|
+
uCloudShadeSoftness: uniform(0),
|
|
58
|
+
uCloudShadeStrength: uniform(0),
|
|
59
|
+
uCloudShadeThreshold: uniform(0),
|
|
60
|
+
uCloudSilverLiningStrength: uniform(0),
|
|
61
|
+
uCloudSoftness: uniform(0),
|
|
49
62
|
uCloudSpeed: uniform(0),
|
|
63
|
+
uCloudSunPower: uniform(0),
|
|
50
64
|
uGroundColor: uniform(new THREE.Color()),
|
|
65
|
+
uGroundExponent: uniform(0),
|
|
66
|
+
uHorizonBandSize: uniform(0),
|
|
51
67
|
uHorizonColor: uniform(new THREE.Color()),
|
|
52
68
|
uHorizonScattering: uniform(0),
|
|
69
|
+
uHorizonSunPower: uniform(0),
|
|
70
|
+
uStarsColor: uniform(new THREE.Color()),
|
|
71
|
+
uStarsDensity: uniform(0),
|
|
72
|
+
uStarsHorizonFade: uniform(0),
|
|
73
|
+
uStarsScale: uniform(0),
|
|
74
|
+
uStarsSeed: uniform(0),
|
|
75
|
+
uStarsSize: uniform(0),
|
|
53
76
|
uStarsStrength: uniform(0),
|
|
77
|
+
uStarsTwinkleSpeed: uniform(0),
|
|
78
|
+
uStarsTwinkleStrength: uniform(0),
|
|
79
|
+
uSunCloudOcclusionStrength: uniform(0),
|
|
54
80
|
uSunColor: uniform(new THREE.Color()),
|
|
81
|
+
uSunDiscSoftness: uniform(0),
|
|
82
|
+
uSunDiscIntensity: uniform(0),
|
|
55
83
|
uSunDirection: uniform(new THREE.Vector3(0, 1, 0)),
|
|
84
|
+
uSunGlowBroadStrength: uniform(0),
|
|
85
|
+
uSunGlowCoreSharpness: uniform(0),
|
|
86
|
+
uSunGlowCoreStrength: uniform(0),
|
|
87
|
+
uSunGlowSpread: uniform(0),
|
|
56
88
|
uSunGlowStrength: uniform(0),
|
|
57
89
|
uSunSize: uniform(0),
|
|
58
90
|
uTime: uniform(0),
|
|
59
91
|
uZenithColor: uniform(new THREE.Color()),
|
|
92
|
+
uZenithExponent: uniform(0),
|
|
60
93
|
};
|
|
61
94
|
|
|
62
95
|
const material = new MeshBasicNodeMaterial({
|
|
@@ -66,6 +99,7 @@ export function createSkyNodeMaterial() {
|
|
|
66
99
|
material.name = 'StylizedSky';
|
|
67
100
|
material.fog = false;
|
|
68
101
|
material.lights = false;
|
|
102
|
+
material.userData.skyQuality = { ...qualitySettings };
|
|
69
103
|
|
|
70
104
|
// Vertex stage: dome pinned to the far plane regardless of sphere radius,
|
|
71
105
|
// so it never clips scene geometry and works inside reflection passes.
|
|
@@ -85,30 +119,52 @@ export function createSkyNodeMaterial() {
|
|
|
85
119
|
const up = direction.y.toVar();
|
|
86
120
|
|
|
87
121
|
// Base vertical gradient with a mirrored ground fade below the horizon.
|
|
88
|
-
const zenithMix = pow(clamp(up, 0.0, 1.0),
|
|
122
|
+
const zenithMix = pow(clamp(up, 0.0, 1.0), uniforms.uZenithExponent);
|
|
89
123
|
const color = select(
|
|
90
124
|
up.greaterThanEqual(0.0),
|
|
91
125
|
mix(uniforms.uHorizonColor, uniforms.uZenithColor, zenithMix),
|
|
92
|
-
mix(
|
|
126
|
+
mix(
|
|
127
|
+
uniforms.uHorizonColor,
|
|
128
|
+
uniforms.uGroundColor,
|
|
129
|
+
pow(clamp(up.negate(), 0.0, 1.0), uniforms.uGroundExponent),
|
|
130
|
+
),
|
|
93
131
|
).toVar();
|
|
94
132
|
|
|
95
133
|
// Sun disc and glow.
|
|
96
134
|
const cosAngle = dot(direction, uniforms.uSunDirection).toVar();
|
|
97
135
|
const angle = acos(clamp(cosAngle, -1.0, 1.0));
|
|
98
|
-
const
|
|
136
|
+
const sunCloudVisibility = smoothstep(0.55, 0.82, uniforms.uCloudCoverage).oneMinus();
|
|
137
|
+
const sunVisibility = mix(1.0, sunCloudVisibility, uniforms.uSunCloudOcclusionStrength);
|
|
138
|
+
const safeSunSize = max(uniforms.uSunSize, 0.00001);
|
|
139
|
+
const sunDisc = smoothstep(
|
|
140
|
+
safeSunSize.mul(uniforms.uSunDiscSoftness.oneMinus()),
|
|
141
|
+
safeSunSize,
|
|
142
|
+
angle,
|
|
143
|
+
)
|
|
99
144
|
.oneMinus()
|
|
100
|
-
.mul(
|
|
101
|
-
|
|
102
|
-
|
|
145
|
+
.mul(sunVisibility)
|
|
146
|
+
.mul(step(0.00001, uniforms.uSunSize));
|
|
147
|
+
const sunGlow = pow(max(cosAngle, 0.0), uniforms.uSunGlowSpread)
|
|
148
|
+
.mul(uniforms.uSunGlowBroadStrength)
|
|
149
|
+
.add(
|
|
150
|
+
pow(max(cosAngle, 0.0), uniforms.uSunGlowCoreSharpness)
|
|
151
|
+
.mul(uniforms.uSunGlowCoreStrength),
|
|
152
|
+
)
|
|
103
153
|
.toVar();
|
|
104
154
|
color.addAssign(
|
|
105
|
-
uniforms.uSunColor.mul(
|
|
155
|
+
uniforms.uSunColor.mul(
|
|
156
|
+
sunDisc.mul(uniforms.uSunDiscIntensity)
|
|
157
|
+
.add(sunGlow.mul(uniforms.uSunGlowStrength)),
|
|
158
|
+
),
|
|
106
159
|
);
|
|
107
160
|
|
|
108
161
|
// Atmospheric scattering hint: a warm wedge along the sun-side horizon
|
|
109
162
|
// that fades with altitude.
|
|
110
|
-
const horizonBand = smoothstep(0.0,
|
|
111
|
-
const sunward = pow(
|
|
163
|
+
const horizonBand = smoothstep(0.0, uniforms.uHorizonBandSize, up.abs()).oneMinus();
|
|
164
|
+
const sunward = pow(
|
|
165
|
+
clamp(cosAngle.mul(0.5).add(0.5), 0.0, 1.0),
|
|
166
|
+
uniforms.uHorizonSunPower,
|
|
167
|
+
);
|
|
112
168
|
color.addAssign(
|
|
113
169
|
uniforms.uSunColor
|
|
114
170
|
.mul(horizonBand)
|
|
@@ -121,23 +177,29 @@ export function createSkyNodeMaterial() {
|
|
|
121
177
|
// The If guard matches the GLSL branch — it also keeps the projected UV
|
|
122
178
|
// division (up + 0.28 crosses zero below the horizon) out of reach.
|
|
123
179
|
If(uniforms.uStarsStrength.greaterThan(0.001).and(up.greaterThan(0.02)), () => {
|
|
124
|
-
const starUv = direction.xz
|
|
180
|
+
const starUv = direction.xz
|
|
181
|
+
.div(up.add(0.28))
|
|
182
|
+
.mul(uniforms.uStarsScale)
|
|
183
|
+
.add(vec2(uniforms.uStarsSeed.mul(1.37), uniforms.uStarsSeed.mul(2.11)));
|
|
125
184
|
const starVoro = waterVoronoi2(starUv);
|
|
126
185
|
const starRandom = waterHash12(starVoro.zw);
|
|
127
|
-
const
|
|
186
|
+
const twinkleWave = uniforms.uTime
|
|
187
|
+
.mul(uniforms.uStarsTwinkleSpeed)
|
|
128
188
|
.mul(starRandom.mul(2.4).add(1.2))
|
|
129
189
|
.add(starRandom.mul(31.0))
|
|
130
|
-
.sin()
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const star = smoothstep(0.0,
|
|
190
|
+
.sin();
|
|
191
|
+
const twinkleAmount = uniforms.uStarsTwinkleStrength.mul(0.5);
|
|
192
|
+
const twinkle = twinkleWave.mul(twinkleAmount).add(float(1.0).sub(twinkleAmount));
|
|
193
|
+
const star = smoothstep(0.0, uniforms.uStarsSize, starVoro.x)
|
|
194
|
+
.oneMinus()
|
|
195
|
+
.mul(step(uniforms.uStarsDensity.oneMinus(), starRandom));
|
|
134
196
|
color.addAssign(
|
|
135
|
-
|
|
197
|
+
uniforms.uStarsColor
|
|
136
198
|
.mul(star)
|
|
137
199
|
.mul(twinkle)
|
|
138
200
|
.mul(uniforms.uStarsStrength)
|
|
139
|
-
.mul(smoothstep(0.03,
|
|
140
|
-
.mul(sunGlow.oneMinus()),
|
|
201
|
+
.mul(smoothstep(0.03, uniforms.uStarsHorizonFade, up))
|
|
202
|
+
.mul(clamp(sunGlow, 0.0, 1.0).oneMinus()),
|
|
141
203
|
);
|
|
142
204
|
});
|
|
143
205
|
|
|
@@ -145,23 +207,55 @@ export function createSkyNodeMaterial() {
|
|
|
145
207
|
// silver lining toward the sun, projected onto a virtual cloud plane.
|
|
146
208
|
If(uniforms.uCloudCoverage.greaterThan(0.001).and(up.greaterThan(0.015)), () => {
|
|
147
209
|
const cloudUv = direction.xz
|
|
148
|
-
.div(up.add(
|
|
210
|
+
.div(up.add(uniforms.uCloudProjection))
|
|
149
211
|
.mul(uniforms.uCloudScale)
|
|
150
|
-
.add(
|
|
212
|
+
.add(
|
|
213
|
+
uniforms.uTime
|
|
214
|
+
.mul(uniforms.uCloudSpeed)
|
|
215
|
+
.mul(uniforms.uCloudDirection)
|
|
216
|
+
.mul(0.0218403297),
|
|
217
|
+
)
|
|
218
|
+
.add(vec2(uniforms.uCloudSeed.mul(1.37), uniforms.uCloudSeed.mul(2.11)))
|
|
151
219
|
.toVar();
|
|
152
|
-
const cloudBase = waterFbm(cloudUv,
|
|
220
|
+
const cloudBase = waterFbm(cloudUv, qualitySettings.cloudOctaves).toVar();
|
|
153
221
|
const threshold = mix(0.74, 0.34, clamp(uniforms.uCloudCoverage, 0.0, 1.0));
|
|
154
|
-
const cloudCore = smoothstep(
|
|
155
|
-
|
|
156
|
-
|
|
222
|
+
const cloudCore = smoothstep(
|
|
223
|
+
threshold.add(uniforms.uCloudSoftness),
|
|
224
|
+
threshold.add(uniforms.uCloudSoftness.mul(2.4)),
|
|
225
|
+
cloudBase,
|
|
226
|
+
);
|
|
227
|
+
const cloudEdge = smoothstep(
|
|
228
|
+
threshold,
|
|
229
|
+
threshold.add(uniforms.uCloudSoftness),
|
|
230
|
+
cloudBase,
|
|
231
|
+
);
|
|
232
|
+
const cloudMask = max(
|
|
233
|
+
cloudCore,
|
|
234
|
+
cloudEdge.mul(uniforms.uCloudEdgeOpacity),
|
|
235
|
+
).mul(uniforms.uCloudOpacity);
|
|
157
236
|
|
|
158
|
-
const litSample = waterFbm(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
237
|
+
const litSample = waterFbm(
|
|
238
|
+
cloudUv.sub(uniforms.uSunDirection.xz.mul(uniforms.uCloudLightOffset)),
|
|
239
|
+
qualitySettings.cloudOctaves,
|
|
240
|
+
);
|
|
241
|
+
const shade = waterToonStep(
|
|
242
|
+
uniforms.uCloudShadeThreshold,
|
|
243
|
+
uniforms.uCloudShadeSoftness,
|
|
244
|
+
cloudBase.sub(litSample),
|
|
245
|
+
);
|
|
246
|
+
const cloudColor = mix(
|
|
247
|
+
uniforms.uCloudColor,
|
|
248
|
+
uniforms.uCloudShadeColor,
|
|
249
|
+
shade.mul(uniforms.uCloudShadeStrength),
|
|
250
|
+
)
|
|
251
|
+
.add(
|
|
252
|
+
uniforms.uSunColor
|
|
253
|
+
.mul(pow(max(cosAngle, 0.0), uniforms.uCloudSunPower))
|
|
254
|
+
.mul(uniforms.uCloudSilverLiningStrength),
|
|
255
|
+
)
|
|
162
256
|
.toVar();
|
|
163
257
|
|
|
164
|
-
const horizonFade = smoothstep(0.015,
|
|
258
|
+
const horizonFade = smoothstep(0.015, uniforms.uCloudHorizonFade, up);
|
|
165
259
|
color.assign(mix(color, cloudColor, cloudMask.mul(horizonFade)));
|
|
166
260
|
});
|
|
167
261
|
|
|
@@ -48,6 +48,13 @@ import { NodeMaterial } from 'three/webgpu';
|
|
|
48
48
|
import { sampleEnvironmentSunShadow } from './chunks/environment-sun-shadow.js';
|
|
49
49
|
import { stylizedCloudShadow } from './chunks/stylized-cloud-shadow.js';
|
|
50
50
|
import { applyFoliageFog, createFoliageFogUniforms } from './chunks/foliage-fog.js';
|
|
51
|
+
import {
|
|
52
|
+
createVegetationStyleUniforms,
|
|
53
|
+
shadeVegetationSurface,
|
|
54
|
+
tagVegetationRole,
|
|
55
|
+
vegetationBand,
|
|
56
|
+
vegetationVisibility,
|
|
57
|
+
} from './chunks/vegetation-style.js';
|
|
51
58
|
|
|
52
59
|
// Shared card-placement vertex logic (color + depth variants). Returns the
|
|
53
60
|
// clip position; assigns the provided varyings when given.
|
|
@@ -101,10 +108,10 @@ function buildLeafVertexNode(u, { vUv, vWorldNormal, vWorldPosition, vTint, vHei
|
|
|
101
108
|
})();
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
export function createTreeLeafNodeMaterial(settings) {
|
|
111
|
+
export function createTreeLeafNodeMaterial(settings, vegetationShader = null) {
|
|
112
|
+
const styleUniforms = createVegetationStyleUniforms(vegetationShader, 'foliageCard');
|
|
105
113
|
const u = {
|
|
106
114
|
uAlphaCutoff: uniform(settings.alphaCutoff ?? 0.5),
|
|
107
|
-
uBacklitStrength: uniform(settings.backlitStrength ?? 0),
|
|
108
115
|
uCloudShadowCoverage: uniform(settings.cloudShadowCoverage ?? 0),
|
|
109
116
|
uCloudShadowScale: uniform(settings.cloudShadowScale ?? 1),
|
|
110
117
|
uCloudShadowStrength: uniform(settings.cloudShadowStrength ?? 0),
|
|
@@ -122,7 +129,12 @@ export function createTreeLeafNodeMaterial(settings) {
|
|
|
122
129
|
uWindSpeed: uniform(settings.windSpeed ?? 1),
|
|
123
130
|
uWindStrength: uniform(settings.windStrength ?? 0.06),
|
|
124
131
|
...createFoliageFogUniforms(),
|
|
132
|
+
...styleUniforms,
|
|
125
133
|
};
|
|
134
|
+
if (!vegetationShader) {
|
|
135
|
+
u.uStyleFoliageBacklitStrength.value = settings.backlitStrength ?? 0;
|
|
136
|
+
}
|
|
137
|
+
u.uBacklitStrength = u.uStyleFoliageBacklitStrength;
|
|
126
138
|
|
|
127
139
|
const material = new NodeMaterial();
|
|
128
140
|
material.name = 'StylizedTreeFoliage';
|
|
@@ -151,41 +163,65 @@ export function createTreeLeafNodeMaterial(settings) {
|
|
|
151
163
|
u.uCloudShadowStrength, u.uCloudShadowCoverage, u.uCloudShadowScale, u.uCloudShadowVelocity,
|
|
152
164
|
);
|
|
153
165
|
const sceneShadow = mix(1.0, sampleEnvironmentSunShadow(vWorldPosition), u.uSceneShadowStrength).toVar();
|
|
154
|
-
const sunVisibility =
|
|
166
|
+
const sunVisibility = vegetationVisibility(
|
|
167
|
+
sceneShadow,
|
|
168
|
+
cloudShadow,
|
|
169
|
+
u.uStyleFoliageSceneShadowResponse,
|
|
170
|
+
u.uStyleFoliageCloudShadowResponse,
|
|
171
|
+
).toVar();
|
|
155
172
|
|
|
156
|
-
const litBand =
|
|
157
|
-
|
|
173
|
+
const litBand = vegetationBand(
|
|
174
|
+
wrap,
|
|
175
|
+
u.uStyleFoliageBandThreshold,
|
|
176
|
+
u.uStyleFoliageBandSoftness,
|
|
177
|
+
).mul(sunVisibility).toVar();
|
|
178
|
+
const crestBand = vegetationBand(
|
|
179
|
+
wrap,
|
|
180
|
+
u.uStyleFoliageCrestThreshold,
|
|
181
|
+
u.uStyleFoliageCrestSoftness,
|
|
182
|
+
).mul(sunVisibility)
|
|
158
183
|
.mul(smoothstep(0.3, 0.8, vHeightT.mul(normal.y.mul(0.5).add(0.5).mul(0.3).add(0.7))));
|
|
159
184
|
|
|
160
185
|
const color = mix(u.uShadowColor, u.uLitColor, litBand).toVar();
|
|
161
186
|
color.assign(mix(color, u.uCrownColor, crestBand));
|
|
162
|
-
color.mulAssign(mix(vec3(1.0), u.uSunColor, litBand.mul(0.35)));
|
|
163
187
|
|
|
164
188
|
// Baked per-leaf luminance + per-card jitter.
|
|
165
|
-
color.mulAssign(sprite.r.mul(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Sky fill + silhouette rim.
|
|
169
|
-
color.addAssign(u.uSkyColor.mul(normal.y.mul(0.5).add(0.5)).mul(litBand.oneMinus()).mul(0.10));
|
|
170
|
-
const viewDirection = normalize(cameraPosition.sub(vWorldPosition));
|
|
171
|
-
const rim = pow(abs(dot(normal, viewDirection)).oneMinus(), 3.0);
|
|
172
|
-
color.addAssign(u.uSkyColor.mul(rim).mul(0.12).mul(vHeightT.mul(0.6).add(0.4)));
|
|
189
|
+
color.mulAssign(sprite.r.mul(u.uStyleFoliageSpriteLuminanceStrength)
|
|
190
|
+
.add(u.uStyleFoliageSpriteLuminanceStrength.mul(0.611111).oneMinus()));
|
|
191
|
+
color.mulAssign(vTint.sub(0.5).mul(u.uStyleFoliageCardVariationStrength).add(1.0));
|
|
173
192
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
u.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
193
|
+
const shaded = shadeVegetationSurface({
|
|
194
|
+
baseColor: color,
|
|
195
|
+
bandSoftness: u.uStyleFoliageBandSoftness,
|
|
196
|
+
bandThreshold: u.uStyleFoliageBandThreshold,
|
|
197
|
+
cloudShadow,
|
|
198
|
+
cloudShadowResponse: u.uStyleFoliageCloudShadowResponse,
|
|
199
|
+
normal,
|
|
200
|
+
sceneShadow,
|
|
201
|
+
sceneShadowResponse: u.uStyleFoliageSceneShadowResponse,
|
|
202
|
+
shadowFloor: 1,
|
|
203
|
+
skyColor: u.uSkyColor,
|
|
204
|
+
sunColor: u.uSunColor,
|
|
205
|
+
sunDirection,
|
|
206
|
+
transmissionMultiplier: u.uStyleFoliageBacklitStrength.div(0.35)
|
|
207
|
+
.mul(sprite.r.mul(0.7).add(0.3)),
|
|
208
|
+
transmissionPower: u.uStyleThinSurfaceTransmissionPower
|
|
209
|
+
.mul(u.uStyleFoliageTransmissionPowerMultiplier),
|
|
210
|
+
u,
|
|
211
|
+
worldPosition: vWorldPosition,
|
|
212
|
+
});
|
|
181
213
|
|
|
182
214
|
// Occluded crowns read clearly darker.
|
|
183
|
-
color.mulAssign(mix(
|
|
215
|
+
shaded.color.mulAssign(mix(
|
|
216
|
+
u.uStyleFoliageCrownOcclusionStrength.oneMinus(),
|
|
217
|
+
1.0,
|
|
218
|
+
sceneShadow,
|
|
219
|
+
));
|
|
184
220
|
|
|
185
221
|
// Manual linear scene fog on the true billboarded depth (see foliage-fog).
|
|
186
|
-
color.assign(applyFoliageFog(color, vViewZ, u));
|
|
222
|
+
shaded.color.assign(applyFoliageFog(shaded.color, vViewZ, u));
|
|
187
223
|
|
|
188
|
-
return vec4(color, 1.0);
|
|
224
|
+
return vec4(shaded.color, 1.0);
|
|
189
225
|
})();
|
|
190
226
|
|
|
191
227
|
material.uniforms = u;
|
|
@@ -260,5 +296,5 @@ export function createTreeLeafNodeMaterial(settings) {
|
|
|
260
296
|
return depthMaterial;
|
|
261
297
|
};
|
|
262
298
|
|
|
263
|
-
return material;
|
|
299
|
+
return tagVegetationRole(material, 'foliageCard', 'cutout');
|
|
264
300
|
}
|
|
@@ -257,7 +257,10 @@ export function createWaterBreakerNodeMaterial({
|
|
|
257
257
|
// --- Shell shaping ----------------------------------------------------
|
|
258
258
|
const amount = clamp(u.uBreakerAmount, 0.0, 1.0).toVar();
|
|
259
259
|
const capDepth = min(lineDepth, localDepth);
|
|
260
|
-
|
|
260
|
+
// Crest elevation is roughly half the depth-limited wave height. Using
|
|
261
|
+
// 0.9*d here treated the entire breaker height as elevation above rest
|
|
262
|
+
// water and made Ocean-on-Beach shells hover like layered ice shelves.
|
|
263
|
+
const breakHeight = capDepth.mul(0.48).mul(u.uBreakerScale).mul(amount).mul(endFade).mul(setEnvelope).toVar();
|
|
261
264
|
const H = breakHeight.mul(mix(0.12, 1.0, pulse)).mul(post.mul(0.55).oneMinus()).toVar();
|
|
262
265
|
const R = H.mul(0.52).toVar();
|
|
263
266
|
|
|
@@ -386,10 +389,10 @@ export function createWaterBreakerNodeMaterial({
|
|
|
386
389
|
const faceNoise = waterFbm(
|
|
387
390
|
vec2(vAlong.mul(1.7), vProfile.mul(4.0).sub(u.uTime.mul(1.6))).mul(noiseScale), 3,
|
|
388
391
|
).toVar();
|
|
389
|
-
const lipFoam = smoothstep(faceNoise.mul(-0.
|
|
390
|
-
.mul(vPulse).mul(1.
|
|
392
|
+
const lipFoam = smoothstep(faceNoise.mul(-0.08).add(0.82), 0.96, vProfile.add(faceNoise.mul(0.04)))
|
|
393
|
+
.mul(vPulse).mul(1.1).toVar();
|
|
391
394
|
const streaks = smoothstep(0.62, 0.85, faceNoise)
|
|
392
|
-
.mul(smoothstep(0.
|
|
395
|
+
.mul(smoothstep(0.38, 0.76, vProfile)).mul(vPulse).mul(0.45);
|
|
393
396
|
const whitewater = vPost.mul(
|
|
394
397
|
waterFbm(vec2(vAlong.mul(2.3), vProfile.mul(3.0).add(u.uTime.mul(2.2))), 3).mul(0.6).add(0.7),
|
|
395
398
|
);
|