genshin-engine 4.1.2 → 4.3.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { A as TERRAIN_RING_INITIAL_TILE_COUNT, C as getCliffBlend, D as TERRAIN_CELL_SIZE, E as GAUSSIAN_REACH_WIDTHS, F as GroundLayer, I as GroundLayers, L as createSeededRandom, M as TILE_INDEX_SPAN, N as createSimplexNoise, O as TERRAIN_HEIGHT_PADDING, P as TerrainFeatureKind, S as getPlateauBlend, T as getTerrainTileLevel, _ as getTerrainTileRow, a as createTerrainFeaturesBlend, b as TerrainFeatureKindBlendMap, c as sampleTerrainResidualFade, d as sampleGroundLayerField, f as getSegmentBounds, g as computeTerrainTile, h as fileByCell, i as createTerrainFeaturesHeight, j as TILE_INDEX_OFFSET, k as TERRAIN_LAYER, l as createGroundPaintColor, m as getGaussianHillBlend, n as createTerrainShapeHeight, o as getTerrainFeatureBounds, p as createGaussianHillsHeight, r as getTerrainShapeLevel, s as createResidualHeight, t as computeScatterPoints, u as createGroundLayerWeights, v as getTerrainTileColumn, w as measureSegment, x as getRidgeBlend, y as blendGridNodes } from "./terrainWorker-DZ04cA3m.js";
2
2
  import { AdditiveBlending, BackSide, Bone, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, ClampToEdgeWrapping, Color, CylinderGeometry, Data3DTexture, DataTexture, DataUtils, DirectionalLight, DoubleSide, Euler, Float32BufferAttribute, FloatType, FrontSide, HalfFloatType, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, InterleavedBufferAttribute, LinearFilter, LinearMipmapLinearFilter, MathUtils, Matrix3, Matrix4, Mesh, NearestFilter, NoColorSpace, NoToneMapping, OrthographicCamera, PerspectiveCamera, Quaternion, RGBAFormat, RedFormat, RepeatWrapping, SRGBColorSpace, Scene, Skeleton, SkinnedMesh, Sphere, Sprite, Texture, UnsignedByteType, Vector2, Vector3 } from "three";
3
- import { Fn, If, abs, acos, asin, atan, attribute, cameraFar, cameraNear, cameraPosition, cameraProjectionMatrix, cameraViewMatrix, clamp, color, cos, cross, diffuseColor, dot, exp, exp2, float, getNormalFromDepth, getViewPosition, hash, instanceIndex, instancedBufferAttribute, interleavedGradientNoise, luminance, mat4, max, min, mix, mod, modelViewMatrix, modelWorldMatrix, modelWorldMatrixInverse, mrt, mx_cell_noise_float, mx_fractal_noise_float, mx_noise_float, normalLocal, normalView, normalWorld, normalWorldGeometry, normalize, output, pass, perspectiveDepthToViewZ, positionGeometry, positionLocal, positionView, positionViewDirection, positionWorld, pow, reflect, renderOutput, sample, saturate, screenCoordinate, screenUV, select, sin, smoothstep, step, tangentLocal, texture, texture3D, time, transformNormalToView, uniform, uniformArray, uv, varying, vec2, vec3, vec4, velocity, vertexColor, viewportDepthTexture, viewportSharedTexture } from "three/tsl";
4
- import { LightingModel, MeshBasicNodeMaterial, MeshToonNodeMaterial, NodeMaterial, RenderPipeline, RenderTarget, SpriteNodeMaterial, StorageInstancedBufferAttribute, ToonOutlinePassNode, WebGPURenderer } from "three/webgpu";
3
+ import { Fn, If, abs, acos, asin, atan, atomicAdd, atomicStore, attribute, cameraFar, cameraNear, cameraPosition, cameraProjectionMatrix, cameraViewMatrix, clamp, color, cos, cross, diffuseColor, distance, dot, exp, exp2, float, fract, getNormalFromDepth, getViewPosition, hash, instanceIndex, instancedBufferAttribute, interleavedGradientNoise, luminance, mat4, max, min, mix, mod, modelViewMatrix, modelWorldMatrix, modelWorldMatrixInverse, mrt, mx_cell_noise_float, mx_fractal_noise_float, mx_noise_float, normalGeometry, normalLocal, normalView, normalViewGeometry, normalWorld, normalWorldGeometry, normalize, output, pass, perspectiveDepthToViewZ, positionGeometry, positionLocal, positionView, positionViewDirection, positionWorld, pow, reflect, renderOutput, sample, saturate, screenCoordinate, screenUV, select, sin, smoothstep, step, storage, tangentLocal, texture, texture3D, time, transformNormal, transformNormalToView, uint, uniform, uniformArray, uv, varying, vec2, vec3, vec4, velocity, vertexColor, viewportDepthTexture, viewportSharedTexture } from "three/tsl";
4
+ import { IndirectStorageBufferAttribute, LightingModel, MeshBasicNodeMaterial, MeshToonNodeMaterial, NodeMaterial, RenderPipeline, RenderTarget, SpriteNodeMaterial, StorageBufferAttribute, StorageInstancedBufferAttribute, ToonOutlinePassNode, WebGPURenderer } from "three/webgpu";
5
5
  import { CSMShadowNode } from "three/examples/jsm/csm/CSMShadowNode.js";
6
6
  import { MeshBVH } from "three-mesh-bvh";
7
7
  import { Capsule } from "three/examples/jsm/math/Capsule.js";
@@ -32,6 +32,7 @@ let WeatherKind = /* @__PURE__ */ function(WeatherKind) {
32
32
  WeatherKind["Rain"] = "Rain";
33
33
  WeatherKind["Sandstorm"] = "Sandstorm";
34
34
  WeatherKind["Snow"] = "Snow";
35
+ WeatherKind["Snowstorm"] = "Snowstorm";
35
36
  WeatherKind["Thunderstorm"] = "Thunderstorm";
36
37
  return WeatherKind;
37
38
  }({});
@@ -80,6 +81,15 @@ const PRECIPITATION_SETTINGS_MAP = {
80
81
  windDrift: .3
81
82
  }
82
83
  };
84
+ const SNOW_WEATHER_SETTINGS = {
85
+ cloudCoverage: .8,
86
+ fogDensity: .001,
87
+ precipitation: {
88
+ density: .5,
89
+ kind: "Snow"
90
+ },
91
+ wetness: 0
92
+ };
83
93
  const WEATHER_SETTINGS_MAP = {
84
94
  ["Clear"]: {
85
95
  cloudCoverage: 0,
@@ -115,15 +125,8 @@ const WEATHER_SETTINGS_MAP = {
115
125
  },
116
126
  wetness: 0
117
127
  },
118
- ["Snow"]: {
119
- cloudCoverage: .8,
120
- fogDensity: .001,
121
- precipitation: {
122
- density: .5,
123
- kind: "Snow"
124
- },
125
- wetness: 0
126
- },
128
+ ["Snow"]: SNOW_WEATHER_SETTINGS,
129
+ ["Snowstorm"]: { ...SNOW_WEATHER_SETTINGS },
127
130
  ["Thunderstorm"]: {
128
131
  cloudCoverage: 1,
129
132
  fogDensity: .002,
@@ -818,6 +821,7 @@ const FREE_CAMERA_MAX_PITCH = Math.PI / 2 - .01;
818
821
  const FOLLOW_CAMERA_DEFAULT_SETTINGS = {
819
822
  defaultDistance: 5,
820
823
  horizontalSensitivity: 3,
824
+ slopePitch: false,
821
825
  verticalSensitivity: 3
822
826
  };
823
827
  const FOLLOW_CAMERA_NEUTRAL_SENSITIVITY = 3;
@@ -829,6 +833,7 @@ const FOLLOW_CAMERA_MIN_DISTANCE = 1;
829
833
  const FOLLOW_CAMERA_MAX_DISTANCE = 6;
830
834
  const FOLLOW_CAMERA_DISTANCE_PER_ZOOM_STEP = .5;
831
835
  const FOLLOW_CAMERA_EASE_OUT_SPEED = 4;
836
+ const FOLLOW_CAMERA_SLOPE_PITCH_SPEED = 4;
832
837
  const FOLLOW_CAMERA_CLEARANCE = .2;
833
838
  const FOLLOW_CAMERA_ARM_STEP = .25;
834
839
  //#endregion
@@ -1572,23 +1577,35 @@ let InputAction = /* @__PURE__ */ function(InputAction) {
1572
1577
  const InputActions = Object.values(InputAction);
1573
1578
  //#endregion
1574
1579
  //#region src/camera/createFollowCamera.ts
1580
+ const clampPitch = (value) => Math.max(FOLLOW_CAMERA_MIN_PITCH, Math.min(FOLLOW_CAMERA_MAX_PITCH, value));
1575
1581
  const createFollowCamera = ({ camera, ground, landmarkCollider, settings }) => {
1576
1582
  const euler = new Euler().setFromQuaternion(camera.quaternion, "YXZ");
1577
1583
  const armDirection = new Vector3();
1578
1584
  let yaw = euler.y;
1579
1585
  let pitch = 0;
1586
+ let slopeBaseline = 0;
1587
+ let lookOffset = 0;
1580
1588
  let distance = settings.defaultDistance;
1581
1589
  let armLength = distance;
1582
1590
  camera.fov = 45;
1583
1591
  camera.updateProjectionMatrix();
1592
+ const settlePitch = () => {
1593
+ lookOffset = clampPitch(slopeBaseline + lookOffset) - slopeBaseline;
1594
+ pitch = slopeBaseline + lookOffset;
1595
+ };
1584
1596
  const turn = () => {
1585
1597
  euler.set(pitch, yaw, 0, "YXZ");
1586
1598
  camera.quaternion.setFromEuler(euler);
1587
1599
  };
1600
+ const returnToDefaultDistance = () => {
1601
+ distance = settings.defaultDistance;
1602
+ };
1588
1603
  const reset = (facing) => {
1589
1604
  yaw = facing;
1590
1605
  pitch = 0;
1591
- distance = settings.defaultDistance;
1606
+ slopeBaseline = 0;
1607
+ lookOffset = 0;
1608
+ returnToDefaultDistance();
1592
1609
  turn();
1593
1610
  };
1594
1611
  const computeGroundReach = (pivot, reach) => {
@@ -1600,11 +1617,23 @@ const createFollowCamera = ({ camera, ground, landmarkCollider, settings }) => {
1600
1617
  }
1601
1618
  return reach;
1602
1619
  };
1620
+ const computeSlopePitch = (pivot) => {
1621
+ const runX = Math.sin(yaw) * distance;
1622
+ const runZ = Math.cos(yaw) * distance;
1623
+ const rise = ground.getGround(pivot.x + runX, pivot.z + runZ).height - ground.getGround(pivot.x, pivot.z).height;
1624
+ return -Math.atan2(rise, distance);
1625
+ };
1603
1626
  return {
1604
1627
  follow: (pivot, origin, frameSeconds) => {
1628
+ if (settings.slopePitch) {
1629
+ const settle = 1 - Math.exp(-4 * frameSeconds);
1630
+ slopeBaseline += (computeSlopePitch(pivot) - slopeBaseline) * settle;
1631
+ settlePitch();
1632
+ turn();
1633
+ }
1605
1634
  armDirection.set(Math.sin(yaw) * Math.cos(pitch), -Math.sin(pitch), Math.cos(yaw) * Math.cos(pitch));
1606
1635
  const landmarkReach = landmarkCollider.castSphere(pivot, armDirection, distance, FOLLOW_CAMERA_CLEARANCE);
1607
- const reach = Math.max(1, computeGroundReach(pivot, landmarkReach));
1636
+ const reach = computeGroundReach(pivot, Math.max(1, landmarkReach));
1608
1637
  armLength = reach < armLength ? reach : Math.min(reach, armLength + 4 * frameSeconds);
1609
1638
  camera.position.copy(pivot).addScaledVector(armDirection, armLength).sub(origin);
1610
1639
  },
@@ -1614,11 +1643,13 @@ const createFollowCamera = ({ camera, ground, landmarkCollider, settings }) => {
1614
1643
  return;
1615
1644
  }
1616
1645
  yaw += input.lookYaw * (settings.horizontalSensitivity / 3);
1617
- pitch = Math.max(FOLLOW_CAMERA_MIN_PITCH, Math.min(FOLLOW_CAMERA_MAX_PITCH, pitch + input.lookPitch * (settings.verticalSensitivity / 3)));
1646
+ lookOffset += input.lookPitch * (settings.verticalSensitivity / 3);
1647
+ settlePitch();
1618
1648
  distance = Math.max(1, Math.min(6, distance + input.zoomSteps * FOLLOW_CAMERA_DISTANCE_PER_ZOOM_STEP));
1619
1649
  turn();
1620
1650
  },
1621
1651
  reset,
1652
+ returnToDefaultDistance,
1622
1653
  get yaw() {
1623
1654
  return yaw;
1624
1655
  }
@@ -1653,6 +1684,18 @@ const createFreeCamera = ({ camera, ground }) => {
1653
1684
  };
1654
1685
  };
1655
1686
  //#endregion
1687
+ //#region src/models/character/PmxSphereMode.ts
1688
+ let PmxSphereMode = /* @__PURE__ */ function(PmxSphereMode) {
1689
+ PmxSphereMode[PmxSphereMode["Disabled"] = 0] = "Disabled";
1690
+ PmxSphereMode[PmxSphereMode["Multiply"] = 1] = "Multiply";
1691
+ PmxSphereMode[PmxSphereMode["Add"] = 2] = "Add";
1692
+ PmxSphereMode[PmxSphereMode["AdditionalUv"] = 3] = "AdditionalUv";
1693
+ return PmxSphereMode;
1694
+ }({});
1695
+ //#endregion
1696
+ //#region src/character/checkIsPmxSphereDrawn.ts
1697
+ const checkIsPmxSphereDrawn = (sphereMode) => sphereMode === 1 || sphereMode === 2;
1698
+ //#endregion
1656
1699
  //#region src/character/checkTransparentTexels.ts
1657
1700
  const checkTransparentTexels = (image) => {
1658
1701
  const context = new OffscreenCanvas(image.width, image.height).getContext("2d", { willReadFrequently: true });
@@ -1667,7 +1710,6 @@ const checkTransparentTexels = (image) => {
1667
1710
  };
1668
1711
  //#endregion
1669
1712
  //#region src/character/constants.ts
1670
- const PMX_UNIT_METRES = .08;
1671
1713
  const SHARED_TOON_RAMP_SHADES = [
1672
1714
  .4,
1673
1715
  .45,
@@ -1699,6 +1741,18 @@ const MINIMUM_RAMP_WIDTH_VERTEX = .01;
1699
1741
  const MINIMUM_OUTLINE_KNOT_SPAN = .001;
1700
1742
  const OUTLINE_PROJECTION_SCALE = 2.414;
1701
1743
  const OUTLINE_WIDTH_SCALE = .41425;
1744
+ const UNIT_OUTLINE_WIDTH_KNOTS = {
1745
+ depths: [
1746
+ 1,
1747
+ 2,
1748
+ 3
1749
+ ],
1750
+ scales: [
1751
+ 1,
1752
+ 1,
1753
+ 1
1754
+ ]
1755
+ };
1702
1756
  const OUTLINE_MAIN_TEXTURE_SHARE = .2;
1703
1757
  const DESATURATION_WEIGHTS = [
1704
1758
  .0397,
@@ -1809,16 +1863,7 @@ const createCharacterShadingInputs = (overrides) => {
1809
1863
  lightArea: DEFAULT_LIGHT_AREA,
1810
1864
  metalDarkColor: BLACK,
1811
1865
  metalLightColor: WHITE,
1812
- outlineDepths: [
1813
- 1,
1814
- 2,
1815
- 3
1816
- ],
1817
- outlineScales: [
1818
- 1,
1819
- 1,
1820
- 1
1821
- ],
1866
+ outlineWidthKnots: UNIT_OUTLINE_WIDTH_KNOTS,
1822
1867
  rampLayout: 0,
1823
1868
  rampWidth: DEFAULT_RAMP_WIDTH,
1824
1869
  regionTints: {
@@ -1940,6 +1985,10 @@ const selectRegionNode = (region, toRegionNode) => LATER_REGIONS.reduce((current
1940
1985
  //#endregion
1941
1986
  //#region src/character/shading/createCharacterShadingNode.ts
1942
1987
  const toVec3 = ([red, green, blue]) => vec3(red, green, blue);
1988
+ const laySphere = (diffuse, sphere) => {
1989
+ const sample = texture(sphere.texture, vec2(normalView.x, normalView.y.negate()).mul(.5).add(.5)).rgb;
1990
+ return sphere.mode === 2 ? diffuse.add(sample) : diffuse.mul(sample);
1991
+ };
1943
1992
  const selectRegionColor = (region, colors) => selectRegionNode(region, (regionName) => toVec3(colors[regionName]));
1944
1993
  const createShadowMultiplyNode = (region, inputs) => {
1945
1994
  const firstShadow = selectRegionColor(region, inputs.shadowMultiplyColors);
@@ -1957,7 +2006,8 @@ const createCharacterShadingNode = (inputs, { lightColor, sunDirection }) => {
1957
2006
  one: color
1958
2007
  });
1959
2008
  const mainSample = inputs.mainTexture ? texture(inputs.mainTexture, uv()) : vec4(1);
1960
- const materialColour = mainSample.rgb.mul(tint);
2009
+ const diffuseColour = mainSample.rgb.mul(tint);
2010
+ const materialColour = inputs.sphere ? laySphere(diffuseColour, inputs.sphere) : diffuseColour;
1961
2011
  const sunTerm = normalView.dot(sunDirectionView).mul(HALF_LAMBERT_SCALE).add(HALF_LAMBERT_OFFSET);
1962
2012
  const threshold = createToonThresholdNode({
1963
2013
  isLightMapAo: inputs.isLightMapAo,
@@ -2019,19 +2069,11 @@ const getToneColour = (colour, desaturateScale, contrastScale) => {
2019
2069
  return new Vector3(.5 + (desaturated.x - .5) * gain, .5 + (desaturated.y - .5) * gain, .5 + (desaturated.z - .5) * gain);
2020
2070
  };
2021
2071
  //#endregion
2022
- //#region src/models/character/PmxSphereMode.ts
2023
- let PmxSphereMode = /* @__PURE__ */ function(PmxSphereMode) {
2024
- PmxSphereMode[PmxSphereMode["Disabled"] = 0] = "Disabled";
2025
- PmxSphereMode[PmxSphereMode["Multiply"] = 1] = "Multiply";
2026
- PmxSphereMode[PmxSphereMode["Add"] = 2] = "Add";
2027
- PmxSphereMode[PmxSphereMode["AdditionalUv"] = 3] = "AdditionalUv";
2028
- return PmxSphereMode;
2029
- }({});
2030
- //#endregion
2031
2072
  //#region src/models/nodes/ToonNodeMaterial.ts
2032
2073
  var ToonNodeMaterial = class extends MeshToonNodeMaterial {
2033
2074
  edge;
2034
2075
  emissiveNode = null;
2076
+ instanceMatrix;
2035
2077
  isMeshToonMaterial;
2036
2078
  isMeshToonNodeMaterial;
2037
2079
  sphereMap;
@@ -2055,11 +2097,14 @@ const createCharacterMaterial = ({ isTextureTransparent, lightUniforms, pmxMater
2055
2097
  const shadingInputs = createCharacterShadingInputs({
2056
2098
  color,
2057
2099
  mainTexture: diffuseTexture,
2058
- metalTexture: sphereTexture && sphereMode !== 0 ? sphereTexture : void 0,
2059
2100
  rampLayout: packToonTexture ? 1 : 0,
2060
2101
  rampTexture: packToonTexture ?? (isToonShared ? getSharedToonRamp(toonIndex) : void 0) ?? rampTexture,
2061
2102
  shininess: specularity,
2062
2103
  specularColor,
2104
+ sphere: sphereTexture && checkIsPmxSphereDrawn(sphereMode) ? {
2105
+ mode: sphereMode,
2106
+ texture: sphereTexture
2107
+ } : void 0,
2063
2108
  ...gameShadingInputs
2064
2109
  });
2065
2110
  const toned = getToneColour(new Vector3(red * edgeColor[0], green * edgeColor[1], blue * edgeColor[2]), shadingInputs.desaturateScale, shadingInputs.contrastScale);
@@ -2080,14 +2125,11 @@ const createCharacterMaterial = ({ isTextureTransparent, lightUniforms, pmxMater
2080
2125
  isVertexWeighted: shadingInputs.isOutlineVertexWeighted,
2081
2126
  offset: shadingInputs.outlineOffset,
2082
2127
  size: edgeSize,
2083
- widthKnots: {
2084
- depths: shadingInputs.outlineDepths,
2085
- scales: shadingInputs.outlineScales
2086
- }
2128
+ widthKnots: shadingInputs.outlineWidthKnots
2087
2129
  } : void 0);
2088
2130
  characterMaterial.lights = false;
2089
2131
  characterMaterial.outputNode = vec4(createCharacterShadingNode(shadingInputs, lightUniforms), alpha);
2090
- if (sphereTexture && sphereMode !== 0) characterMaterial.sphereMap = sphereTexture;
2132
+ if (sphereTexture && checkIsPmxSphereDrawn(sphereMode)) characterMaterial.sphereMap = sphereTexture;
2091
2133
  return characterMaterial;
2092
2134
  };
2093
2135
  //#endregion
@@ -2143,13 +2185,13 @@ const createPmxSkeleton = (pmxBones) => {
2143
2185
  };
2144
2186
  //#endregion
2145
2187
  //#region src/character/createPmxMesh.ts
2146
- const createPmxMesh = (pmxModel, materials) => {
2188
+ const createPmxMesh = (pmxModel, materials, unitMetres) => {
2147
2189
  const geometry = createPmxGeometry(pmxModel);
2148
2190
  const mesh = new SkinnedMesh(geometry, materials);
2149
2191
  const skeleton = createPmxSkeleton(pmxModel.bones);
2150
2192
  for (const bone of skeleton.bones) if (!bone.parent) mesh.add(bone);
2151
2193
  mesh.normalizeSkinWeights();
2152
- mesh.scale.setScalar(PMX_UNIT_METRES);
2194
+ mesh.scale.setScalar(unitMetres);
2153
2195
  mesh.bind(skeleton);
2154
2196
  return mesh;
2155
2197
  };
@@ -3115,6 +3157,80 @@ const createLandmarkCollider = () => {
3115
3157
  };
3116
3158
  };
3117
3159
  //#endregion
3160
+ //#region src/culling/constants.ts
3161
+ const CULLING_FRUSTUM_MARGIN = .1;
3162
+ const CULLING_INDIRECT_ARGUMENT_COUNT = 5;
3163
+ const CULLING_INDEX_COUNT_INDEX = 0;
3164
+ const CULLING_INSTANCE_COUNT_INDEX = 1;
3165
+ const CULLING_MIN_SIZE = 1e-4;
3166
+ const CULLING_MATRIX_COLUMN_COUNT = 4;
3167
+ const CULLING_MATRIX_ELEMENT_COUNT = 16;
3168
+ //#endregion
3169
+ //#region src/culling/createFrustumVisibility.ts
3170
+ const createFrustumVisibility = (clipFromModel, point) => {
3171
+ const clip = clipFromModel.mul(vec4(point, 1));
3172
+ const limit = clip.w.mul(1.1);
3173
+ return step(0, clip.w).mul(step(clip.x.abs(), limit)).mul(step(clip.y.abs(), limit)).mul(step(0, clip.z)).mul(step(clip.z, limit));
3174
+ };
3175
+ //#endregion
3176
+ //#region src/culling/createSurvivorIndices.ts
3177
+ const createSurvivorIndices = (count) => Uint32Array.from({ length: count }, (_value, index) => index);
3178
+ //#endregion
3179
+ //#region src/culling/createInstanceCulling.ts
3180
+ const createInstanceCulling = ({ count, indexCount, isVisible }) => {
3181
+ const indirectArray = /* @__PURE__ */ new Uint32Array(5);
3182
+ indirectArray[0] = indexCount;
3183
+ const indirect = new IndirectStorageBufferAttribute(indirectArray, 1);
3184
+ const survivorAttribute = new StorageBufferAttribute(createSurvivorIndices(count), 1);
3185
+ const counter = storage(indirect, "uint", 5).toAtomic();
3186
+ const survivors = storage(survivorAttribute, "uint", count);
3187
+ const resetCount = Fn(() => {
3188
+ atomicStore(counter.element(1), uint(0));
3189
+ })().compute(1);
3190
+ const cullInstances = Fn(() => {
3191
+ If(isVisible(float(instanceIndex)).greaterThan(0), () => {
3192
+ const slot = atomicAdd(counter.element(1), uint(1));
3193
+ survivors.element(slot).assign(uint(instanceIndex));
3194
+ });
3195
+ })().compute(count);
3196
+ return {
3197
+ cull: (renderer) => {
3198
+ renderer.compute(resetCount);
3199
+ renderer.compute(cullInstances);
3200
+ },
3201
+ dispose: () => {
3202
+ indirect.dispose();
3203
+ survivorAttribute.dispose();
3204
+ },
3205
+ indirect,
3206
+ survivor: float(storage(survivorAttribute, "uint", count).toReadOnly().element(instanceIndex))
3207
+ };
3208
+ };
3209
+ //#endregion
3210
+ //#region src/culling/createInstanceMatrixBuffer.ts
3211
+ const createInstanceMatrixBuffer = (matrices) => {
3212
+ const array = new Float32Array(matrices.length * 16);
3213
+ for (const [index, matrix] of matrices.entries()) array.set(matrix.elements, index * 16);
3214
+ return new StorageBufferAttribute(array, 4);
3215
+ };
3216
+ //#endregion
3217
+ //#region src/culling/createInstanceMatrixNode.ts
3218
+ const createInstanceMatrixNode = (attribute, instance) => {
3219
+ const columns = storage(attribute, "vec4", attribute.count).toReadOnly();
3220
+ const firstColumn = uint(instance).mul(uint(4));
3221
+ const column = (offset) => columns.element(firstColumn.add(uint(offset)));
3222
+ return mat4(column(0), column(1), column(2), column(3));
3223
+ };
3224
+ //#endregion
3225
+ //#region src/culling/createInstancedGeometry.ts
3226
+ const createInstancedGeometry = (geometry, instanceCount) => {
3227
+ const instancedGeometry = new InstancedBufferGeometry();
3228
+ for (const [name, attribute] of Object.entries(geometry.attributes)) instancedGeometry.setAttribute(name, attribute);
3229
+ instancedGeometry.setIndex(geometry.getIndex());
3230
+ instancedGeometry.instanceCount = instanceCount;
3231
+ return instancedGeometry;
3232
+ };
3233
+ //#endregion
3118
3234
  //#region src/models/input/GamepadButton.ts
3119
3235
  let GamepadButton = /* @__PURE__ */ function(GamepadButton) {
3120
3236
  GamepadButton["Back"] = "GamepadBack";
@@ -3660,8 +3776,50 @@ const SURFACE_DETAIL_BAND_SIGMAS = [
3660
3776
  4,
3661
3777
  8
3662
3778
  ];
3663
- const SURFACE_OCTAVE_TEXEL_FREQUENCIES = [...SURFACE_DETAIL_BAND_SIGMAS.map((sigma) => 1 / (2 * Math.PI * sigma)), 1 / (4 * Math.PI * (SURFACE_DETAIL_BAND_SIGMAS.at(-1) ?? 0))];
3664
- const SURFACE_DETAIL_RENDER_GAIN = 4;
3779
+ const SURFACE_OCTAVE_TEXEL_FREQUENCIES = [
3780
+ .9,
3781
+ .3,
3782
+ .1,
3783
+ .033,
3784
+ .011
3785
+ ];
3786
+ const SURFACE_OCTAVE_RESPONSES = [
3787
+ [
3788
+ .0529,
3789
+ .00115,
3790
+ 13e-5,
3791
+ 385e-7,
3792
+ .0618
3793
+ ],
3794
+ [
3795
+ .0162,
3796
+ .00896,
3797
+ .00235,
3798
+ 251e-6,
3799
+ .0605
3800
+ ],
3801
+ [
3802
+ 543e-6,
3803
+ .00257,
3804
+ .00927,
3805
+ .00654,
3806
+ .0626
3807
+ ],
3808
+ [
3809
+ 99e-7,
3810
+ 654e-7,
3811
+ 742e-6,
3812
+ .0048,
3813
+ .0534
3814
+ ],
3815
+ [
3816
+ 419e-9,
3817
+ 155e-8,
3818
+ 169e-7,
3819
+ 188e-6,
3820
+ .0379
3821
+ ]
3822
+ ];
3665
3823
  const OBJECT_SURFACE_KEY = "surface";
3666
3824
  const OBJECT_FADE_KEY = "fade";
3667
3825
  const LEAF_SHAPE_WIDTH = .8;
@@ -4024,6 +4182,9 @@ const createStamina = (maximum, getStaminaConsumptionMultiplier = () => 1) => {
4024
4182
  refill: () => {
4025
4183
  stamina.value = stamina.maximum;
4026
4184
  },
4185
+ restore: (amount) => {
4186
+ stamina.value = Math.min(stamina.maximum, stamina.value + amount);
4187
+ },
4027
4188
  spend: (amount) => {
4028
4189
  stamina.value = Math.max(0, stamina.value - getCost(amount));
4029
4190
  restSeconds = 0;
@@ -4050,7 +4211,8 @@ const getSpeed = (state, locomotion) => {
4050
4211
  else if (state === "SwimDash") return locomotion.swimDashSpeed;
4051
4212
  else return locomotion.runSpeed;
4052
4213
  };
4053
- const createCharacterController = ({ getStaminaConsumptionMultiplier, ground, landmarkCollider, position, staminaMaximum }) => {
4214
+ const createCharacterController = (options) => {
4215
+ const { ground, landmarkCollider, position } = options;
4054
4216
  const previousPosition = position.clone();
4055
4217
  const lastFullPosition = position.clone();
4056
4218
  const velocity = new Vector3();
@@ -4065,7 +4227,7 @@ const createCharacterController = ({ getStaminaConsumptionMultiplier, ground, la
4065
4227
  state: "Idle",
4066
4228
  stateSeconds: 0
4067
4229
  };
4068
- const stamina = createStamina(staminaMaximum, getStaminaConsumptionMultiplier);
4230
+ const stamina = options.stamina === void 0 ? createStamina(options.staminaMaximum, options.getStaminaConsumptionMultiplier) : options.stamina;
4069
4231
  const contact = {
4070
4232
  isFacingWall: false,
4071
4233
  isGrounded: true,
@@ -4291,14 +4453,16 @@ var ObjectSurface = class {
4291
4453
  };
4292
4454
  //#endregion
4293
4455
  //#region src/models/nodes/createOutlineMaterial.ts
4294
- const createOutlineMaterial = (colorNode, thicknessNode) => {
4456
+ const createOutlineMaterial = (colorNode, thicknessNode, instanceMatrix) => {
4295
4457
  const material = Object.assign(new NodeMaterial(), { isMeshToonOutlineMaterial: true });
4296
4458
  material.name = "Toon_Outline";
4297
4459
  material.side = BackSide;
4298
4460
  const outlineNormal = normalLocal.negate();
4461
+ const outlineDirection = instanceMatrix ? transformNormal(outlineNormal, instanceMatrix) : outlineNormal;
4462
+ const placed = (point) => instanceMatrix ? instanceMatrix.mul(vec4(point, 1)).xyz : point;
4299
4463
  const mvp = cameraProjectionMatrix.mul(modelViewMatrix);
4300
- const pos = mvp.mul(vec4(positionLocal, 1));
4301
- const pos2 = mvp.mul(vec4(positionLocal.add(outlineNormal), 1));
4464
+ const pos = mvp.mul(vec4(placed(positionLocal), 1));
4465
+ const pos2 = pos.add(mvp.mul(vec4(outlineDirection, 0)));
4302
4466
  const norm = normalize(pos.sub(pos2));
4303
4467
  material.vertexNode = pos.add(norm.mul(thicknessNode).mul(pos.w));
4304
4468
  material.colorNode = colorNode;
@@ -4322,10 +4486,14 @@ const createGameOutlineMaterial = (colorNode, widthNode, offsetNode) => {
4322
4486
  var SharedToonOutlinePassNode = class extends ToonOutlinePassNode {
4323
4487
  #drawn;
4324
4488
  #edgeOutlineMaterials = /* @__PURE__ */ new Map();
4489
+ #instancedOutlineMaterials = /* @__PURE__ */ new WeakMap();
4325
4490
  #outlineMaterial;
4326
4491
  #pixelEdgeOutlineMaterials = /* @__PURE__ */ new WeakMap();
4327
4492
  _getOutlineMaterial(originalMaterial) {
4328
- if (originalMaterial instanceof ToonNodeMaterial && originalMaterial.edge) return this.#getEdgeOutlineMaterial(originalMaterial.edge);
4493
+ if (originalMaterial instanceof ToonNodeMaterial) {
4494
+ if (originalMaterial.instanceMatrix) return this.#getInstancedOutlineMaterial(originalMaterial.instanceMatrix);
4495
+ if (originalMaterial.edge) return this.#getEdgeOutlineMaterial(originalMaterial.edge);
4496
+ }
4329
4497
  return this.#getSharedOutlineMaterial();
4330
4498
  }
4331
4499
  async compileAsync(renderer) {
@@ -4362,6 +4530,14 @@ var SharedToonOutlinePassNode = class extends ToonOutlinePassNode {
4362
4530
  }
4363
4531
  return edgeOutlineMaterial;
4364
4532
  }
4533
+ #getInstancedOutlineMaterial(instanceMatrix) {
4534
+ let instancedOutlineMaterial = this.#instancedOutlineMaterials.get(instanceMatrix);
4535
+ if (instancedOutlineMaterial === void 0) {
4536
+ instancedOutlineMaterial = createOutlineMaterial(vec4(this.colorNode, this.alphaNode), this.thicknessNode, instanceMatrix);
4537
+ this.#instancedOutlineMaterials.set(instanceMatrix, instancedOutlineMaterial);
4538
+ }
4539
+ return instancedOutlineMaterial;
4540
+ }
4365
4541
  #getSharedOutlineMaterial() {
4366
4542
  this.#outlineMaterial ??= createOutlineMaterial(vec4(this.colorNode, this.alphaNode), this.thicknessNode);
4367
4543
  return this.#outlineMaterial;
@@ -4478,12 +4654,7 @@ const computeStoneRampCoordinate = (facing, visibility) => .5 + .5 * facing * Ma
4478
4654
  //#region src/nodes/computeSurfaceOctaves.ts
4479
4655
  const SOLVE_ITERATIONS = 300;
4480
4656
  const SOLVE_START_ENERGY = 1e-6;
4481
- const BAND_EDGE_SIGMAS = [0, ...SURFACE_DETAIL_BAND_SIGMAS];
4482
- const computeBandResponse = (fineSigma, coarseSigma, texelFrequency) => {
4483
- const decay = 2 * Math.PI ** 2 * texelFrequency ** 2;
4484
- return (Math.exp(-decay * fineSigma ** 2) - Math.exp(-decay * coarseSigma ** 2)) ** 2 / 2;
4485
- };
4486
- const computeResponses = (targets) => SURFACE_OCTAVE_TEXEL_FREQUENCIES.map((texelFrequency) => [...BAND_EDGE_SIGMAS.slice(0, -1).map((fineSigma, band) => computeBandResponse(fineSigma, BAND_EDGE_SIGMAS[band + 1] ?? 0, texelFrequency)), .5]).map((responses) => responses.map((response, row) => targets[row] ? response / targets[row] : 0));
4657
+ const computeResponses = (targets) => SURFACE_OCTAVE_RESPONSES.map((responses) => responses.map((response, row) => targets[row] ? response / targets[row] : 0));
4487
4658
  const solveOctaveEnergies = (responses, targets) => {
4488
4659
  const energies = responses.map(() => SOLVE_START_ENERGY);
4489
4660
  for (let iteration = 0; iteration < SOLVE_ITERATIONS; iteration++) {
@@ -4505,6 +4676,12 @@ const computeSurfaceOctaves = ({ bands, metresPerTexel, variance }) => {
4505
4676
  }));
4506
4677
  };
4507
4678
  //#endregion
4679
+ //#region src/nodes/computeWindGust.ts
4680
+ const computeWindGust = (downwind, time, { gustSpeed, gustStrength, gustWidth }) => {
4681
+ const gustPhase = (downwind - time * gustSpeed) / gustWidth * Math.PI * 2;
4682
+ return MathUtils.smoothstep(Math.sin(gustPhase) * .5 + .5, .2, 1) * gustStrength;
4683
+ };
4684
+ //#endregion
4508
4685
  //#region src/nodes/createCausticsNode.ts
4509
4686
  const CAUSTIC_SCALE = .35;
4510
4687
  const CAUSTIC_SPEED = .6;
@@ -4607,9 +4784,12 @@ const createDitherFadeNode = (visibility) => interleavedGradientNoise(screenCoor
4607
4784
  //#region src/nodes/createSurfaceDetailNode.ts
4608
4785
  const createSurfaceDetailNode = (amplitudes, texelsPerMetre) => {
4609
4786
  const texelPosition = vec3(positionWorld.mul(texelsPerMetre));
4610
- return SURFACE_OCTAVE_TEXEL_FREQUENCIES.reduce((node, texelFrequency, octave) => node.add(mx_noise_float(texelPosition.mul(texelFrequency)).mul((amplitudes[octave] ?? float(0)).mul(4))), float(1));
4787
+ return SURFACE_OCTAVE_TEXEL_FREQUENCIES.reduce((node, texelFrequency, octave) => node.add(mx_noise_float(texelPosition.mul(texelFrequency)).mul(amplitudes[octave] ?? float(0))), float(1));
4611
4788
  };
4612
4789
  //#endregion
4790
+ //#region src/nodes/createMaterialDetailNode.ts
4791
+ const createMaterialDetailNode = (detail) => createSurfaceDetailNode(computeSurfaceOctaves(detail).map(({ amplitude }) => uniform(amplitude)), uniform(1 / detail.metresPerTexel));
4792
+ //#endregion
4613
4793
  //#region src/nodes/createObjectSurfaceNode.ts
4614
4794
  const DEFAULT_SURFACE = new ObjectSurface(new Color(16777215), [], 0);
4615
4795
  const readObjectSurface = (object) => {
@@ -4643,9 +4823,9 @@ const createWetSheenNode = ({ lightColor, sunDirection, wetness }) => {
4643
4823
  const createMaterialSurfaceNode = (color, detail) => {
4644
4824
  const colorUniform = uniform(new Color(color ?? 16777215));
4645
4825
  if (detail === void 0) return colorUniform;
4646
- return colorUniform.mul(createSurfaceDetailNode(computeSurfaceOctaves(detail).map(({ amplitude }) => uniform(amplitude)), uniform(1 / detail.metresPerTexel)));
4826
+ return colorUniform.mul(createMaterialDetailNode(detail));
4647
4827
  };
4648
- const createToonMaterial = ({ color, detail, isObjectSurface = false, isOutlined = true, isVertexColors = false, lightUniforms, rampTexture }) => {
4828
+ const createToonMaterial = ({ color, detail, instanceMatrix, isObjectSurface = false, isOutlined = true, isVertexColors = false, lightUniforms, rampTexture }) => {
4649
4829
  const toonMaterial = new ToonNodeMaterial({
4650
4830
  ...color === void 0 ? {} : { color },
4651
4831
  gradientMap: rampTexture,
@@ -4653,24 +4833,32 @@ const createToonMaterial = ({ color, detail, isObjectSurface = false, isOutlined
4653
4833
  }, isOutlined);
4654
4834
  toonMaterial.colorNode = (isObjectSurface ? createObjectSurfaceNode() : createMaterialSurfaceNode(color, detail)).mul(createWetDarkeningNode(lightUniforms));
4655
4835
  toonMaterial.emissiveNode = createRimNode(lightUniforms).add(createWetSheenNode(lightUniforms));
4836
+ if (instanceMatrix) {
4837
+ toonMaterial.instanceMatrix = instanceMatrix;
4838
+ toonMaterial.positionNode = instanceMatrix.mul(vec4(positionGeometry, 1)).xyz;
4839
+ toonMaterial.normalNode = transformNormalToView(transformNormal(normalGeometry, instanceMatrix)).normalize();
4840
+ }
4656
4841
  return toonMaterial;
4657
4842
  };
4658
4843
  //#endregion
4659
4844
  //#region src/nodes/createImpostorMaterial.ts
4660
4845
  const IMPOSTOR_ALPHA_TEST = .5;
4661
- const createImpostorMaterial = ({ fade, impostor, lightUniforms, rampTexture }) => {
4846
+ const createImpostorMaterial = ({ fade, impostor, instanceMatrix, lightUniforms, rampTexture }) => {
4662
4847
  const impostorMaterial = createToonMaterial({
4663
4848
  isOutlined: false,
4664
4849
  lightUniforms,
4665
4850
  rampTexture
4666
4851
  });
4667
- const eye = modelWorldMatrixInverse.mul(vec4(cameraPosition, 1)).xyz;
4852
+ const eyeInModel = modelWorldMatrixInverse.mul(vec4(cameraPosition, 1));
4853
+ const eye = instanceMatrix ? instanceMatrix.inverse().mul(eyeInModel).xyz : eyeInModel.xyz;
4668
4854
  const forward = vec3(eye.x, 0, eye.z).normalize();
4669
4855
  const right = vec3(forward.z, 0, forward.x.negate());
4670
- impostorMaterial.positionNode = right.mul(positionGeometry.x).add(vec3(0, positionGeometry.y, 0));
4856
+ const cardPoint = right.mul(positionGeometry.x).add(vec3(0, positionGeometry.y, 0));
4857
+ impostorMaterial.positionNode = instanceMatrix ? instanceMatrix.mul(vec4(cardPoint, 1)).xyz : cardPoint;
4671
4858
  const albedo = texture(impostor.albedoTarget.texture, uv());
4672
4859
  const bakedNormal = texture(impostor.normalTarget.texture, uv()).xyz.mul(2).sub(1);
4673
- impostorMaterial.normalNode = transformNormalToView(right.mul(bakedNormal.x).add(vec3(0, bakedNormal.y, 0)).add(forward.mul(bakedNormal.z))).normalize();
4860
+ const cardNormal = right.mul(bakedNormal.x).add(vec3(0, bakedNormal.y, 0)).add(forward.mul(bakedNormal.z));
4861
+ impostorMaterial.normalNode = transformNormalToView(instanceMatrix ? transformNormal(cardNormal, instanceMatrix) : cardNormal).normalize();
4674
4862
  impostorMaterial.colorNode = albedo.rgb.mul(createWetDarkeningNode(lightUniforms));
4675
4863
  impostorMaterial.maskNode = albedo.a.greaterThan(IMPOSTOR_ALPHA_TEST).and(createDitherFadeNode(fade));
4676
4864
  impostorMaterial.side = DoubleSide;
@@ -4681,7 +4869,7 @@ const createImpostorMaterial = ({ fade, impostor, lightUniforms, rampTexture })
4681
4869
  const createLeafShapeNode = () => {
4682
4870
  const centered = uv().sub(.5).mul(2);
4683
4871
  const width = float(1).sub(centered.y.abs().pow(2)).mul(LEAF_SHAPE_WIDTH);
4684
- return step(0, width.sub(centered.x.abs()));
4872
+ return centered.x.abs().lessThanEqual(width);
4685
4873
  };
4686
4874
  //#endregion
4687
4875
  //#region src/nodes/createWindNode.ts
@@ -4695,17 +4883,17 @@ const createWindNode = ({ direction, gustSpeed, gustStrength, gustWidth, strengt
4695
4883
  };
4696
4884
  //#endregion
4697
4885
  //#region src/nodes/createLeafMaterial.ts
4698
- const LEAF_ALPHA_TEST = .5;
4699
4886
  const SWAY_PER_WIND = .03;
4700
4887
  const FLUTTER = .06;
4701
- const createLeafMaterial = (toonMaterialOptions, windUniforms) => {
4888
+ const createLeafMaterial = (toonMaterialOptions, windUniforms, maskNode) => {
4702
4889
  const leafMaterial = createToonMaterial({
4703
4890
  ...toonMaterialOptions,
4704
4891
  isOutlined: false
4705
4892
  });
4706
- leafMaterial.opacityNode = createLeafShapeNode();
4707
- leafMaterial.alphaTest = LEAF_ALPHA_TEST;
4893
+ const leafShape = createLeafShapeNode();
4894
+ leafMaterial.maskNode = maskNode ? leafShape.and(maskNode) : leafShape;
4708
4895
  leafMaterial.side = DoubleSide;
4896
+ leafMaterial.normalNode = normalViewGeometry;
4709
4897
  if (windUniforms) {
4710
4898
  const worldPosition = modelWorldMatrix.mul(vec4(positionLocal, 1)).xyz;
4711
4899
  const lean = createWindNode(windUniforms, worldPosition.xz).mul(positionLocal.y.mul(SWAY_PER_WIND));
@@ -4775,6 +4963,62 @@ const createPrecipitationMaterial = ({ lightUniforms, precipitationUniforms, win
4775
4963
  return precipitationMaterial;
4776
4964
  };
4777
4965
  //#endregion
4966
+ //#region src/nodes/createWaterMaterial.ts
4967
+ const RIPPLE_SCALE = .08;
4968
+ const RIPPLE_SPEED = .05;
4969
+ const REFRACTION_STRENGTH = .015;
4970
+ const GLINT_POWER = 180;
4971
+ const GLINT_BRIGHTNESS = 5;
4972
+ const FOAM_SCALE = .6;
4973
+ const REFLECTION_STRENGTH = .55;
4974
+ const createWaterMaterial = ({ lightColor, sunDirection }, { horizonColor, zenithColor }, { deepColor, deepDepth, foamColor, foamDepth, shallowColor }, { direction, speed }, bendFoam = float(0)) => {
4975
+ const waterMaterial = new MeshBasicNodeMaterial({
4976
+ side: DoubleSide,
4977
+ transparent: true
4978
+ });
4979
+ const flowedPosition = positionWorld.xz.sub(direction.mul(speed).mul(time));
4980
+ const ripplePosition = flowedPosition.mul(RIPPLE_SCALE);
4981
+ const drift = time.mul(RIPPLE_SPEED);
4982
+ const sampleRipples = (offset) => mx_fractal_noise_float(vec3(ripplePosition.add(offset).add(vec2(drift, drift.mul(.6))), 0), 3).add(mx_fractal_noise_float(vec3(ripplePosition.add(offset).mul(1.9).sub(vec2(drift.mul(.8), drift)), 1), 2)).mul(.5);
4983
+ const ripple = sampleRipples(vec2(0, 0));
4984
+ const slopeX = sampleRipples(vec2(.02, 0)).sub(ripple);
4985
+ const slopeZ = sampleRipples(vec2(0, .02)).sub(ripple);
4986
+ const normal = vec3(slopeX.mul(-.35 / .02), 1, slopeZ.mul(-.35 / .02)).normalize();
4987
+ const refractedUV = screenUV.add(normal.xz.mul(REFRACTION_STRENGTH));
4988
+ const floorUV = perspectiveDepthToViewZ(viewportDepthTexture(refractedUV), cameraNear, cameraFar).greaterThan(positionView.z).select(screenUV, refractedUV);
4989
+ const depth = positionView.z.sub(perspectiveDepthToViewZ(viewportDepthTexture(floorUV), cameraNear, cameraFar)).max(0);
4990
+ const deepness = smoothstep(0, deepDepth, depth);
4991
+ const waterColor = mix(shallowColor, deepColor, deepness);
4992
+ const floorColor = viewportSharedTexture(floorUV).rgb;
4993
+ const clarity = float(1).sub(smoothstep(0, deepDepth.mul(.6), depth));
4994
+ const tinted = mix(waterColor, floorColor.mul(shallowColor.mul(1.4)), clarity.mul(.8));
4995
+ const eyeDirection = cameraPosition.sub(positionWorld).normalize();
4996
+ const fresnel = pow(float(1).sub(normal.dot(eyeDirection).abs().saturate()), 4);
4997
+ const skyColor = mix(horizonColor, zenithColor, .35);
4998
+ const reflected = mix(tinted, skyColor, fresnel.mul(REFLECTION_STRENGTH));
4999
+ const highlight = pow(reflect(sunDirection.negate(), normal).dot(eyeDirection).max(0), GLINT_POWER);
5000
+ const glints = lightColor.mul(smoothstep(.45, .5, highlight).mul(GLINT_BRIGHTNESS));
5001
+ const shore = float(1).sub(smoothstep(0, foamDepth, depth));
5002
+ const foamNoise = mx_fractal_noise_float(vec3(flowedPosition.mul(FOAM_SCALE), time.mul(.3)), 2).mul(.5).add(.5);
5003
+ const gathered = shore.max(bendFoam);
5004
+ const foam = smoothstep(.55, .6, foamNoise.add(gathered.mul(.5))).mul(gathered);
5005
+ waterMaterial.colorNode = mix(reflected, foamColor, foam).add(glints);
5006
+ return waterMaterial;
5007
+ };
5008
+ //#endregion
5009
+ //#region src/water/constants.ts
5010
+ const RIVER_BEND_FOAM_ATTRIBUTE = "bendFoam";
5011
+ const BEND_FOAM_FULL_RADIUS_WIDTHS = 2;
5012
+ //#endregion
5013
+ //#region src/water/createWaterFlowUniforms.ts
5014
+ const createWaterFlowUniforms = () => ({
5015
+ direction: uniform(new Vector2()),
5016
+ speed: uniform(0)
5017
+ });
5018
+ //#endregion
5019
+ //#region src/nodes/createRiverMaterial.ts
5020
+ const createRiverMaterial = (lightUniforms, skyUniforms, waterUniforms) => createWaterMaterial(lightUniforms, skyUniforms, waterUniforms, createWaterFlowUniforms(), attribute(RIVER_BEND_FOAM_ATTRIBUTE, "float"));
5021
+ //#endregion
4778
5022
  //#region src/nodes/createSkyColorNode.ts
4779
5023
  const HALO_TOWARD_START = .3;
4780
5024
  const HALO_TOWARD_SPAN = .7;
@@ -4911,49 +5155,6 @@ const createStoneMaterial = (options, stoneLight, glowNode = vec3(0)) => {
4911
5155
  return material;
4912
5156
  };
4913
5157
  //#endregion
4914
- //#region src/nodes/createWaterMaterial.ts
4915
- const RIPPLE_SCALE = .08;
4916
- const RIPPLE_SPEED = .05;
4917
- const REFRACTION_STRENGTH = .015;
4918
- const GLINT_POWER = 180;
4919
- const GLINT_BRIGHTNESS = 5;
4920
- const FOAM_SCALE = .6;
4921
- const REFLECTION_STRENGTH = .55;
4922
- const createWaterMaterial = ({ lightColor, sunDirection }, { horizonColor, zenithColor }, { deepColor, deepDepth, foamColor, foamDepth, shallowColor }, { direction, speed }, bendFoam = float(0)) => {
4923
- const waterMaterial = new MeshBasicNodeMaterial({
4924
- side: DoubleSide,
4925
- transparent: true
4926
- });
4927
- const flowedPosition = positionWorld.xz.sub(direction.mul(speed).mul(time));
4928
- const ripplePosition = flowedPosition.mul(RIPPLE_SCALE);
4929
- const drift = time.mul(RIPPLE_SPEED);
4930
- const sampleRipples = (offset) => mx_fractal_noise_float(vec3(ripplePosition.add(offset).add(vec2(drift, drift.mul(.6))), 0), 3).add(mx_fractal_noise_float(vec3(ripplePosition.add(offset).mul(1.9).sub(vec2(drift.mul(.8), drift)), 1), 2)).mul(.5);
4931
- const ripple = sampleRipples(vec2(0, 0));
4932
- const slopeX = sampleRipples(vec2(.02, 0)).sub(ripple);
4933
- const slopeZ = sampleRipples(vec2(0, .02)).sub(ripple);
4934
- const normal = vec3(slopeX.mul(-.35 / .02), 1, slopeZ.mul(-.35 / .02)).normalize();
4935
- const refractedUV = screenUV.add(normal.xz.mul(REFRACTION_STRENGTH));
4936
- const floorUV = perspectiveDepthToViewZ(viewportDepthTexture(refractedUV), cameraNear, cameraFar).greaterThan(positionView.z).select(screenUV, refractedUV);
4937
- const depth = positionView.z.sub(perspectiveDepthToViewZ(viewportDepthTexture(floorUV), cameraNear, cameraFar)).max(0);
4938
- const deepness = smoothstep(0, deepDepth, depth);
4939
- const waterColor = mix(shallowColor, deepColor, deepness);
4940
- const floorColor = viewportSharedTexture(floorUV).rgb;
4941
- const clarity = float(1).sub(smoothstep(0, deepDepth.mul(.6), depth));
4942
- const tinted = mix(waterColor, floorColor.mul(shallowColor.mul(1.4)), clarity.mul(.8));
4943
- const eyeDirection = cameraPosition.sub(positionWorld).normalize();
4944
- const fresnel = pow(float(1).sub(normal.dot(eyeDirection).abs().saturate()), 4);
4945
- const skyColor = mix(horizonColor, zenithColor, .35);
4946
- const reflected = mix(tinted, skyColor, fresnel.mul(REFLECTION_STRENGTH));
4947
- const highlight = pow(reflect(sunDirection.negate(), normal).dot(eyeDirection).max(0), GLINT_POWER);
4948
- const glints = lightColor.mul(smoothstep(.45, .5, highlight).mul(GLINT_BRIGHTNESS));
4949
- const shore = float(1).sub(smoothstep(0, foamDepth, depth));
4950
- const foamNoise = mx_fractal_noise_float(vec3(flowedPosition.mul(FOAM_SCALE), time.mul(.3)), 2).mul(.5).add(.5);
4951
- const gathered = shore.max(bendFoam);
4952
- const foam = smoothstep(.55, .6, foamNoise.add(gathered.mul(.5))).mul(gathered);
4953
- waterMaterial.colorNode = mix(reflected, foamColor, foam).add(glints);
4954
- return waterMaterial;
4955
- };
4956
- //#endregion
4957
5158
  //#region src/nodes/createWaterfallMaterial.ts
4958
5159
  const STREAK_DENSITY = 14;
4959
5160
  const STREAK_LENGTH = .25;
@@ -4972,6 +5173,38 @@ const createWaterfallMaterial = ({ foamColor }) => {
4972
5173
  return waterfallMaterial;
4973
5174
  };
4974
5175
  //#endregion
5176
+ //#region src/vegetation/constants.ts
5177
+ const IMPOSTOR_RESOLUTION = 256;
5178
+ const IMPOSTOR_SWITCH_HEIGHTS = 10;
5179
+ const IMPOSTOR_CROSSFADE_SHARE = .1;
5180
+ const FLOWER_BEND_PER_WIND = .12;
5181
+ const FLOWER_MATRIX_ATTRIBUTE_NAMES = [
5182
+ "flowerMatrix0",
5183
+ "flowerMatrix1",
5184
+ "flowerMatrix2",
5185
+ "flowerMatrix3"
5186
+ ];
5187
+ const FLOWER_COLOR_ATTRIBUTE_NAME = "flowerColor";
5188
+ const GRASS_TRAIL_EXTENT = 16;
5189
+ const GRASS_TRAIL_TEXELS = 64;
5190
+ const GRASS_TRAIL_TEXEL_SIZE = 16 / 64;
5191
+ const GRASS_TRAIL_STAMP_RADIUS = .6;
5192
+ const GRASS_TRAIL_FADE_SECONDS = 1.5;
5193
+ const GRASS_TRAIL_BEND_SHARE = .9;
5194
+ const GRASS_TRAIL_FADE_START_SHARE = .8;
5195
+ const GRASS_TRAIL_FADE_END_SHARE = .95;
5196
+ const GRASS_BEND_PER_WIND = .9;
5197
+ const GRASS_DIP_PER_BEND = .3;
5198
+ //#endregion
5199
+ //#region src/nodes/sampleGrassTrail.ts
5200
+ const sampleGrassTrail = (grassTrail, ground) => {
5201
+ const encoded = texture(grassTrail.texture, fract(ground.div(16))).level(float(0));
5202
+ const offset = ground.sub(grassTrail.center).abs();
5203
+ const reachShare = max(offset.x, offset.y).div(8);
5204
+ const reachFade = float(1).sub(smoothstep(GRASS_TRAIL_FADE_START_SHARE, GRASS_TRAIL_FADE_END_SHARE, reachShare));
5205
+ return encoded.xy.mul(2).sub(1).mul(reachFade);
5206
+ };
5207
+ //#endregion
4975
5208
  //#region src/nodes/setObjectFade.ts
4976
5209
  const setObjectFade = (object, fade) => {
4977
5210
  object.userData[OBJECT_FADE_KEY] = fade;
@@ -5360,6 +5593,7 @@ const createTileStreamer = ({ disposeTile, maxCachedCount, maxPendingCount, requ
5360
5593
  return cachedTile !== void 0 && !cachedTile.isStale || givenUpKeySet.has(key);
5361
5594
  };
5362
5595
  return {
5596
+ checkIsSettled,
5363
5597
  dispose: () => {
5364
5598
  isDisposed = true;
5365
5599
  for (const { tile } of cachedTileMap.values()) disposeTile(tile);
@@ -5380,8 +5614,6 @@ const createTileStreamer = ({ disposeTile, maxCachedCount, maxPendingCount, requ
5380
5614
  },
5381
5615
  get: (key) => cachedTileMap.get(key)?.tile,
5382
5616
  has: (key) => cachedTileMap.has(key),
5383
- isSettled: checkIsSettled,
5384
- pendingKeys: () => [...pendingWantedFrameMap.keys()],
5385
5617
  receive: (key, tile) => {
5386
5618
  const lastWantedFrame = pendingWantedFrameMap.get(key) ?? frame;
5387
5619
  pendingWantedFrameMap.delete(key);
@@ -5503,11 +5735,9 @@ const createTerrainMaterial = (terrainOptions, eye, toonMaterialOptions, waterUn
5503
5735
  normalLocal.assign(mix(normalLocal, attribute("coarseNormal", "vec3"), morphAmount).normalize());
5504
5736
  return mix(positionGeometry, coarsePosition.xyz, morphAmount);
5505
5737
  })();
5506
- terrainMaterial.colorNode = vec4(varying(mix(attribute("color", "vec3"), attribute("coarseColor", "vec3"), morphAmount)).mul(createWetDarkeningNode(toonMaterialOptions.lightUniforms)), 1);
5507
- if (waterUniforms) {
5508
- const { lightUniforms } = toonMaterialOptions;
5509
- terrainMaterial.emissiveNode = createRimNode(lightUniforms).add(createWetSheenNode(lightUniforms)).add(createCausticsNode(lightUniforms, waterUniforms));
5510
- }
5738
+ const { lightUniforms } = toonMaterialOptions;
5739
+ terrainMaterial.colorNode = vec4(varying(mix(attribute("color", "vec3"), attribute("coarseColor", "vec3"), morphAmount)).mul(createWetDarkeningNode(lightUniforms)), 1);
5740
+ if (waterUniforms) terrainMaterial.emissiveNode = createRimNode(lightUniforms).add(createWetSheenNode(lightUniforms)).add(createCausticsNode(lightUniforms, waterUniforms));
5511
5741
  return terrainMaterial;
5512
5742
  };
5513
5743
  //#endregion
@@ -5835,12 +6065,12 @@ const bakeImpostor = (renderer, parts, resolution) => {
5835
6065
  camera.position.z = radius + 1;
5836
6066
  camera.updateMatrixWorld();
5837
6067
  const bakeScene = new Scene();
5838
- const bakeMeshes = parts.map(({ color: partColor, geometry, opacityNode }) => {
6068
+ const bakeMeshes = parts.map(({ color: partColor, geometry, maskNode }) => {
5839
6069
  const albedoMaterial = new MeshBasicNodeMaterial({ side: DoubleSide });
5840
6070
  const normalMaterial = new MeshBasicNodeMaterial({ side: DoubleSide });
5841
6071
  albedoMaterial.outputNode = vec4(color(new Color(partColor)), 1);
5842
- normalMaterial.outputNode = vec4(normalView.mul(.5).add(.5), 1);
5843
- if (opacityNode) albedoMaterial.maskNode = normalMaterial.maskNode = opacityNode.greaterThan(.5);
6072
+ normalMaterial.outputNode = vec4(normalViewGeometry.mul(.5).add(.5), 1);
6073
+ if (maskNode) albedoMaterial.maskNode = normalMaterial.maskNode = maskNode;
5844
6074
  const mesh = new Mesh(geometry, albedoMaterial);
5845
6075
  bakeScene.add(mesh);
5846
6076
  return {
@@ -5909,18 +6139,21 @@ const computeGrassBlade = (segmentCount) => {
5909
6139
  };
5910
6140
  };
5911
6141
  //#endregion
5912
- //#region src/vegetation/constants.ts
5913
- const IMPOSTOR_RESOLUTION = 256;
5914
- const IMPOSTOR_SWITCH_HEIGHTS = 10;
5915
- const IMPOSTOR_CROSSFADE_SHARE = .1;
5916
- const FLOWER_BEND_PER_WIND = .12;
5917
- const FLOWER_MATRIX_ATTRIBUTE_NAMES = [
5918
- "flowerMatrix0",
5919
- "flowerMatrix1",
5920
- "flowerMatrix2",
5921
- "flowerMatrix3"
5922
- ];
5923
- const FLOWER_COLOR_ATTRIBUTE_NAME = "flowerColor";
6142
+ //#region src/vegetation/computeGrassTrailCell.ts
6143
+ const computeGrassTrailCell = (coordinate, texelSize) => Math.floor(coordinate / texelSize);
6144
+ //#endregion
6145
+ //#region src/vegetation/computeGrassTrailTexel.ts
6146
+ const computeGrassTrailTexel = (cell) => (cell % 64 + 64) % 64;
6147
+ //#endregion
6148
+ //#region src/vegetation/computeGrassTrailTexelIndex.ts
6149
+ const computeGrassTrailTexelIndex = (cellX, cellZ) => computeGrassTrailTexel(cellZ) * 64 + computeGrassTrailTexel(cellX);
6150
+ //#endregion
6151
+ //#region src/vegetation/computeImpostorFade.ts
6152
+ const computeImpostorFade = (distance, impostorHeight) => {
6153
+ const switchDistance = impostorHeight * 10;
6154
+ const halfBand = switchDistance * IMPOSTOR_CROSSFADE_SHARE / 2;
6155
+ return MathUtils.smoothstep(distance, switchDistance - halfBand, switchDistance + halfBand);
6156
+ };
5924
6157
  //#endregion
5925
6158
  //#region src/vegetation/createFlowerGeometry.ts
5926
6159
  const createFlowerGeometry = () => {
@@ -6035,6 +6268,70 @@ const createFlowerTileGeometry = (matrices, colors) => {
6035
6268
  return geometry;
6036
6269
  };
6037
6270
  //#endregion
6271
+ //#region src/vegetation/createGrassBladePoint.ts
6272
+ const createGrassBladePoint = ({ bladeHeight, captured, grassTrail, ground, offset, size, up, windUniforms }) => {
6273
+ const bend = up.mul(up);
6274
+ const wind = createWindNode(windUniforms, ground).mul(GRASS_BEND_PER_WIND).mul(bend);
6275
+ const trailBend = sampleGrassTrail(grassTrail, ground).mul(GRASS_TRAIL_BEND_SHARE).mul(bend);
6276
+ const trailOffset = trailBend.mul(bladeHeight).mul(size);
6277
+ const height = up.mul(bladeHeight).mul(size).sub(wind.length().mul(bladeHeight).mul(size).mul(GRASS_DIP_PER_BEND)).sub(trailBend.length().mul(bladeHeight).mul(size).mul(GRASS_DIP_PER_BEND));
6278
+ return vec3(ground.x.add(offset.x).add(wind.x.mul(bladeHeight).mul(size)).add(trailOffset.x), captured.a.add(height), ground.y.add(offset.y).add(wind.y.mul(bladeHeight).mul(size)).add(trailOffset.y));
6279
+ };
6280
+ //#endregion
6281
+ //#region src/vegetation/createGrassCell.ts
6282
+ const MIN_GREENNESS = .05;
6283
+ const createGrassCell = ({ cameraGround, density, groundCapture, index, ring, waterUniforms }) => {
6284
+ const { cellsPerSide, fadeEnd, fadeStart, innerRadius, scale, spacing } = ring;
6285
+ const row = index.div(cellsPerSide).floor();
6286
+ const column = index.sub(row.mul(cellsPerSide));
6287
+ const gridOrigin = cameraGround.div(spacing).floor().mul(spacing);
6288
+ const cell = vec2(column, row).sub(cellsPerSide / 2).mul(spacing).add(gridOrigin);
6289
+ const seed = cell.x.mul(127.1).add(cell.y.mul(311.7));
6290
+ const ground = cell.add(vec2(hash(seed), hash(seed.add(1))).sub(.5).mul(spacing));
6291
+ const { captured, isInsideCapture } = sampleGroundCapture(groundCapture, ground);
6292
+ const greenness = captured.g.sub(captured.r.max(captured.b));
6293
+ const isGrown = isInsideCapture.mul(step(MIN_GREENNESS, greenness)).mul(step(waterUniforms.level, captured.a)).mul(step(hash(seed.add(2)), density));
6294
+ const distance = ground.distance(cameraGround);
6295
+ const fade = smoothstep(innerRadius, innerRadius + spacing * 4, distance).mul(float(1).sub(smoothstep(fadeStart, fadeEnd, distance)));
6296
+ const size = hash(seed.add(3)).mul(.5).add(.75).mul(fade).mul(isGrown).mul(scale);
6297
+ return {
6298
+ angle: hash(seed.add(4)).mul(Math.PI * 2),
6299
+ captured,
6300
+ ground,
6301
+ size
6302
+ };
6303
+ };
6304
+ //#endregion
6305
+ //#region src/vegetation/createGrassCulling.ts
6306
+ const createGrassCulling = ({ bladeHeight, cameraGround, clipFromModel, density, grassTrail, groundCapture, ring, segmentCount, waterUniforms, windUniforms }) => createInstanceCulling({
6307
+ count: ring.cellsPerSide * ring.cellsPerSide,
6308
+ indexCount: computeGrassBlade(segmentCount).indices.length,
6309
+ isVisible: (index) => {
6310
+ const { captured, ground, size } = createGrassCell({
6311
+ cameraGround,
6312
+ density,
6313
+ groundCapture,
6314
+ index,
6315
+ ring,
6316
+ waterUniforms
6317
+ });
6318
+ const isInView = (up) => createFrustumVisibility(clipFromModel, createGrassBladePoint({
6319
+ bladeHeight,
6320
+ captured,
6321
+ grassTrail,
6322
+ ground,
6323
+ offset: vec2(0),
6324
+ size,
6325
+ up,
6326
+ windUniforms
6327
+ }));
6328
+ const root = createFrustumVisibility(clipFromModel, vec3(ground.x, captured.a, ground.y));
6329
+ const tip = isInView(float(1));
6330
+ const top = createFrustumVisibility(clipFromModel, vec3(ground.x, captured.a.add(size.mul(bladeHeight)), ground.y));
6331
+ return step(CULLING_MIN_SIZE, size).mul(max(max(root, top), tip));
6332
+ }
6333
+ });
6334
+ //#endregion
6038
6335
  //#region src/vegetation/createGrassGeometry.ts
6039
6336
  const createGrassGeometry = (segmentCount, bladeCount) => {
6040
6337
  const { indices, positions } = computeGrassBlade(segmentCount);
@@ -6047,9 +6344,7 @@ const createGrassGeometry = (segmentCount, bladeCount) => {
6047
6344
  };
6048
6345
  //#endregion
6049
6346
  //#region src/vegetation/createGrassMaterial.ts
6050
- const MIN_GREENNESS = .05;
6051
- const BEND_PER_WIND = .9;
6052
- const createGrassMaterial = ({ bladeHeight, bladeWidth, cameraGround, density, groundCapture, lightUniforms, rampTexture, ring, waterUniforms, windUniforms }) => {
6347
+ const createGrassMaterial = ({ bladeHeight, bladeWidth, cameraGround, cellIndex, density, grassTrail, groundCapture, lightUniforms, rampTexture, ring, waterUniforms, windUniforms }) => {
6053
6348
  const grassMaterial = createToonMaterial({
6054
6349
  isOutlined: false,
6055
6350
  lightUniforms,
@@ -6057,32 +6352,50 @@ const createGrassMaterial = ({ bladeHeight, bladeWidth, cameraGround, density, g
6057
6352
  });
6058
6353
  grassMaterial.emissiveNode = createWetSheenNode(lightUniforms);
6059
6354
  grassMaterial.side = DoubleSide;
6060
- const { cellsPerSide, fadeEnd, fadeStart, innerRadius, scale, spacing } = ring;
6061
- const index = float(instanceIndex);
6062
- const row = index.div(cellsPerSide).floor();
6063
- const column = index.sub(row.mul(cellsPerSide));
6064
- const gridOrigin = cameraGround.div(spacing).floor().mul(spacing);
6065
- const cell = vec2(column, row).sub(cellsPerSide / 2).mul(spacing).add(gridOrigin);
6066
- const seed = cell.x.mul(127.1).add(cell.y.mul(311.7));
6067
- const ground = cell.add(vec2(hash(seed), hash(seed.add(1))).sub(.5).mul(spacing));
6068
- const { captured, isInsideCapture } = sampleGroundCapture(groundCapture, ground);
6069
- const greenness = captured.g.sub(captured.r.max(captured.b));
6070
- const isGrown = isInsideCapture.mul(step(MIN_GREENNESS, greenness)).mul(step(waterUniforms.level, captured.a)).mul(step(hash(seed.add(2)), density));
6071
- const distance = ground.distance(cameraGround);
6072
- const fade = smoothstep(innerRadius, innerRadius + spacing * 4, distance).mul(float(1).sub(smoothstep(fadeStart, fadeEnd, distance)));
6073
- const size = hash(seed.add(3)).mul(.5).add(.75).mul(fade).mul(isGrown).mul(scale);
6074
- const angle = hash(seed.add(4)).mul(Math.PI * 2);
6075
- const across = positionGeometry.x.mul(bladeWidth).mul(size);
6355
+ const { angle, captured, ground, size } = createGrassCell({
6356
+ cameraGround,
6357
+ density,
6358
+ groundCapture,
6359
+ index: cellIndex,
6360
+ ring,
6361
+ waterUniforms
6362
+ });
6076
6363
  const up = positionGeometry.y;
6077
- const wind = createWindNode(windUniforms, ground).mul(BEND_PER_WIND).mul(up.mul(up));
6078
- const bladeHeightNode = up.mul(bladeHeight).mul(size).sub(wind.length().mul(bladeHeight).mul(size).mul(.3));
6079
- grassMaterial.positionNode = vec3(ground.x.add(across.mul(cos(angle))).add(wind.x.mul(bladeHeight).mul(size)), captured.a.add(bladeHeightNode), ground.y.add(across.mul(sin(angle))).add(wind.y.mul(bladeHeight).mul(size)));
6364
+ grassMaterial.positionNode = createGrassBladePoint({
6365
+ bladeHeight,
6366
+ captured,
6367
+ grassTrail,
6368
+ ground,
6369
+ offset: vec2(cos(angle), sin(angle)).mul(positionGeometry.x.mul(bladeWidth).mul(size)),
6370
+ size,
6371
+ up,
6372
+ windUniforms
6373
+ });
6080
6374
  grassMaterial.normalNode = cameraViewMatrix.mul(vec4(0, 1, 0, 0)).xyz;
6081
6375
  const groundColor = varying(captured.rgb);
6082
6376
  grassMaterial.colorNode = mix(groundColor.mul(.72), groundColor.mul(1.12).add(vec3(.03, .03, 0)), up).mul(createWetDarkeningNode(lightUniforms));
6083
6377
  return grassMaterial;
6084
6378
  };
6085
6379
  //#endregion
6380
+ //#region src/vegetation/createGrassTrail.ts
6381
+ const createGrassTrail = () => {
6382
+ const texelCount = 4096;
6383
+ const data = new Uint8Array(texelCount * 4);
6384
+ for (let index = 0; index < data.length; index++) data[index] = index % 4 === 3 ? 255 : 128;
6385
+ const texture = new DataTexture(data, 64, 64, RGBAFormat);
6386
+ texture.magFilter = LinearFilter;
6387
+ texture.minFilter = LinearFilter;
6388
+ texture.wrapS = RepeatWrapping;
6389
+ texture.wrapT = RepeatWrapping;
6390
+ return {
6391
+ bends: new Float32Array(texelCount * 2),
6392
+ cells: new Float64Array(texelCount * 2).fill(NaN),
6393
+ center: uniform(new Vector2()),
6394
+ data,
6395
+ texture
6396
+ };
6397
+ };
6398
+ //#endregion
6086
6399
  //#region src/vegetation/createGroundCapture.ts
6087
6400
  const createGroundCapture = (size, resolution) => {
6088
6401
  const renderTarget = new RenderTarget(resolution, resolution, { type: HalfFloatType });
@@ -6103,6 +6416,52 @@ const createGroundCapture = (size, resolution) => {
6103
6416
  };
6104
6417
  };
6105
6418
  //#endregion
6419
+ //#region src/vegetation/createPlantCulling.ts
6420
+ const createPlantCulling = ({ attribute, bounds: { bottom, halfWidth, height }, clipFromModel, drawDistance, eye, indexCount }) => {
6421
+ const middle = bottom + height / 2;
6422
+ const boxPoints = [
6423
+ [
6424
+ 0,
6425
+ bottom,
6426
+ 0
6427
+ ],
6428
+ [
6429
+ 0,
6430
+ bottom + height,
6431
+ 0
6432
+ ],
6433
+ [
6434
+ halfWidth,
6435
+ middle,
6436
+ 0
6437
+ ],
6438
+ [
6439
+ -halfWidth,
6440
+ middle,
6441
+ 0
6442
+ ],
6443
+ [
6444
+ 0,
6445
+ middle,
6446
+ halfWidth
6447
+ ],
6448
+ [
6449
+ 0,
6450
+ middle,
6451
+ -halfWidth
6452
+ ]
6453
+ ];
6454
+ return createInstanceCulling({
6455
+ count: attribute.count / 4,
6456
+ indexCount,
6457
+ isVisible: (instance) => {
6458
+ const instanceMatrix = createInstanceMatrixNode(attribute, instance);
6459
+ const isNear = step(distance(instanceMatrix.mul(vec4(0, 0, 0, 1)).xyz, eye), drawDistance);
6460
+ return boxPoints.map(([x, y, z]) => createFrustumVisibility(clipFromModel, instanceMatrix.mul(vec4(x, y, z, 1)).xyz)).reduce((visible, point) => max(visible, point)).mul(isNear);
6461
+ }
6462
+ });
6463
+ };
6464
+ //#endregion
6106
6465
  //#region src/vegetation/renderGroundCapture.ts
6107
6466
  const CLEAR_COLOR = new Color();
6108
6467
  const previousClearColor = new Color();
@@ -6129,9 +6488,44 @@ const renderGroundCapture = (renderer, scene, { camera, center, material, render
6129
6488
  scene.backgroundNode = previousBackgroundNode;
6130
6489
  };
6131
6490
  //#endregion
6132
- //#region src/water/constants.ts
6133
- const RIVER_BEND_FOAM_ATTRIBUTE = "bendFoam";
6134
- const BEND_FOAM_FULL_RADIUS_WIDTHS = 2;
6491
+ //#region src/vegetation/stepGrassTrail.ts
6492
+ const encodeBend = (bend) => Math.round((Math.min(Math.max(bend, -1), 1) * .5 + .5) * 255);
6493
+ const stepGrassTrail = (trail, position, velocity, delta) => {
6494
+ const { bends, cells, data, texture } = trail;
6495
+ const decay = Math.exp(-delta / GRASS_TRAIL_FADE_SECONDS);
6496
+ for (let index = 0; index < bends.length; index++) bends[index] = (bends[index] ?? 0) * decay;
6497
+ const centreCellX = computeGrassTrailCell(position.x, GRASS_TRAIL_TEXEL_SIZE);
6498
+ const centreCellZ = computeGrassTrailCell(position.y, GRASS_TRAIL_TEXEL_SIZE);
6499
+ trail.center.value.set((centreCellX + .5) * GRASS_TRAIL_TEXEL_SIZE, (centreCellZ + .5) * GRASS_TRAIL_TEXEL_SIZE);
6500
+ const firstCellOffset = -32;
6501
+ for (let row = 0; row < 64; row++) for (let column = 0; column < 64; column++) {
6502
+ const cellX = centreCellX + firstCellOffset + column;
6503
+ const cellZ = centreCellZ + firstCellOffset + row;
6504
+ const texelIndex = computeGrassTrailTexelIndex(cellX, cellZ);
6505
+ if (cells[texelIndex * 2] === cellX && cells[texelIndex * 2 + 1] === cellZ) continue;
6506
+ cells[texelIndex * 2] = cellX;
6507
+ cells[texelIndex * 2 + 1] = cellZ;
6508
+ bends[texelIndex * 2] = 0;
6509
+ bends[texelIndex * 2 + 1] = 0;
6510
+ }
6511
+ const speed = Math.hypot(velocity.x, velocity.y);
6512
+ if (speed > 0) {
6513
+ const stampCellRadius = Math.ceil(GRASS_TRAIL_STAMP_RADIUS / GRASS_TRAIL_TEXEL_SIZE);
6514
+ for (let offsetZ = -3; offsetZ <= stampCellRadius; offsetZ++) for (let offsetX = -3; offsetX <= stampCellRadius; offsetX++) {
6515
+ const cellX = centreCellX + offsetX;
6516
+ const cellZ = centreCellZ + offsetZ;
6517
+ if (Math.hypot((cellX + .5) * .25 - position.x, (cellZ + .5) * .25 - position.y) > .6) continue;
6518
+ const texelIndex = computeGrassTrailTexelIndex(cellX, cellZ);
6519
+ bends[texelIndex * 2] = velocity.x / speed;
6520
+ bends[texelIndex * 2 + 1] = velocity.y / speed;
6521
+ }
6522
+ }
6523
+ for (let index = 0; index < bends.length / 2; index++) {
6524
+ data[index * 4] = encodeBend(bends[index * 2] ?? 0);
6525
+ data[index * 4 + 1] = encodeBend(bends[index * 2 + 1] ?? 0);
6526
+ }
6527
+ texture.needsUpdate = true;
6528
+ };
6135
6529
  //#endregion
6136
6530
  //#region src/water/createRiverGeometry.ts
6137
6531
  const createRiverGeometry = (course) => {
@@ -6194,12 +6588,6 @@ const createUnderwaterFogState = () => ({
6194
6588
  underwaterDensity: 0
6195
6589
  });
6196
6590
  //#endregion
6197
- //#region src/water/createWaterFlowUniforms.ts
6198
- const createWaterFlowUniforms = () => ({
6199
- direction: uniform(new Vector2()),
6200
- speed: uniform(0)
6201
- });
6202
- //#endregion
6203
6591
  //#region src/water/createWaterUniforms.ts
6204
6592
  const createWaterUniforms = () => ({
6205
6593
  causticStrength: uniform(0),
@@ -6314,4 +6702,4 @@ const computeOutlineDistance = (outline, x, z) => {
6314
6702
  return isInside ? 0 : Math.sqrt(nearestSquared);
6315
6703
  };
6316
6704
  //#endregion
6317
- export { A4_FREQUENCY, A4_PITCH, AIR_LOCOMOTION_STATES, AnchoredCascadeShadowNode, AntialiasingMode, BEND_FOAM_FULL_RADIUS_WIDTHS, CLIMB_JUMP_STAMINA_COST, CLIMB_LOCOMOTION_STATES, CLIMB_REGRAB_SECONDS, CLIMB_STAMINA_PER_SECOND, CLIMB_START_STAMINA, COOL_RAMP_ROW_BASE, CharacterMaterialKind, DASH_STAMINA_COST, DEFAULT_LIGHT_AREA, DEFAULT_RAMP_WIDTH, DEFAULT_SKY_GRADIENT, DEFAULT_SKY_SHAPE, DESATURATION_WEIGHTS, EMISSION_ALPHA_FLOOR, FIELD_SELECTOR, FLAT_LIGHT_MAP, FLOWER_BEND_PER_WIND, FLOWER_COLOR_ATTRIBUTE_NAME, FLOWER_MATRIX_ATTRIBUTE_NAMES, FOCUS_KEY_CODES, FOLLOW_CAMERA_ARM_STEP, FOLLOW_CAMERA_CLEARANCE, FOLLOW_CAMERA_DEFAULT_SETTINGS, FOLLOW_CAMERA_DISTANCE_PER_ZOOM_STEP, FOLLOW_CAMERA_EASE_OUT_SPEED, FOLLOW_CAMERA_FOV, FOLLOW_CAMERA_MAX_DISTANCE, FOLLOW_CAMERA_MAX_PITCH, FOLLOW_CAMERA_MIN_DISTANCE, FOLLOW_CAMERA_MIN_PITCH, FOLLOW_CAMERA_NEUTRAL_SENSITIVITY, FOLLOW_CAMERA_PIVOT_SHARE, FREE_CAMERA_BASE_SPEED, FREE_CAMERA_CLEARANCE, FREE_CAMERA_MAX_PITCH, FREE_CAMERA_SPEED_PER_HEIGHT, GAMEPAD_BUTTONS, GAMEPAD_LOOK_RADIANS_PER_SECOND, GAMEPAD_STICK_DEADZONE, GAME_MINUTES_PER_SECOND, GAUSSIAN_REACH_WIDTHS, GENSHIN_TONE_CONTRAST, GENSHIN_TONE_EXPOSURE, GENSHIN_TONE_MAPPING, GLIDE_STAMINA_PER_SECOND, GROUND_CONTACT_DISTANCE, GROUND_LOCOMOTION_STATES, GROUND_NORMAL_SPAN, GROUND_PRESS_SPEED, GamepadButton, GroundLayer, GroundLayers, HALF_LAMBERT_OFFSET, HALF_LAMBERT_SCALE, IMPOSTOR_CROSSFADE_SHARE, IMPOSTOR_RESOLUTION, IMPOSTOR_SWITCH_HEIGHTS, InputAction, InputActionBindingMap, InputActions, KEY_CODE_BACKWARD, KEY_CODE_DOWN, KEY_CODE_FORWARD, KEY_CODE_LEFT, KEY_CODE_RIGHT, KEY_CODE_UP, LEAF_SHAPE_KEPT_SHARE, LEAF_SHAPE_WIDTH, LEAST_DIVISOR, LIGHTNING_BOLT_BRIGHTNESS, LIGHTNING_BOLT_COLOR, LIGHTNING_BOLT_OPTIONS, LIGHTNING_FLASH_AMBIENT, LIGHTNING_FLASH_COLOR, LIGHTNING_FLASH_DECAY_SECONDS, LIGHTNING_FLASH_END, LIGHTNING_FLASH_PULSES, LIGHTNING_FLASH_SKY, LIGHTNING_MAX_DISTANCE, LIGHTNING_MIN_DISTANCE, LocomotionState, MAXIMUM_FACE_THRESHOLD, MAXIMUM_WINDOW_FLOOR, MAX_BYTE, MAX_STEPS_PER_FRAME, MAX_TILE_ATTEMPTS, MIDI_VELOCITY_MAX, MINIMUM_FACE_THRESHOLD, MINIMUM_OUTLINE_KNOT_SPAN, MINIMUM_RAMP_WIDTH_VERTEX, MINUTES_PER_DAY, MMD_BONE_NAME_MAP, MOUSE_BUTTONS, MOUSE_LOOK_MAX_PIXELS_PER_EVENT, MOUSE_LOOK_RADIANS_PER_PIXEL, MUSIC_EXPRESSION_WINDOW_SECONDS, MUSIC_LOOKAHEAD_SECONDS, MUSIC_NOISE_BAND_CENTRES, MUSIC_NOISE_LENGTH, MUSIC_SCHEDULE_INTERVAL_MS, MmdBoneName, MouseButton, NEUTRAL_LIGHT_MAP_GREEN, OBJECT_FADE_KEY, OBJECT_SURFACE_KEY, OUTLINE_MAIN_TEXTURE_SHARE, OUTLINE_PROJECTION_SCALE, OUTLINE_WIDTH_SCALE, ObjectSurface, PMX_UNIT_METRES, POSE_AIR_STANCES, POSE_ARM_BEND_RADIANS, POSE_ARM_CHAINS, POSE_ARM_LOWER_RADIANS, POSE_BREATH_SECONDS, POSE_CHEST_BREATH_RADIANS, POSE_CROSSFADE_SECONDS, POSE_GAITS, POSE_SHOULDER_BREATH_RADIANS, PRECIPITATION_COUNT, PRECIPITATION_SETTINGS_MAP, PRECIPITATION_SWAY_SPEED, PRECIPITATION_VOLUME_HEIGHT, PRECIPITATION_VOLUME_SIZE, PmxBoneFlag, PmxJointKind, PmxMaterialFlag, PmxMorphKind, PmxPhysicsMode, PmxReader, PmxRigidBodyShape, PmxSphereMode, PmxTextEncoding, PmxWeightDeform, PrecipitationKind, QualityTier, QualityTierSettingsMap, RAMP_ROW_BASE, RAMP_ROW_STEP, REGION_FLOORS, RELEASE_TIME_CONSTANTS, RIVER_BEND_FOAM_ATTRIBUTE, RampLayout, RoofKind, SHARED_TOON_RAMP_SHADES, SOUND_EFFECT_BAND_EDGES, SOUND_EFFECT_FRAME_LENGTH, SPECTRAL_ANGULAR_BIN_COUNT, SPECTRAL_RADIAL_BIN_COUNT, SPHERE_CAST_STRIDE_SHARE, SPLASH_COUNT, SPLASH_LIFETIME, SPLASH_LIFT, SPLASH_OPACITY, SPLASH_RADIUS, SPLASH_SIZE, SPRINT_STAMINA_PER_SECOND, STAMINA_MAX, STAMINA_REFILL_DELAY_SECONDS, STAMINA_REFILL_PER_SECOND, STAMINA_REFILL_STATES, STEEP_SLIDE_SPEED, STONE_DARKENING_TOP, STONE_HARMONIC_COUNT, STONE_HEIGHT_FALLOFF, STONE_MASK_OUTPUT, STONE_RAMP_KNOT_COUNT, STONE_SHADOW_EXPONENT, SUN_REDRAW_COSINE, SURFACE_DETAIL_BAND_SIGMAS, SURFACE_DETAIL_RENDER_GAIN, SURFACE_OCTAVE_TEXEL_FREQUENCIES, SWIM_DASH_STAMINA_COST, SWIM_DASH_STAMINA_PER_SECOND, SWIM_STROKE_SECONDS, SWIM_STROKE_STAMINA_COST, SharedToonOutlinePassNode, StoneLightingModel, StoneNodeMaterial, TERRAIN_CELL_SIZE, TERRAIN_HEIGHT_PADDING, TERRAIN_LAYER, TERRAIN_RING_INITIAL_TILE_COUNT, TILE_INDEX_OFFSET, TILE_INDEX_SPAN, TONE_CONTRAST_OFFSET, TONE_CURVE_FLOOR, TONE_CURVE_LIFT, TOON_HIGH, TOON_LOW, TerrainFeatureKind, TerrainFeatureKindBlendMap, ToonNodeMaterial, WALK_MOVE_MAGNITUDE, WALL_PRESS_SPEED, WALL_PROBE_DISTANCE, WATER_LOCOMOTION_STATES, WEATHER_SETTINGS_MAP, WEATHER_TRANSITION_SECONDS, WET_DARKENING, WET_SHEEN_POWER, WET_SHEEN_STRENGTH, WeatherKind, addSmoothLoop, advanceGameClock, advanceStridePhase, applyLightningFlash, applyPrecipitationSettings, applySkyState, applyStoneLight, applyWeatherState, attachInspector, bakeImpostor, blendGridNodes, blendWeatherState, checkSunTurned, checkTerrainBoundsOverlap, checkTerrainDrawsChanged, checkTerrainTileCasts, checkTransparentTexels, collectMusicNotes, collectMusicSegments, computeCharacterPose, computeGradeLut, computeGrassBlade, computeLeafCards, computeLightningBolt, computeLightningFlash, computeLocomotionState, computeNoiseSamples, computeOriginShift, computeOutlineDistance, computeRampValues, computeScatterPoints, computeSoundEffectSamples, computeStatueSurface, computeStoneDarkening, computeStoneHarmonics, computeStoneRampCoordinate, computeSunDirection, computeSurfaceOctaves, computeTerrainIndices, computeTerrainTile, computeTreeTubes, computeWhiteBalance, createBoxesGeometry, createBuildingGeometry, createCausticsNode, createCharacterController, createCharacterMaterial, createCharacterPoseRotations, createCharacterPoser, createCharacterShadingInputs, createCharacterShadingNode, createCloudAtlasTexture, createCloudBandSprite, createCloudLayerNode, createCloudLayerProfileTexture, createCloudLayerTexture, createCloudLayerTextures, createCloudLayerUniforms, createDitherFadeNode, createFaceDraw, createFaceShadeNode, createFixedStepLoop, createFlowerGeometry, createFlowerMaterial, createFlowerTileGeometry, createFogUniforms, createFollowCamera, createFreeCamera, createGameOutlineMaterial, createGaussianHillsHeight, createGenshinRenderer, createGodraysLight, createGradeLutTexture, createGrassGeometry, createGrassMaterial, createGroundCapture, createGroundLayerWeights, createGroundPaintColor, createGroundQuery, createHeightFogNode, createImpostorMaterial, createIndexedGeometry, createInput, createInstancedMesh, createInstrumentWave, createLandmarkCollider, createLatheStackGeometry, createLeafMaterial, createLeafShapeNode, createLightUniforms, createLightningBoltGeometry, createLightningBoltMaterial, createMusicPlayer, createNoiseBuffer, createObjectFadeNode, createObjectSurfaceNode, createOcclusionNode, createOutlineColorNode, createOutlineMaterial, createOutlineScaleNode, createPavingGeometry, createPavingStoneGeometry, createPmxGeometry, createPmxMesh, createPmxSkeleton, createPmxTexture, createPmxToonTexture, createPostPipeline, createPostUniforms, createPrecipitationGeometry, createPrecipitationMaterial, createPrecipitationUniforms, createRampColumnNode, createRampTexture, createRampUvNode, createResidualHeight, createRimNode, createRiverGeometry, createSeededRandom, createShadingRegionNode, createSightNode, createSightUniforms, createSimplexNoise, createSkyColorNode, createSkyGradientTexture, createSkyNode, createSkyState, createSkyUniforms, createSoundEffectBuffer, createSplashMaterial, createStamina, createStatueGeometries, createStoneGlowNode, createStoneLightUniforms, createStoneMaterial, createSunLight, createSunVisibilityNode, createSurfaceDetailNode, createTerrainFeaturesBlend, createTerrainFeaturesHeight, createTerrainMaterial, createTerrainRing, createTerrainSelection, createTerrainShapeHeight, createTerrainTileGeometry, createTileStreamer, createToneNode, createToonMaterial, createToonThresholdNode, createTreeGeometry, createUnderwaterFogState, createWaterFlowUniforms, createWaterMaterial, createWaterUniforms, createWaterfallGeometry, createWaterfallMaterial, createWetDarkeningNode, createWetSheenNode, createWindNode, createWindUniforms, fileByCell, findSkinnedMesh, getCliffBlend, getCloudAtlasColumns, getCloudSunColors, getDesaturatedColour, getGameOutlineOffset, getGaussianHillBlend, getMusicRecordingGain, getMusicRecordingRate, getOutlineDepth, getOutlineScale, getParentTerrainTileKey, getPlateauBlend, getRampColumn, getRampRow, getRampWidth, getRidgeBlend, getScreenDirection, getSegmentBounds, getShadingRegion, getSharedToonRamp, getSoundEffectBandBins, getSpectralBin, getTerrainFeatureBounds, getTerrainMorphStart, getTerrainOverlayBounds, getTerrainShapeLevel, getTerrainTileBounds, getTerrainTileColumn, getTerrainTileKey, getTerrainTileLevel, getTerrainTileRow, getToneColour, getToonThreshold, measureSegment, mergeGeometryParts, orderByViewDepth, parsePmx, parsePmxBones, parsePmxJoints, parsePmxMaterials, parsePmxMorphs, parsePmxRigidBodies, parsePmxVertices, placeCloudBand, renderGroundCapture, renderMusicSegment, resolveTerrainDraws, sampleGroundCapture, sampleGroundLayerField, sampleSkyState, sampleTerrainResidualFade, sampleTreeNormalField, scheduleMusicExpression, scheduleMusicNote, scheduleMusicRecording, selectMusicSample, selectRegionNode, selectTerrainTiles, setObjectFade, setObjectSurface, synthesizeCloudLayerTextures, synthesizeSpectralNoise, toSceneColor, toneMapGenshin, toneMapGenshinNode, transformFourier, transformFourierGrid, updateFaceDraw, updateUnderwaterFog, writeCloudLayerTexture, writeQuadIndices, writeTerrainRingIndices, writeTerrainRingTile };
6705
+ export { A4_FREQUENCY, A4_PITCH, AIR_LOCOMOTION_STATES, AnchoredCascadeShadowNode, AntialiasingMode, BEND_FOAM_FULL_RADIUS_WIDTHS, CLIMB_JUMP_STAMINA_COST, CLIMB_LOCOMOTION_STATES, CLIMB_REGRAB_SECONDS, CLIMB_STAMINA_PER_SECOND, CLIMB_START_STAMINA, COOL_RAMP_ROW_BASE, CULLING_FRUSTUM_MARGIN, CULLING_INDEX_COUNT_INDEX, CULLING_INDIRECT_ARGUMENT_COUNT, CULLING_INSTANCE_COUNT_INDEX, CULLING_MATRIX_COLUMN_COUNT, CULLING_MATRIX_ELEMENT_COUNT, CULLING_MIN_SIZE, CharacterMaterialKind, DASH_STAMINA_COST, DEFAULT_LIGHT_AREA, DEFAULT_RAMP_WIDTH, DEFAULT_SKY_GRADIENT, DEFAULT_SKY_SHAPE, DESATURATION_WEIGHTS, EMISSION_ALPHA_FLOOR, FIELD_SELECTOR, FLAT_LIGHT_MAP, FLOWER_BEND_PER_WIND, FLOWER_COLOR_ATTRIBUTE_NAME, FLOWER_MATRIX_ATTRIBUTE_NAMES, FOCUS_KEY_CODES, FOLLOW_CAMERA_ARM_STEP, FOLLOW_CAMERA_CLEARANCE, FOLLOW_CAMERA_DEFAULT_SETTINGS, FOLLOW_CAMERA_DISTANCE_PER_ZOOM_STEP, FOLLOW_CAMERA_EASE_OUT_SPEED, FOLLOW_CAMERA_FOV, FOLLOW_CAMERA_MAX_DISTANCE, FOLLOW_CAMERA_MAX_PITCH, FOLLOW_CAMERA_MIN_DISTANCE, FOLLOW_CAMERA_MIN_PITCH, FOLLOW_CAMERA_NEUTRAL_SENSITIVITY, FOLLOW_CAMERA_PIVOT_SHARE, FOLLOW_CAMERA_SLOPE_PITCH_SPEED, FREE_CAMERA_BASE_SPEED, FREE_CAMERA_CLEARANCE, FREE_CAMERA_MAX_PITCH, FREE_CAMERA_SPEED_PER_HEIGHT, GAMEPAD_BUTTONS, GAMEPAD_LOOK_RADIANS_PER_SECOND, GAMEPAD_STICK_DEADZONE, GAME_MINUTES_PER_SECOND, GAUSSIAN_REACH_WIDTHS, GENSHIN_TONE_CONTRAST, GENSHIN_TONE_EXPOSURE, GENSHIN_TONE_MAPPING, GLIDE_STAMINA_PER_SECOND, GRASS_BEND_PER_WIND, GRASS_DIP_PER_BEND, GRASS_TRAIL_BEND_SHARE, GRASS_TRAIL_EXTENT, GRASS_TRAIL_FADE_END_SHARE, GRASS_TRAIL_FADE_SECONDS, GRASS_TRAIL_FADE_START_SHARE, GRASS_TRAIL_STAMP_RADIUS, GRASS_TRAIL_TEXELS, GRASS_TRAIL_TEXEL_SIZE, GROUND_CONTACT_DISTANCE, GROUND_LOCOMOTION_STATES, GROUND_NORMAL_SPAN, GROUND_PRESS_SPEED, GamepadButton, GroundLayer, GroundLayers, HALF_LAMBERT_OFFSET, HALF_LAMBERT_SCALE, IMPOSTOR_CROSSFADE_SHARE, IMPOSTOR_RESOLUTION, IMPOSTOR_SWITCH_HEIGHTS, InputAction, InputActionBindingMap, InputActions, KEY_CODE_BACKWARD, KEY_CODE_DOWN, KEY_CODE_FORWARD, KEY_CODE_LEFT, KEY_CODE_RIGHT, KEY_CODE_UP, LEAF_SHAPE_KEPT_SHARE, LEAF_SHAPE_WIDTH, LEAST_DIVISOR, LIGHTNING_BOLT_BRIGHTNESS, LIGHTNING_BOLT_COLOR, LIGHTNING_BOLT_OPTIONS, LIGHTNING_FLASH_AMBIENT, LIGHTNING_FLASH_COLOR, LIGHTNING_FLASH_DECAY_SECONDS, LIGHTNING_FLASH_END, LIGHTNING_FLASH_PULSES, LIGHTNING_FLASH_SKY, LIGHTNING_MAX_DISTANCE, LIGHTNING_MIN_DISTANCE, LocomotionState, MAXIMUM_FACE_THRESHOLD, MAXIMUM_WINDOW_FLOOR, MAX_BYTE, MAX_STEPS_PER_FRAME, MAX_TILE_ATTEMPTS, MIDI_VELOCITY_MAX, MINIMUM_FACE_THRESHOLD, MINIMUM_OUTLINE_KNOT_SPAN, MINIMUM_RAMP_WIDTH_VERTEX, MINUTES_PER_DAY, MMD_BONE_NAME_MAP, MOUSE_BUTTONS, MOUSE_LOOK_MAX_PIXELS_PER_EVENT, MOUSE_LOOK_RADIANS_PER_PIXEL, MUSIC_EXPRESSION_WINDOW_SECONDS, MUSIC_LOOKAHEAD_SECONDS, MUSIC_NOISE_BAND_CENTRES, MUSIC_NOISE_LENGTH, MUSIC_SCHEDULE_INTERVAL_MS, MmdBoneName, MouseButton, NEUTRAL_LIGHT_MAP_GREEN, OBJECT_FADE_KEY, OBJECT_SURFACE_KEY, OUTLINE_MAIN_TEXTURE_SHARE, OUTLINE_PROJECTION_SCALE, OUTLINE_WIDTH_SCALE, ObjectSurface, POSE_AIR_STANCES, POSE_ARM_BEND_RADIANS, POSE_ARM_CHAINS, POSE_ARM_LOWER_RADIANS, POSE_BREATH_SECONDS, POSE_CHEST_BREATH_RADIANS, POSE_CROSSFADE_SECONDS, POSE_GAITS, POSE_SHOULDER_BREATH_RADIANS, PRECIPITATION_COUNT, PRECIPITATION_SETTINGS_MAP, PRECIPITATION_SWAY_SPEED, PRECIPITATION_VOLUME_HEIGHT, PRECIPITATION_VOLUME_SIZE, PmxBoneFlag, PmxJointKind, PmxMaterialFlag, PmxMorphKind, PmxPhysicsMode, PmxReader, PmxRigidBodyShape, PmxSphereMode, PmxTextEncoding, PmxWeightDeform, PrecipitationKind, QualityTier, QualityTierSettingsMap, RAMP_ROW_BASE, RAMP_ROW_STEP, REGION_FLOORS, RELEASE_TIME_CONSTANTS, RIVER_BEND_FOAM_ATTRIBUTE, RampLayout, RoofKind, SHARED_TOON_RAMP_SHADES, SOUND_EFFECT_BAND_EDGES, SOUND_EFFECT_FRAME_LENGTH, SPECTRAL_ANGULAR_BIN_COUNT, SPECTRAL_RADIAL_BIN_COUNT, SPHERE_CAST_STRIDE_SHARE, SPLASH_COUNT, SPLASH_LIFETIME, SPLASH_LIFT, SPLASH_OPACITY, SPLASH_RADIUS, SPLASH_SIZE, SPRINT_STAMINA_PER_SECOND, STAMINA_MAX, STAMINA_REFILL_DELAY_SECONDS, STAMINA_REFILL_PER_SECOND, STAMINA_REFILL_STATES, STEEP_SLIDE_SPEED, STONE_DARKENING_TOP, STONE_HARMONIC_COUNT, STONE_HEIGHT_FALLOFF, STONE_MASK_OUTPUT, STONE_RAMP_KNOT_COUNT, STONE_SHADOW_EXPONENT, SUN_REDRAW_COSINE, SURFACE_DETAIL_BAND_SIGMAS, SURFACE_OCTAVE_RESPONSES, SURFACE_OCTAVE_TEXEL_FREQUENCIES, SWIM_DASH_STAMINA_COST, SWIM_DASH_STAMINA_PER_SECOND, SWIM_STROKE_SECONDS, SWIM_STROKE_STAMINA_COST, SharedToonOutlinePassNode, StoneLightingModel, StoneNodeMaterial, TERRAIN_CELL_SIZE, TERRAIN_HEIGHT_PADDING, TERRAIN_LAYER, TERRAIN_RING_INITIAL_TILE_COUNT, TILE_INDEX_OFFSET, TILE_INDEX_SPAN, TONE_CONTRAST_OFFSET, TONE_CURVE_FLOOR, TONE_CURVE_LIFT, TOON_HIGH, TOON_LOW, TerrainFeatureKind, TerrainFeatureKindBlendMap, ToonNodeMaterial, UNIT_OUTLINE_WIDTH_KNOTS, WALK_MOVE_MAGNITUDE, WALL_PRESS_SPEED, WALL_PROBE_DISTANCE, WATER_LOCOMOTION_STATES, WEATHER_SETTINGS_MAP, WEATHER_TRANSITION_SECONDS, WET_DARKENING, WET_SHEEN_POWER, WET_SHEEN_STRENGTH, WeatherKind, addSmoothLoop, advanceGameClock, advanceStridePhase, applyLightningFlash, applyPrecipitationSettings, applySkyState, applyStoneLight, applyWeatherState, attachInspector, bakeImpostor, blendGridNodes, blendWeatherState, checkIsPmxSphereDrawn, checkSunTurned, checkTerrainBoundsOverlap, checkTerrainDrawsChanged, checkTerrainTileCasts, checkTransparentTexels, collectMusicNotes, collectMusicSegments, computeCharacterPose, computeGradeLut, computeGrassBlade, computeGrassTrailCell, computeGrassTrailTexel, computeGrassTrailTexelIndex, computeImpostorFade, computeLeafCards, computeLightningBolt, computeLightningFlash, computeLocomotionState, computeNoiseSamples, computeOriginShift, computeOutlineDistance, computeRampValues, computeScatterPoints, computeSoundEffectSamples, computeStatueSurface, computeStoneDarkening, computeStoneHarmonics, computeStoneRampCoordinate, computeSunDirection, computeSurfaceOctaves, computeTerrainIndices, computeTerrainTile, computeTreeTubes, computeWhiteBalance, computeWindGust, createBoxesGeometry, createBuildingGeometry, createCausticsNode, createCharacterController, createCharacterMaterial, createCharacterPoseRotations, createCharacterPoser, createCharacterShadingInputs, createCharacterShadingNode, createCloudAtlasTexture, createCloudBandSprite, createCloudLayerNode, createCloudLayerProfileTexture, createCloudLayerTexture, createCloudLayerTextures, createCloudLayerUniforms, createDitherFadeNode, createFaceDraw, createFaceShadeNode, createFixedStepLoop, createFlowerGeometry, createFlowerMaterial, createFlowerTileGeometry, createFogUniforms, createFollowCamera, createFreeCamera, createFrustumVisibility, createGameOutlineMaterial, createGaussianHillsHeight, createGenshinRenderer, createGodraysLight, createGradeLutTexture, createGrassBladePoint, createGrassCell, createGrassCulling, createGrassGeometry, createGrassMaterial, createGrassTrail, createGroundCapture, createGroundLayerWeights, createGroundPaintColor, createGroundQuery, createHeightFogNode, createImpostorMaterial, createIndexedGeometry, createInput, createInstanceCulling, createInstanceMatrixBuffer, createInstanceMatrixNode, createInstancedGeometry, createInstancedMesh, createInstrumentWave, createLandmarkCollider, createLatheStackGeometry, createLeafMaterial, createLeafShapeNode, createLightUniforms, createLightningBoltGeometry, createLightningBoltMaterial, createMaterialDetailNode, createMusicPlayer, createNoiseBuffer, createObjectFadeNode, createObjectSurfaceNode, createOcclusionNode, createOutlineColorNode, createOutlineMaterial, createOutlineScaleNode, createPavingGeometry, createPavingStoneGeometry, createPlantCulling, createPmxGeometry, createPmxMesh, createPmxSkeleton, createPmxTexture, createPmxToonTexture, createPostPipeline, createPostUniforms, createPrecipitationGeometry, createPrecipitationMaterial, createPrecipitationUniforms, createRampColumnNode, createRampTexture, createRampUvNode, createResidualHeight, createRimNode, createRiverGeometry, createRiverMaterial, createSeededRandom, createShadingRegionNode, createSightNode, createSightUniforms, createSimplexNoise, createSkyColorNode, createSkyGradientTexture, createSkyNode, createSkyState, createSkyUniforms, createSoundEffectBuffer, createSplashMaterial, createStamina, createStatueGeometries, createStoneGlowNode, createStoneLightUniforms, createStoneMaterial, createSunLight, createSunVisibilityNode, createSurfaceDetailNode, createSurvivorIndices, createTerrainFeaturesBlend, createTerrainFeaturesHeight, createTerrainMaterial, createTerrainRing, createTerrainSelection, createTerrainShapeHeight, createTerrainTileGeometry, createTileStreamer, createToneNode, createToonMaterial, createToonThresholdNode, createTreeGeometry, createUnderwaterFogState, createWaterFlowUniforms, createWaterMaterial, createWaterUniforms, createWaterfallGeometry, createWaterfallMaterial, createWetDarkeningNode, createWetSheenNode, createWindNode, createWindUniforms, fileByCell, findSkinnedMesh, getCliffBlend, getCloudAtlasColumns, getCloudSunColors, getDesaturatedColour, getGameOutlineOffset, getGaussianHillBlend, getMusicRecordingGain, getMusicRecordingRate, getOutlineDepth, getOutlineScale, getParentTerrainTileKey, getPlateauBlend, getRampColumn, getRampRow, getRampWidth, getRidgeBlend, getScreenDirection, getSegmentBounds, getShadingRegion, getSharedToonRamp, getSoundEffectBandBins, getSpectralBin, getTerrainFeatureBounds, getTerrainMorphStart, getTerrainOverlayBounds, getTerrainShapeLevel, getTerrainTileBounds, getTerrainTileColumn, getTerrainTileKey, getTerrainTileLevel, getTerrainTileRow, getToneColour, getToonThreshold, measureSegment, mergeGeometryParts, orderByViewDepth, parsePmx, parsePmxBones, parsePmxJoints, parsePmxMaterials, parsePmxMorphs, parsePmxRigidBodies, parsePmxVertices, placeCloudBand, renderGroundCapture, renderMusicSegment, resolveTerrainDraws, sampleGrassTrail, sampleGroundCapture, sampleGroundLayerField, sampleSkyState, sampleTerrainResidualFade, sampleTreeNormalField, scheduleMusicExpression, scheduleMusicNote, scheduleMusicRecording, selectMusicSample, selectRegionNode, selectTerrainTiles, setObjectFade, setObjectSurface, stepGrassTrail, synthesizeCloudLayerTextures, synthesizeSpectralNoise, toSceneColor, toneMapGenshin, toneMapGenshinNode, transformFourier, transformFourierGrid, updateFaceDraw, updateUnderwaterFog, writeCloudLayerTexture, writeQuadIndices, writeTerrainRingIndices, writeTerrainRingTile };