genshin-engine 3.7.0 → 3.8.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.d.ts +109 -4
- package/dist/index.js +189 -27
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import { BufferAttribute, BufferGeometry, Camera, Color, ColorRepresentation, Data3DTexture, DataTexture, DirectionalLight, Frustum, HemisphereLight, InstancedBufferGeometry, OrthographicCamera, Scene, Vector2, Vector3, Vector3Like } from "three";
|
|
1
|
+
import { BufferAttribute, BufferGeometry, Camera, CanvasTexture, Color, ColorRepresentation, Data3DTexture, DataTexture, DirectionalLight, ExtrudeGeometry, Frustum, HemisphereLight, InstancedBufferGeometry, OrthographicCamera, Scene, Texture, ToneMapping, Vector2, Vector3, Vector3Like } from "three";
|
|
2
|
+
import { MeshBasicNodeMaterial, MeshToonNodeMaterial, MeshToonNodeMaterialParameters, Node, RenderPipeline, RenderTarget, Renderer, SpriteNodeMaterial, TextureNode, UniformNode, WebGPURenderer } from "three/webgpu";
|
|
2
3
|
import { CSMShadowNode } from "three/examples/jsm/csm/CSMShadowNode.js";
|
|
3
|
-
import { MeshBasicNodeMaterial, MeshToonNodeMaterial, MeshToonNodeMaterialParameters, Node, RenderPipeline, RenderTarget, Renderer, TextureNode, UniformNode, WebGPURenderer } from "three/webgpu";
|
|
4
4
|
import BloomNode from "three/examples/jsm/tsl/display/BloomNode.js";
|
|
5
5
|
import GodraysNode from "three/examples/jsm/tsl/display/GodraysNode.js";
|
|
6
|
+
//#region src/atmosphere/CloudBandOptions.d.ts
|
|
7
|
+
export interface CloudBandOptions {
|
|
8
|
+
count: number;
|
|
9
|
+
distanceRange: [number, number];
|
|
10
|
+
heightRange: [number, number];
|
|
11
|
+
seed: number;
|
|
12
|
+
widthRange: [number, number];
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/atmosphere/CloudSprite.d.ts
|
|
16
|
+
export interface CloudSprite {
|
|
17
|
+
lit: [number, number][][];
|
|
18
|
+
outline: [number, number][][];
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
6
21
|
//#region src/atmosphere/SkyKeyframe.d.ts
|
|
7
22
|
export interface SkyKeyframe {
|
|
8
23
|
cloudLitColor: Color;
|
|
@@ -20,6 +35,7 @@ export interface SkyKeyframe {
|
|
|
20
35
|
//#endregion
|
|
21
36
|
//#region src/atmosphere/SkyState.d.ts
|
|
22
37
|
export interface SkyState extends Omit<SkyKeyframe, "minutes"> {
|
|
38
|
+
fogColor?: Color;
|
|
23
39
|
lightDirection: Vector3;
|
|
24
40
|
moonDirection: Vector3;
|
|
25
41
|
sunDirection: Vector3;
|
|
@@ -31,6 +47,7 @@ export interface SkyUniforms {
|
|
|
31
47
|
cloudDrift: UniformNode<"vec2", Vector2>;
|
|
32
48
|
cloudLitColor: UniformNode<"color", Color>;
|
|
33
49
|
cloudShadeColor: UniformNode<"color", Color>;
|
|
50
|
+
horizonBand: UniformNode<"float", number>;
|
|
34
51
|
horizonColor: UniformNode<"color", Color>;
|
|
35
52
|
lightColor: UniformNode<"color", Color>;
|
|
36
53
|
moonDirection: UniformNode<"vec3", Vector3>;
|
|
@@ -53,6 +70,10 @@ export interface FogUniforms {
|
|
|
53
70
|
color: UniformNode<"color", Color>;
|
|
54
71
|
density: UniformNode<"float", number>;
|
|
55
72
|
heightFalloff: UniformNode<"float", number>;
|
|
73
|
+
scatterColor: UniformNode<"color", Color>;
|
|
74
|
+
scatterDirection: UniformNode<"vec3", Vector3>;
|
|
75
|
+
scatterPower: UniformNode<"float", number>;
|
|
76
|
+
scatterStrength: UniformNode<"float", number>;
|
|
56
77
|
startDistance: UniformNode<"float", number>;
|
|
57
78
|
}
|
|
58
79
|
//#endregion
|
|
@@ -96,6 +117,16 @@ export declare const applySkyState: (skyState: SkyState, { fogUniforms, godraysL
|
|
|
96
117
|
//#region src/atmosphere/computeSunDirection.d.ts
|
|
97
118
|
export declare const computeSunDirection: (minutes: number, tilt: number, sunDirection: Vector3) => Vector3;
|
|
98
119
|
//#endregion
|
|
120
|
+
//#region src/atmosphere/createCloudAtlasTexture.d.ts
|
|
121
|
+
export declare const getCloudAtlasColumns: (spriteCount: number) => number;
|
|
122
|
+
export declare const createCloudAtlasTexture: (sprites: readonly CloudSprite[], cellSize: number) => CanvasTexture<OffscreenCanvas>;
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/atmosphere/createCloudSpriteMaterial.d.ts
|
|
125
|
+
export declare const createCloudSpriteMaterial: (atlas: Texture, { index, spriteCount }: {
|
|
126
|
+
index: number;
|
|
127
|
+
spriteCount: number;
|
|
128
|
+
}, { cloudLitColor, cloudShadeColor }: Pick<SkyUniforms, "cloudLitColor" | "cloudShadeColor">) => SpriteNodeMaterial;
|
|
129
|
+
//#endregion
|
|
99
130
|
//#region src/atmosphere/createSkyState.d.ts
|
|
100
131
|
export declare const createSkyState: () => SkyState;
|
|
101
132
|
//#endregion
|
|
@@ -105,6 +136,13 @@ export declare const createSkyUniforms: () => SkyUniforms;
|
|
|
105
136
|
//#region src/atmosphere/createSunLight.d.ts
|
|
106
137
|
export declare const createSunLight: ({ cascadeCount, maxFar, shadowMapSize }: SunLightOptions) => SunLight;
|
|
107
138
|
//#endregion
|
|
139
|
+
//#region src/atmosphere/placeCloudBand.d.ts
|
|
140
|
+
export declare const placeCloudBand: ({ count, distanceRange: [near, far], heightRange: [low, high], seed, widthRange: [narrow, wide] }: CloudBandOptions, spriteCount: number) => {
|
|
141
|
+
position: [number, number, number];
|
|
142
|
+
spriteIndex: number;
|
|
143
|
+
width: number;
|
|
144
|
+
}[];
|
|
145
|
+
//#endregion
|
|
108
146
|
//#region src/atmosphere/sampleSkyState.d.ts
|
|
109
147
|
export declare const sampleSkyState: (skyKeyframes: readonly SkyKeyframe[], minutes: number, tilt: number, skyState: SkyState) => SkyState;
|
|
110
148
|
//#endregion
|
|
@@ -121,6 +159,32 @@ export declare const advanceGameClock: (gameClock: GameClock, deltaSeconds: numb
|
|
|
121
159
|
export declare const MINUTES_PER_DAY = 1440;
|
|
122
160
|
export declare const GAME_MINUTES_PER_SECOND = 1;
|
|
123
161
|
//#endregion
|
|
162
|
+
//#region src/kits/architecture/LatheSection.d.ts
|
|
163
|
+
export interface LatheSection {
|
|
164
|
+
bottomRadius: number;
|
|
165
|
+
height: number;
|
|
166
|
+
topRadius: number;
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/kits/architecture/LatheStackOptions.d.ts
|
|
170
|
+
export interface LatheStackOptions {
|
|
171
|
+
isFaceted: boolean;
|
|
172
|
+
radialSegments: number;
|
|
173
|
+
sections: LatheSection[];
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region src/kits/architecture/SilhouetteOptions.d.ts
|
|
177
|
+
export interface SilhouetteOptions {
|
|
178
|
+
contours: [number, number][][];
|
|
179
|
+
depth: [number, number];
|
|
180
|
+
}
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/kits/architecture/createLatheStackGeometry.d.ts
|
|
183
|
+
export declare const createLatheStackGeometry: ({ isFaceted, radialSegments, sections }: LatheStackOptions) => BufferGeometry;
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/kits/architecture/createSilhouetteGeometry.d.ts
|
|
186
|
+
export declare const createSilhouetteGeometry: ({ contours, depth: [front, back] }: SilhouetteOptions) => ExtrudeGeometry;
|
|
187
|
+
//#endregion
|
|
124
188
|
//#region src/kits/statue/createStatueGeometry.d.ts
|
|
125
189
|
export declare const createStatueGeometry: () => BufferGeometry;
|
|
126
190
|
//#endregion
|
|
@@ -240,7 +304,7 @@ export declare const createLightUniforms: () => LightUniforms;
|
|
|
240
304
|
export declare const createRimNode: ({ rimColor, rimStrength, sunDirection }: LightUniforms) => Node<"vec3">;
|
|
241
305
|
//#endregion
|
|
242
306
|
//#region src/nodes/createSkyNode.d.ts
|
|
243
|
-
export declare const createSkyNode: ({ cloudCoverage, cloudDrift, cloudLitColor, cloudShadeColor, horizonColor, lightColor, moonDirection, starIntensity, sunDirection, zenithColor }: SkyUniforms) => Node<"vec3">;
|
|
307
|
+
export declare const createSkyNode: ({ cloudCoverage, cloudDrift, cloudLitColor, cloudShadeColor, horizonBand, horizonColor, lightColor, moonDirection, starIntensity, sunDirection, zenithColor }: SkyUniforms) => Node<"vec3">;
|
|
244
308
|
//#endregion
|
|
245
309
|
//#region src/nodes/createToonMaterial.d.ts
|
|
246
310
|
export declare const createToonMaterial: ({ color, isOutlined, isVertexColors, lightUniforms, rampTexture }: ToonMaterialOptions) => ToonNodeMaterial;
|
|
@@ -312,7 +376,7 @@ export declare const createGodraysLight: (shadowMapSize: number, halfExtent: num
|
|
|
312
376
|
export declare const createGradeLutTexture: (gradeOptions: GradeOptions) => Data3DTexture;
|
|
313
377
|
//#endregion
|
|
314
378
|
//#region src/post/createHeightFogNode.d.ts
|
|
315
|
-
export declare const createHeightFogNode: (colorNode: Node<"vec4">, depthNode: TextureNode, camera: Camera, { baseHeight, color, density, heightFalloff, startDistance }: FogUniforms) => Node<"vec4">;
|
|
379
|
+
export declare const createHeightFogNode: (colorNode: Node<"vec4">, depthNode: TextureNode, camera: Camera, { baseHeight, color, density, heightFalloff, scatterColor, scatterDirection, scatterPower, scatterStrength, startDistance }: FogUniforms) => Node<"vec4">;
|
|
316
380
|
//#endregion
|
|
317
381
|
//#region src/post/createPostPipeline.d.ts
|
|
318
382
|
export declare const createPostPipeline: ({ camera, fogUniforms, godraysLight, gradeLutTexture, postUniforms: { godraysColor, gradeIntensity, outlineColor, outlineFadeDistance, outlineThickness }, qualityTierSettings: { antialiasingMode, godraysStepCount, isBloomEnabled }, renderer, scene }: PostPipelineOptions) => PostPipeline;
|
|
@@ -320,6 +384,9 @@ export declare const createPostPipeline: ({ camera, fogUniforms, godraysLight, g
|
|
|
320
384
|
//#region src/post/createPostUniforms.d.ts
|
|
321
385
|
export declare const createPostUniforms: () => PostUniforms;
|
|
322
386
|
//#endregion
|
|
387
|
+
//#region src/post/toSceneColor.d.ts
|
|
388
|
+
export declare const toSceneColor: (displayColor: Color) => Color;
|
|
389
|
+
//#endregion
|
|
323
390
|
//#region src/random/createSeededRandom.d.ts
|
|
324
391
|
export declare const createSeededRandom: (seed: number) => (() => number);
|
|
325
392
|
//#endregion
|
|
@@ -333,6 +400,44 @@ export declare enum QualityTier {
|
|
|
333
400
|
//#region src/renderer/QualityTierSettingsMap.d.ts
|
|
334
401
|
export declare const QualityTierSettingsMap: Readonly<Record<QualityTier, QualityTierSettings>>;
|
|
335
402
|
//#endregion
|
|
403
|
+
//#region src/renderer/constants.d.ts
|
|
404
|
+
export declare const GENSHIN_TONE_MAPPING: ToneMapping;
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/renderer/getScreenDirection.d.ts
|
|
407
|
+
export declare const getScreenDirection: ({ aspect, fov, pitch, yaw }: {
|
|
408
|
+
aspect: number;
|
|
409
|
+
fov: number;
|
|
410
|
+
pitch: number;
|
|
411
|
+
yaw: number;
|
|
412
|
+
}, [x, y]: [number, number]) => Vector3;
|
|
413
|
+
//#endregion
|
|
414
|
+
//#region src/scene/SceneMaterial.d.ts
|
|
415
|
+
export interface SceneMaterial {
|
|
416
|
+
colors: Record<string, [number, number, number, number]>;
|
|
417
|
+
floats: Record<string, number>;
|
|
418
|
+
name: string;
|
|
419
|
+
textures: Record<string, {
|
|
420
|
+
name: string;
|
|
421
|
+
offset: [number, number];
|
|
422
|
+
scale: [number, number];
|
|
423
|
+
}>;
|
|
424
|
+
}
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region src/scene/ScenePlacement.d.ts
|
|
427
|
+
export interface ScenePlacement {
|
|
428
|
+
materials: string[];
|
|
429
|
+
mesh: string;
|
|
430
|
+
position: [number, number, number];
|
|
431
|
+
rotation: [number, number, number, number];
|
|
432
|
+
scale: [number, number, number];
|
|
433
|
+
}
|
|
434
|
+
//#endregion
|
|
435
|
+
//#region src/scene/SceneLayout.d.ts
|
|
436
|
+
export interface SceneLayout {
|
|
437
|
+
materials: Record<string, SceneMaterial>;
|
|
438
|
+
placements: ScenePlacement[];
|
|
439
|
+
}
|
|
440
|
+
//#endregion
|
|
336
441
|
//#region src/terrain/TerrainSelection.d.ts
|
|
337
442
|
export interface TerrainSelection {
|
|
338
443
|
count: number;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Box3, BufferAttribute, BufferGeometry, Color, CylinderGeometry, Data3DTexture, DataTexture, DirectionalLight, DoubleSide, HalfFloatType, InstancedBufferGeometry, LatheGeometry, LinearFilter, OrthographicCamera, Quaternion, RedFormat, Vector2, Vector3 } from "three";
|
|
1
|
+
import { Box3, BufferAttribute, BufferGeometry, CanvasTexture, Color, CylinderGeometry, Data3DTexture, DataTexture, DirectionalLight, DoubleSide, ExtrudeGeometry, HalfFloatType, InstancedBufferGeometry, LatheGeometry, LinearFilter, MathUtils, NeutralToneMapping, NoColorSpace, OrthographicCamera, Quaternion, RedFormat, ShapePath, Vector2, Vector3 } from "three";
|
|
2
2
|
import { Fn, If, attribute, cameraFar, cameraNear, cameraPosition, cameraViewMatrix, cos, exp, exp2, float, getViewPosition, hash, instanceIndex, max, mix, modelViewMatrix, modelWorldMatrix, mrt, mx_cell_noise_float, mx_fractal_noise_float, mx_noise_float, normalView, normalWorldGeometry, output, perspectiveDepthToViewZ, positionGeometry, positionLocal, positionView, positionViewDirection, positionWorld, pow, reflect, renderOutput, screenUV, sin, smoothstep, step, texture, texture3D, time, uniform, uv, varying, vec2, vec3, vec4, velocity, viewportDepthTexture, viewportSharedTexture } from "three/tsl";
|
|
3
|
+
import { MeshBasicNodeMaterial, MeshToonNodeMaterial, RenderPipeline, RenderTarget, SpriteNodeMaterial, ToonOutlinePassNode, WebGPURenderer } from "three/webgpu";
|
|
3
4
|
import { CSMShadowNode } from "three/examples/jsm/csm/CSMShadowNode.js";
|
|
4
5
|
import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
|
|
5
|
-
import { MeshBasicNodeMaterial, MeshToonNodeMaterial, NeutralToneMapping, RenderPipeline, RenderTarget, ToonOutlinePassNode, WebGPURenderer } from "three/webgpu";
|
|
6
6
|
import { voronoi2d } from "three/examples/jsm/tsl/math/voronoiNoise.js";
|
|
7
7
|
import { bilateralBlur } from "three/examples/jsm/tsl/display/BilateralBlurNode.js";
|
|
8
8
|
import { bloom } from "three/examples/jsm/tsl/display/BloomNode.js";
|
|
@@ -11,6 +11,49 @@ import { godrays } from "three/examples/jsm/tsl/display/GodraysNode.js";
|
|
|
11
11
|
import { lut3D } from "three/examples/jsm/tsl/display/Lut3DNode.js";
|
|
12
12
|
import { smaa } from "three/examples/jsm/tsl/display/SMAANode.js";
|
|
13
13
|
import { traa } from "three/examples/jsm/tsl/display/TRAANode.js";
|
|
14
|
+
//#region src/post/toSceneColor.ts
|
|
15
|
+
const TOE_END = .08;
|
|
16
|
+
const TOE_OFFSET = .04;
|
|
17
|
+
const COMPRESSION_START = .76;
|
|
18
|
+
const DESATURATION = .15;
|
|
19
|
+
const INVERSE_STEP_COUNT = 16;
|
|
20
|
+
const SLOPE_NUDGE = 1e-4;
|
|
21
|
+
const SCENE_CHANNEL_LIMIT = 1.5;
|
|
22
|
+
const toneMap = ([red, green, blue]) => {
|
|
23
|
+
const lowest = Math.min(red, green, blue);
|
|
24
|
+
const offset = lowest < TOE_END ? lowest - 6.25 * lowest * lowest : TOE_OFFSET;
|
|
25
|
+
const offsetColor = [
|
|
26
|
+
red - offset,
|
|
27
|
+
green - offset,
|
|
28
|
+
blue - offset
|
|
29
|
+
];
|
|
30
|
+
const peak = Math.max(...offsetColor);
|
|
31
|
+
if (peak < COMPRESSION_START) return offsetColor;
|
|
32
|
+
const headroom = .24;
|
|
33
|
+
const newPeak = 1 - headroom * headroom / (peak + headroom - COMPRESSION_START);
|
|
34
|
+
const whiteShare = 1 - 1 / (DESATURATION * (peak - newPeak) + 1);
|
|
35
|
+
return offsetColor.map((channel) => channel * newPeak / peak + (newPeak - channel * newPeak / peak) * whiteShare);
|
|
36
|
+
};
|
|
37
|
+
const toSceneColor = (displayColor) => {
|
|
38
|
+
const target = [
|
|
39
|
+
displayColor.r,
|
|
40
|
+
displayColor.g,
|
|
41
|
+
displayColor.b
|
|
42
|
+
];
|
|
43
|
+
let input = [...target];
|
|
44
|
+
for (let step = 0; step < INVERSE_STEP_COUNT; step++) {
|
|
45
|
+
const current = input;
|
|
46
|
+
const output = toneMap(current);
|
|
47
|
+
input = current.map((channel, index) => {
|
|
48
|
+
const nudged = [...current];
|
|
49
|
+
nudged[index] = channel + SLOPE_NUDGE;
|
|
50
|
+
const slope = ((toneMap(nudged)[index] ?? 0) - (output[index] ?? 0)) / SLOPE_NUDGE;
|
|
51
|
+
return Math.min(Math.max(channel + ((target[index] ?? 0) - (output[index] ?? 0)) / slope, 0), SCENE_CHANNEL_LIMIT);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return new Color(...input);
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
14
57
|
//#region src/atmosphere/applySkyState.ts
|
|
15
58
|
const GODRAYS_REDRAW_COSINE = Math.cos(.6 * Math.PI / 180);
|
|
16
59
|
const godraysDirection = new Vector3();
|
|
@@ -25,16 +68,18 @@ const applySkyState = (skyState, { fogUniforms, godraysLight, hemisphere, light,
|
|
|
25
68
|
lightUniforms.lightColor.value.copy(lightColor);
|
|
26
69
|
lightUniforms.sunDirection.value.copy(lightDirection);
|
|
27
70
|
lightUniforms.rimColor.value.copy(horizonColor);
|
|
28
|
-
fogUniforms.color.value.copy(horizonColor);
|
|
71
|
+
fogUniforms.color.value.copy(toSceneColor(skyState.fogColor ?? horizonColor));
|
|
72
|
+
fogUniforms.scatterColor.value.copy(toSceneColor(lightColor));
|
|
73
|
+
fogUniforms.scatterDirection.value.copy(lightDirection);
|
|
29
74
|
postUniforms.godraysColor.value.copy(lightColor);
|
|
30
|
-
skyUniforms.cloudLitColor.value.copy(skyState.cloudLitColor);
|
|
31
|
-
skyUniforms.cloudShadeColor.value.copy(skyState.cloudShadeColor);
|
|
32
|
-
skyUniforms.horizonColor.value.copy(horizonColor);
|
|
75
|
+
skyUniforms.cloudLitColor.value.copy(toSceneColor(skyState.cloudLitColor));
|
|
76
|
+
skyUniforms.cloudShadeColor.value.copy(toSceneColor(skyState.cloudShadeColor));
|
|
77
|
+
skyUniforms.horizonColor.value.copy(toSceneColor(horizonColor));
|
|
33
78
|
skyUniforms.lightColor.value.copy(lightColor);
|
|
34
79
|
skyUniforms.moonDirection.value.copy(skyState.moonDirection);
|
|
35
80
|
skyUniforms.starIntensity.value = skyState.starIntensity;
|
|
36
81
|
skyUniforms.sunDirection.value.copy(skyState.sunDirection);
|
|
37
|
-
skyUniforms.zenithColor.value.copy(skyState.zenithColor);
|
|
82
|
+
skyUniforms.zenithColor.value.copy(toSceneColor(skyState.zenithColor));
|
|
38
83
|
godraysDirection.subVectors(godraysLight.position, godraysLight.target.position).normalize();
|
|
39
84
|
if (godraysDirection.dot(lightDirection) >= GODRAYS_REDRAW_COSINE) return;
|
|
40
85
|
godraysLight.position.copy(godraysLight.target.position).addScaledVector(lightDirection, lightDistance);
|
|
@@ -52,6 +97,58 @@ const computeSunDirection = (minutes, tilt, sunDirection) => {
|
|
|
52
97
|
return sunDirection.set(Math.sin(hourAngle), height * Math.cos(tilt), height * Math.sin(tilt));
|
|
53
98
|
};
|
|
54
99
|
//#endregion
|
|
100
|
+
//#region src/atmosphere/createCloudAtlasTexture.ts
|
|
101
|
+
const getCloudAtlasColumns = (spriteCount) => Math.ceil(Math.sqrt(spriteCount));
|
|
102
|
+
const createCloudAtlasTexture = (sprites, cellSize) => {
|
|
103
|
+
const columns = getCloudAtlasColumns(sprites.length);
|
|
104
|
+
const canvas = new OffscreenCanvas(columns * cellSize, columns * cellSize);
|
|
105
|
+
const context = canvas.getContext("2d");
|
|
106
|
+
if (context) {
|
|
107
|
+
context.globalCompositeOperation = "lighter";
|
|
108
|
+
const fill = (loops, column, row, style) => {
|
|
109
|
+
const path = new Path2D();
|
|
110
|
+
for (const [first, ...rest] of loops) {
|
|
111
|
+
if (!first) continue;
|
|
112
|
+
const toCanvas = ([x, y]) => [(column + x) * cellSize, (row + 1 - y) * cellSize];
|
|
113
|
+
path.moveTo(...toCanvas(first));
|
|
114
|
+
for (const point of rest) path.lineTo(...toCanvas(point));
|
|
115
|
+
path.closePath();
|
|
116
|
+
}
|
|
117
|
+
context.fillStyle = style;
|
|
118
|
+
context.fill(path, "evenodd");
|
|
119
|
+
};
|
|
120
|
+
for (const [index, { lit, outline }] of sprites.entries()) {
|
|
121
|
+
const column = index % columns;
|
|
122
|
+
const row = Math.floor(index / columns);
|
|
123
|
+
fill(outline, column, row, "#f00");
|
|
124
|
+
fill(lit, column, row, "#0f0");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const texture = new CanvasTexture(canvas);
|
|
128
|
+
texture.colorSpace = NoColorSpace;
|
|
129
|
+
texture.magFilter = LinearFilter;
|
|
130
|
+
texture.minFilter = LinearFilter;
|
|
131
|
+
texture.generateMipmaps = false;
|
|
132
|
+
return texture;
|
|
133
|
+
};
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/atmosphere/createCloudSpriteMaterial.ts
|
|
136
|
+
const createCloudSpriteMaterial = (atlas, { index, spriteCount }, { cloudLitColor, cloudShadeColor }) => {
|
|
137
|
+
const columns = getCloudAtlasColumns(spriteCount);
|
|
138
|
+
const column = index % columns;
|
|
139
|
+
const row = Math.floor(index / columns);
|
|
140
|
+
const cellUv = uv().add(vec2(column, columns - 1 - row)).div(columns);
|
|
141
|
+
const mask = texture(atlas, cellUv);
|
|
142
|
+
const material = new SpriteNodeMaterial({
|
|
143
|
+
depthWrite: false,
|
|
144
|
+
transparent: true
|
|
145
|
+
});
|
|
146
|
+
material.colorNode = mix(cloudShadeColor, cloudLitColor, mask.g);
|
|
147
|
+
material.opacityNode = mask.r;
|
|
148
|
+
material.alphaTest = .5;
|
|
149
|
+
return material;
|
|
150
|
+
};
|
|
151
|
+
//#endregion
|
|
55
152
|
//#region src/atmosphere/createSkyState.ts
|
|
56
153
|
const createSkyState = () => ({
|
|
57
154
|
cloudLitColor: new Color(),
|
|
@@ -75,6 +172,7 @@ const createSkyUniforms = () => ({
|
|
|
75
172
|
cloudDrift: uniform(new Vector2()),
|
|
76
173
|
cloudLitColor: uniform(new Color()),
|
|
77
174
|
cloudShadeColor: uniform(new Color()),
|
|
175
|
+
horizonBand: uniform(.45),
|
|
78
176
|
horizonColor: uniform(new Color()),
|
|
79
177
|
lightColor: uniform(new Color()),
|
|
80
178
|
moonDirection: uniform(new Vector3(0, -1, 0)),
|
|
@@ -108,6 +206,36 @@ const createSunLight = ({ cascadeCount, maxFar, shadowMapSize }) => {
|
|
|
108
206
|
};
|
|
109
207
|
};
|
|
110
208
|
//#endregion
|
|
209
|
+
//#region src/random/createSeededRandom.ts
|
|
210
|
+
const createSeededRandom = (seed) => {
|
|
211
|
+
let state = seed;
|
|
212
|
+
return () => {
|
|
213
|
+
state = state + 1831565813 >>> 0;
|
|
214
|
+
let mixed = Math.imul(state ^ state >>> 15, 1 | state);
|
|
215
|
+
mixed ^= mixed + Math.imul(mixed ^ mixed >>> 7, 61 | mixed);
|
|
216
|
+
return ((mixed ^ mixed >>> 14) >>> 0) / 2 ** 32;
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/atmosphere/placeCloudBand.ts
|
|
221
|
+
const placeCloudBand = ({ count, distanceRange: [near, far], heightRange: [low, high], seed, widthRange: [narrow, wide] }, spriteCount) => {
|
|
222
|
+
const random = createSeededRandom(seed);
|
|
223
|
+
return Array.from({ length: count }, () => {
|
|
224
|
+
const angle = random() * Math.PI * 2;
|
|
225
|
+
const distance = Math.sqrt(near ** 2 + random() * (far ** 2 - near ** 2));
|
|
226
|
+
const height = low + random() * (high - low);
|
|
227
|
+
return {
|
|
228
|
+
position: [
|
|
229
|
+
Math.cos(angle) * distance,
|
|
230
|
+
height,
|
|
231
|
+
Math.sin(angle) * distance
|
|
232
|
+
],
|
|
233
|
+
spriteIndex: Math.floor(random() * spriteCount),
|
|
234
|
+
width: narrow + random() * (wide - narrow)
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
//#endregion
|
|
111
239
|
//#region src/atmosphere/sampleSkyState.ts
|
|
112
240
|
const lerp = (from, to, amount) => from + (to - from) * amount;
|
|
113
241
|
const sampleSkyState = (skyKeyframes, minutes, tilt, skyState) => {
|
|
@@ -140,6 +268,34 @@ const advanceGameClock = (gameClock, deltaSeconds) => {
|
|
|
140
268
|
gameClock.minutes = (gameClock.minutes + deltaSeconds * gameClock.minutesPerSecond) % MINUTES_PER_DAY;
|
|
141
269
|
};
|
|
142
270
|
//#endregion
|
|
271
|
+
//#region src/kits/architecture/createLatheStackGeometry.ts
|
|
272
|
+
const createLatheStackGeometry = ({ isFaceted, radialSegments, sections }) => {
|
|
273
|
+
let footHeight = 0;
|
|
274
|
+
const parts = sections.map(({ bottomRadius, height, topRadius }) => {
|
|
275
|
+
const part = new CylinderGeometry(topRadius, bottomRadius, height, radialSegments).translate(0, footHeight + height / 2, 0);
|
|
276
|
+
footHeight += height;
|
|
277
|
+
return isFaceted ? part.toNonIndexed() : part;
|
|
278
|
+
});
|
|
279
|
+
const stackGeometry = mergeGeometries(parts) ?? new BufferGeometry();
|
|
280
|
+
for (const part of parts) part.dispose();
|
|
281
|
+
if (isFaceted) stackGeometry.computeVertexNormals();
|
|
282
|
+
return stackGeometry;
|
|
283
|
+
};
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region src/kits/architecture/createSilhouetteGeometry.ts
|
|
286
|
+
const createSilhouetteGeometry = ({ contours, depth: [front, back] }) => {
|
|
287
|
+
const shapePath = new ShapePath();
|
|
288
|
+
for (const [first, ...rest] of contours) {
|
|
289
|
+
if (!first) continue;
|
|
290
|
+
shapePath.moveTo(...first);
|
|
291
|
+
for (const point of rest) shapePath.lineTo(...point);
|
|
292
|
+
}
|
|
293
|
+
return new ExtrudeGeometry(shapePath.toShapes(), {
|
|
294
|
+
bevelEnabled: false,
|
|
295
|
+
depth: back - front
|
|
296
|
+
}).translate(0, 0, front);
|
|
297
|
+
};
|
|
298
|
+
//#endregion
|
|
143
299
|
//#region src/kits/statue/createStatueGeometry.ts
|
|
144
300
|
const PLINTH_SIDES = 8;
|
|
145
301
|
const FIGURE_SEGMENTS = 24;
|
|
@@ -179,17 +335,6 @@ const createStatueGeometry = () => {
|
|
|
179
335
|
return statueGeometry;
|
|
180
336
|
};
|
|
181
337
|
//#endregion
|
|
182
|
-
//#region src/random/createSeededRandom.ts
|
|
183
|
-
const createSeededRandom = (seed) => {
|
|
184
|
-
let state = seed;
|
|
185
|
-
return () => {
|
|
186
|
-
state = state + 1831565813 >>> 0;
|
|
187
|
-
let mixed = Math.imul(state ^ state >>> 15, 1 | state);
|
|
188
|
-
mixed ^= mixed + Math.imul(mixed ^ mixed >>> 7, 61 | mixed);
|
|
189
|
-
return ((mixed ^ mixed >>> 14) >>> 0) / 2 ** 32;
|
|
190
|
-
};
|
|
191
|
-
};
|
|
192
|
-
//#endregion
|
|
193
338
|
//#region src/kits/tree/computeLeafCards.ts
|
|
194
339
|
const VERTICES_PER_CARD = 4;
|
|
195
340
|
const INDICES_PER_CARD = 6;
|
|
@@ -379,14 +524,18 @@ const createCausticsNode = ({ lightColor }, { causticStrength, deepDepth, level
|
|
|
379
524
|
return lightColor.mul(veins.mul(fade).mul(causticStrength));
|
|
380
525
|
};
|
|
381
526
|
//#endregion
|
|
527
|
+
//#region src/renderer/constants.ts
|
|
528
|
+
const GENSHIN_TONE_MAPPING = NeutralToneMapping;
|
|
529
|
+
//#endregion
|
|
382
530
|
//#region src/nodes/createGenshinRenderer.ts
|
|
383
531
|
const createGenshinRenderer = (canvas) => {
|
|
532
|
+
const isWindows = window.navigator.userAgent.includes("Windows");
|
|
384
533
|
const renderer = new WebGPURenderer({
|
|
385
534
|
antialias: false,
|
|
386
535
|
canvas,
|
|
387
|
-
powerPreference: "high-performance"
|
|
536
|
+
...isWindows ? {} : { powerPreference: "high-performance" }
|
|
388
537
|
});
|
|
389
|
-
renderer.toneMapping =
|
|
538
|
+
renderer.toneMapping = GENSHIN_TONE_MAPPING;
|
|
390
539
|
return renderer;
|
|
391
540
|
};
|
|
392
541
|
//#endregion
|
|
@@ -402,7 +551,7 @@ const createRimNode = ({ rimColor, rimStrength, sunDirection }) => {
|
|
|
402
551
|
//#region src/nodes/createToonMaterial.ts
|
|
403
552
|
const createToonMaterial = ({ color, isOutlined = true, isVertexColors = false, lightUniforms, rampTexture }) => {
|
|
404
553
|
const toonMaterial = new ToonNodeMaterial({
|
|
405
|
-
color,
|
|
554
|
+
...color === void 0 ? {} : { color },
|
|
406
555
|
gradientMap: rampTexture,
|
|
407
556
|
vertexColors: isVertexColors
|
|
408
557
|
}, isOutlined);
|
|
@@ -450,7 +599,6 @@ const createLightUniforms = () => ({
|
|
|
450
599
|
});
|
|
451
600
|
//#endregion
|
|
452
601
|
//#region src/nodes/createSkyNode.ts
|
|
453
|
-
const HORIZON_BAND = .45;
|
|
454
602
|
const SUN_DISC_COSINE = Math.cos(.035);
|
|
455
603
|
const MOON_DISC_COSINE = Math.cos(.05);
|
|
456
604
|
const SUN_GLOW_POWER = 12;
|
|
@@ -462,10 +610,10 @@ const CLOUD_EDGE = .04;
|
|
|
462
610
|
const CLOUD_SHADE_DEPTH = .18;
|
|
463
611
|
const STAR_SCALE = 420;
|
|
464
612
|
const STAR_THRESHOLD = .9975;
|
|
465
|
-
const createSkyNode = ({ cloudCoverage, cloudDrift, cloudLitColor, cloudShadeColor, horizonColor, lightColor, moonDirection, starIntensity, sunDirection, zenithColor }) => Fn(() => {
|
|
613
|
+
const createSkyNode = ({ cloudCoverage, cloudDrift, cloudLitColor, cloudShadeColor, horizonBand, horizonColor, lightColor, moonDirection, starIntensity, sunDirection, zenithColor }) => Fn(() => {
|
|
466
614
|
const direction = normalWorldGeometry.normalize();
|
|
467
615
|
const height = direction.y;
|
|
468
|
-
const gradient = mix(horizonColor, zenithColor, smoothstep(0,
|
|
616
|
+
const gradient = mix(horizonColor, zenithColor, smoothstep(0, horizonBand, height));
|
|
469
617
|
const sunCosine = direction.dot(sunDirection);
|
|
470
618
|
const sunVisibility = smoothstep(-.1, .05, sunDirection.y);
|
|
471
619
|
const sunGlow = pow(max(sunCosine, 0), SUN_GLOW_POWER).mul(sunVisibility);
|
|
@@ -616,6 +764,10 @@ const createFogUniforms = () => ({
|
|
|
616
764
|
color: uniform(new Color()),
|
|
617
765
|
density: uniform(0),
|
|
618
766
|
heightFalloff: uniform(0),
|
|
767
|
+
scatterColor: uniform(new Color()),
|
|
768
|
+
scatterDirection: uniform(new Vector3(0, 1, 0)),
|
|
769
|
+
scatterPower: uniform(1),
|
|
770
|
+
scatterStrength: uniform(0),
|
|
619
771
|
startDistance: uniform(0)
|
|
620
772
|
});
|
|
621
773
|
//#endregion
|
|
@@ -647,7 +799,7 @@ const createGradeLutTexture = (gradeOptions) => {
|
|
|
647
799
|
//#endregion
|
|
648
800
|
//#region src/post/createHeightFogNode.ts
|
|
649
801
|
const MIN_RAY_CLIMB = 1e-6;
|
|
650
|
-
const createHeightFogNode = (colorNode, depthNode, camera, { baseHeight, color, density, heightFalloff, startDistance }) => {
|
|
802
|
+
const createHeightFogNode = (colorNode, depthNode, camera, { baseHeight, color, density, heightFalloff, scatterColor, scatterDirection, scatterPower, scatterStrength, startDistance }) => {
|
|
651
803
|
const cameraWorldMatrix = uniform(camera.matrixWorld);
|
|
652
804
|
const cameraProjectionMatrixInverse = uniform(camera.projectionMatrixInverse);
|
|
653
805
|
return Fn(() => {
|
|
@@ -668,7 +820,8 @@ const createHeightFogNode = (colorNode, depthNode, camera, { baseHeight, color,
|
|
|
668
820
|
opticalDepth.assign(densityAtStart.mul(float(1).sub(exp(fogLength.mul(climb).negate()))).div(climb));
|
|
669
821
|
});
|
|
670
822
|
const opacity = float(1).sub(exp(opticalDepth.negate()));
|
|
671
|
-
|
|
823
|
+
const scatter = pow(max(ray.normalize().dot(scatterDirection), 0), scatterPower).mul(scatterStrength);
|
|
824
|
+
output.assign(vec4(mix(output.rgb, mix(color, scatterColor, scatter.min(1)), opacity), output.a));
|
|
672
825
|
});
|
|
673
826
|
return output;
|
|
674
827
|
})();
|
|
@@ -770,6 +923,14 @@ const QualityTierSettingsMap = {
|
|
|
770
923
|
}
|
|
771
924
|
};
|
|
772
925
|
//#endregion
|
|
926
|
+
//#region src/renderer/getScreenDirection.ts
|
|
927
|
+
const X_AXIS = new Vector3(1, 0, 0);
|
|
928
|
+
const Y_AXIS = new Vector3(0, 1, 0);
|
|
929
|
+
const getScreenDirection = ({ aspect, fov, pitch, yaw }, [x, y]) => {
|
|
930
|
+
const halfHeight = Math.tan(MathUtils.degToRad(fov) / 2);
|
|
931
|
+
return new Vector3((x * 2 - 1) * halfHeight * aspect, (1 - y * 2) * halfHeight, -1).normalize().applyAxisAngle(X_AXIS, pitch).applyAxisAngle(Y_AXIS, yaw);
|
|
932
|
+
};
|
|
933
|
+
//#endregion
|
|
773
934
|
//#region src/terrain/constants.ts
|
|
774
935
|
const TILE_INDEX_OFFSET = 2 ** 19;
|
|
775
936
|
const TILE_INDEX_SPAN = 2 ** 20;
|
|
@@ -1089,6 +1250,7 @@ const createGrassGeometry = (segmentCount, bladeCount) => {
|
|
|
1089
1250
|
const { indices, positions } = computeGrassBlade(segmentCount);
|
|
1090
1251
|
const grassGeometry = new InstancedBufferGeometry();
|
|
1091
1252
|
grassGeometry.setAttribute("position", new BufferAttribute(positions, 3));
|
|
1253
|
+
grassGeometry.setAttribute("normal", new BufferAttribute(Float32Array.from({ length: positions.length }, (_, index) => index % 3 === 1 ? 1 : 0), 3));
|
|
1092
1254
|
grassGeometry.setIndex(new BufferAttribute(indices, 1));
|
|
1093
1255
|
grassGeometry.instanceCount = bladeCount;
|
|
1094
1256
|
return grassGeometry;
|
|
@@ -1255,4 +1417,4 @@ const computeOutlineDistance = (outline, x, z) => {
|
|
|
1255
1417
|
return isInside ? 0 : Math.sqrt(nearestSquared);
|
|
1256
1418
|
};
|
|
1257
1419
|
//#endregion
|
|
1258
|
-
export { AntialiasingMode, GAME_MINUTES_PER_SECOND, MINUTES_PER_DAY, QualityTier, QualityTierSettingsMap, TERRAIN_LAYER, TILE_INDEX_OFFSET, TILE_INDEX_SPAN, ToonNodeMaterial, advanceGameClock, applySkyState, computeGradeLut, computeGrassBlade, computeLeafCards, computeOriginShift, computeOutlineDistance, computeRampValues, computeSunDirection, computeTerrainIndices, computeTerrainTile, computeTreeSkeleton, createCausticsNode, createFogUniforms, createGenshinRenderer, createGodraysLight, createGradeLutTexture, createGrassGeometry, createGrassMaterial, createGroundCapture, createHeightFogNode, createLeafMaterial, createLightUniforms, createPostPipeline, createPostUniforms, createRampTexture, createRimNode, createSeededRandom, createSimplexNoise, createSkyNode, createSkyState, createSkyUniforms, createStatueGeometry, createSunLight, createTerrainMaterial, createTerrainSelection, createTerrainTileGeometry, createTileStreamer, createToonMaterial, createTreeGeometry, createUnderwaterFogState, createWaterMaterial, createWaterUniforms, createWindNode, createWindUniforms, getParentTerrainTileKey, getTerrainTileColumn, getTerrainTileKey, getTerrainTileLevel, getTerrainTileRow, renderGroundCapture, resolveTerrainDraws, sampleSkyState, selectTerrainTiles, updateUnderwaterFog };
|
|
1420
|
+
export { AntialiasingMode, GAME_MINUTES_PER_SECOND, GENSHIN_TONE_MAPPING, MINUTES_PER_DAY, QualityTier, QualityTierSettingsMap, TERRAIN_LAYER, TILE_INDEX_OFFSET, TILE_INDEX_SPAN, ToonNodeMaterial, advanceGameClock, applySkyState, computeGradeLut, computeGrassBlade, computeLeafCards, computeOriginShift, computeOutlineDistance, computeRampValues, computeSunDirection, computeTerrainIndices, computeTerrainTile, computeTreeSkeleton, createCausticsNode, createCloudAtlasTexture, createCloudSpriteMaterial, createFogUniforms, createGenshinRenderer, createGodraysLight, createGradeLutTexture, createGrassGeometry, createGrassMaterial, createGroundCapture, createHeightFogNode, createLatheStackGeometry, createLeafMaterial, createLightUniforms, createPostPipeline, createPostUniforms, createRampTexture, createRimNode, createSeededRandom, createSilhouetteGeometry, createSimplexNoise, createSkyNode, createSkyState, createSkyUniforms, createStatueGeometry, createSunLight, createTerrainMaterial, createTerrainSelection, createTerrainTileGeometry, createTileStreamer, createToonMaterial, createTreeGeometry, createUnderwaterFogState, createWaterMaterial, createWaterUniforms, createWindNode, createWindUniforms, getCloudAtlasColumns, getParentTerrainTileKey, getScreenDirection, getTerrainTileColumn, getTerrainTileKey, getTerrainTileLevel, getTerrainTileRow, placeCloudBand, renderGroundCapture, resolveTerrainDraws, sampleSkyState, selectTerrainTiles, toSceneColor, updateUnderwaterFog };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genshin-engine",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.1",
|
|
4
4
|
"description": "An anime-style open-world engine for the browser on three.js WebGPU — toon materials, outlines, post-processing, streamed terrain and parametric world kits, as plain TypeScript and TSL modules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anime",
|
|
@@ -53,16 +53,16 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@arethetypeswrong/core": "^0.18.5",
|
|
56
|
-
"@esposter/configuration": "3.
|
|
57
|
-
"@esposter/shared-node": "3.
|
|
56
|
+
"@esposter/configuration": "3.8.1",
|
|
57
|
+
"@esposter/shared-node": "3.8.1",
|
|
58
58
|
"@types/node": "^26.6.3",
|
|
59
59
|
"@types/three": "^0.186.0",
|
|
60
60
|
"publint": "^0.3.24",
|
|
61
61
|
"tsdown": "^0.23.0",
|
|
62
|
-
"vitest": "^5.0.
|
|
62
|
+
"vitest": "^5.0.3"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"three": "^0.186.1"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "1cc0b24081a5fd56ec0c57b784f978f1ad0df0f4"
|
|
68
68
|
}
|