reze-engine 0.3.12 → 0.3.14
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/README.md +66 -66
- package/dist/bezier-interpolate.d.ts +15 -0
- package/dist/bezier-interpolate.d.ts.map +1 -0
- package/dist/bezier-interpolate.js +40 -0
- package/dist/engine.d.ts +4 -8
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +21 -30
- package/dist/engine_r.d.ts +132 -0
- package/dist/engine_r.d.ts.map +1 -0
- package/dist/engine_r.js +1489 -0
- package/dist/engine_ts.d.ts +143 -0
- package/dist/engine_ts.d.ts.map +1 -0
- package/dist/engine_ts.js +1575 -0
- package/dist/player.d.ts +64 -0
- package/dist/player.d.ts.map +1 -0
- package/dist/player.js +220 -0
- package/package.json +1 -1
- package/src/camera.ts +358 -358
- package/src/engine.ts +31 -28
- package/src/ik-solver.ts +411 -411
- package/src/math.ts +584 -584
- package/src/physics.ts +742 -742
- package/src/vmd-loader.ts +276 -276
- package/dist/audio.d.ts +0 -29
- package/dist/audio.d.ts.map +0 -1
- package/dist/audio.js +0 -116
- package/dist/particles.d.ts +0 -67
- package/dist/particles.d.ts.map +0 -1
- package/dist/particles.js +0 -266
package/README.md
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
# Reze Engine
|
|
2
|
-
|
|
3
|
-
A lightweight engine built with WebGPU and TypeScript for real-time 3D anime character MMD model rendering.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Physics
|
|
8
|
-
- Alpha blending
|
|
9
|
-
- Post alpha eye rendering
|
|
10
|
-
- Rim lighting
|
|
11
|
-
- Bloom
|
|
12
|
-
- Outlines
|
|
13
|
-
- MSAA 4x anti-aliasing
|
|
14
|
-
- Bone and morph api
|
|
15
|
-
- VMD animation
|
|
16
|
-
- Ik solver
|
|
17
|
-
|
|
18
|
-
## Usage
|
|
19
|
-
|
|
20
|
-
```javascript
|
|
21
|
-
export default function Scene() {
|
|
22
|
-
const canvasRef = useRef < HTMLCanvasElement > null
|
|
23
|
-
const engineRef = useRef < Engine > null
|
|
24
|
-
|
|
25
|
-
const initEngine = useCallback(async () => {
|
|
26
|
-
if (canvasRef.current) {
|
|
27
|
-
try {
|
|
28
|
-
const engine = new Engine(canvasRef.current)
|
|
29
|
-
engineRef.current = engine
|
|
30
|
-
await engine.init()
|
|
31
|
-
await engine.loadModel("/models/塞尔凯特/塞尔凯特.pmx")
|
|
32
|
-
|
|
33
|
-
engine.runRenderLoop(() => {})
|
|
34
|
-
} catch (error) {
|
|
35
|
-
console.error(error)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}, [])
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
void (async () => {
|
|
42
|
-
initEngine()
|
|
43
|
-
})()
|
|
44
|
-
|
|
45
|
-
return () => {
|
|
46
|
-
if (engineRef.current) {
|
|
47
|
-
engineRef.current.dispose()
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}, [initEngine])
|
|
51
|
-
|
|
52
|
-
return <canvas ref={canvasRef} className="w-full h-full" />
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Projects Using This Engine
|
|
57
|
-
|
|
58
|
-
- **[MiKaPo](https://mikapo.vercel.app)** - Online real-time motion capture for MMD using webcam and MediaPipe
|
|
59
|
-
- **[Popo](https://popo.love)** - Fine-tuned LLM that generates MMD poses from natural language descriptions
|
|
60
|
-
- **[MPL](https://mmd-mpl.vercel.app)** - Semantic motion programming language for scripting MMD animations with intuitive syntax
|
|
61
|
-
|
|
62
|
-
## Tutorial
|
|
63
|
-
|
|
64
|
-
Learn WebGPU from scratch by building an anime character renderer in incremental steps. The tutorial covers the complete rendering pipeline from a simple triangle to fully textured, skeletal-animated characters.
|
|
65
|
-
|
|
66
|
-
[How to Render an Anime Character with WebGPU](https://reze.one/tutorial)
|
|
1
|
+
# Reze Engine
|
|
2
|
+
|
|
3
|
+
A lightweight engine built with WebGPU and TypeScript for real-time 3D anime character MMD model rendering.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Physics
|
|
8
|
+
- Alpha blending
|
|
9
|
+
- Post alpha eye rendering
|
|
10
|
+
- Rim lighting
|
|
11
|
+
- Bloom
|
|
12
|
+
- Outlines
|
|
13
|
+
- MSAA 4x anti-aliasing
|
|
14
|
+
- Bone and morph api
|
|
15
|
+
- VMD animation
|
|
16
|
+
- Ik solver
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
export default function Scene() {
|
|
22
|
+
const canvasRef = useRef < HTMLCanvasElement > null
|
|
23
|
+
const engineRef = useRef < Engine > null
|
|
24
|
+
|
|
25
|
+
const initEngine = useCallback(async () => {
|
|
26
|
+
if (canvasRef.current) {
|
|
27
|
+
try {
|
|
28
|
+
const engine = new Engine(canvasRef.current)
|
|
29
|
+
engineRef.current = engine
|
|
30
|
+
await engine.init()
|
|
31
|
+
await engine.loadModel("/models/塞尔凯特/塞尔凯特.pmx")
|
|
32
|
+
|
|
33
|
+
engine.runRenderLoop(() => {})
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error(error)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}, [])
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
void (async () => {
|
|
42
|
+
initEngine()
|
|
43
|
+
})()
|
|
44
|
+
|
|
45
|
+
return () => {
|
|
46
|
+
if (engineRef.current) {
|
|
47
|
+
engineRef.current.dispose()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, [initEngine])
|
|
51
|
+
|
|
52
|
+
return <canvas ref={canvasRef} className="w-full h-full" />
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Projects Using This Engine
|
|
57
|
+
|
|
58
|
+
- **[MiKaPo](https://mikapo.vercel.app)** - Online real-time motion capture for MMD using webcam and MediaPipe
|
|
59
|
+
- **[Popo](https://popo.love)** - Fine-tuned LLM that generates MMD poses from natural language descriptions
|
|
60
|
+
- **[MPL](https://mmd-mpl.vercel.app)** - Semantic motion programming language for scripting MMD animations with intuitive syntax
|
|
61
|
+
|
|
62
|
+
## Tutorial
|
|
63
|
+
|
|
64
|
+
Learn WebGPU from scratch by building an anime character renderer in incremental steps. The tutorial covers the complete rendering pipeline from a simple triangle to fully textured, skeletal-animated characters.
|
|
65
|
+
|
|
66
|
+
[How to Render an Anime Character with WebGPU](https://reze.one/tutorial)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bezier interpolation for VMD animations
|
|
3
|
+
* Based on the reference implementation from babylon-mmd
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Bezier interpolation function
|
|
7
|
+
* @param x1 First control point X (0-127, normalized to 0-1)
|
|
8
|
+
* @param x2 Second control point X (0-127, normalized to 0-1)
|
|
9
|
+
* @param y1 First control point Y (0-127, normalized to 0-1)
|
|
10
|
+
* @param y2 Second control point Y (0-127, normalized to 0-1)
|
|
11
|
+
* @param t Interpolation parameter (0-1)
|
|
12
|
+
* @returns Interpolated value (0-1)
|
|
13
|
+
*/
|
|
14
|
+
export declare function bezierInterpolate(x1: number, x2: number, y1: number, y2: number, t: number): number;
|
|
15
|
+
//# sourceMappingURL=bezier-interpolate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bezier-interpolate.d.ts","sourceRoot":"","sources":["../src/bezier-interpolate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgCnG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bezier interpolation for VMD animations
|
|
3
|
+
* Based on the reference implementation from babylon-mmd
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Bezier interpolation function
|
|
7
|
+
* @param x1 First control point X (0-127, normalized to 0-1)
|
|
8
|
+
* @param x2 Second control point X (0-127, normalized to 0-1)
|
|
9
|
+
* @param y1 First control point Y (0-127, normalized to 0-1)
|
|
10
|
+
* @param y2 Second control point Y (0-127, normalized to 0-1)
|
|
11
|
+
* @param t Interpolation parameter (0-1)
|
|
12
|
+
* @returns Interpolated value (0-1)
|
|
13
|
+
*/
|
|
14
|
+
export function bezierInterpolate(x1, x2, y1, y2, t) {
|
|
15
|
+
// Clamp t to [0, 1]
|
|
16
|
+
t = Math.max(0, Math.min(1, t));
|
|
17
|
+
// Binary search for the t value that gives us the desired x
|
|
18
|
+
// We're solving for t in the Bezier curve: x(t) = 3*(1-t)^2*t*x1 + 3*(1-t)*t^2*x2 + t^3
|
|
19
|
+
let start = 0;
|
|
20
|
+
let end = 1;
|
|
21
|
+
let mid = 0.5;
|
|
22
|
+
// Iterate until we find the t value that gives us the desired x
|
|
23
|
+
for (let i = 0; i < 15; i++) {
|
|
24
|
+
// Evaluate Bezier curve at mid point
|
|
25
|
+
const x = 3 * (1 - mid) * (1 - mid) * mid * x1 + 3 * (1 - mid) * mid * mid * x2 + mid * mid * mid;
|
|
26
|
+
if (Math.abs(x - t) < 0.0001) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
if (x < t) {
|
|
30
|
+
start = mid;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
end = mid;
|
|
34
|
+
}
|
|
35
|
+
mid = (start + end) / 2;
|
|
36
|
+
}
|
|
37
|
+
// Now evaluate the y value at this t
|
|
38
|
+
const y = 3 * (1 - mid) * (1 - mid) * mid * y1 + 3 * (1 - mid) * mid * mid * y2 + mid * mid * mid;
|
|
39
|
+
return y;
|
|
40
|
+
}
|
package/dist/engine.d.ts
CHANGED
|
@@ -2,10 +2,13 @@ import { Quat, Vec3 } from "./math";
|
|
|
2
2
|
export type EngineOptions = {
|
|
3
3
|
ambientColor?: Vec3;
|
|
4
4
|
bloomIntensity?: number;
|
|
5
|
+
bloomThreshold?: number;
|
|
5
6
|
rimLightIntensity?: number;
|
|
6
7
|
cameraDistance?: number;
|
|
7
8
|
cameraTarget?: Vec3;
|
|
9
|
+
cameraFov?: number;
|
|
8
10
|
};
|
|
11
|
+
export declare const DEFAULT_ENGINE_OPTIONS: Required<EngineOptions>;
|
|
9
12
|
export interface EngineStats {
|
|
10
13
|
fps: number;
|
|
11
14
|
frameTime: number;
|
|
@@ -20,6 +23,7 @@ export declare class Engine {
|
|
|
20
23
|
private cameraMatrixData;
|
|
21
24
|
private cameraDistance;
|
|
22
25
|
private cameraTarget;
|
|
26
|
+
private cameraFov;
|
|
23
27
|
private lightUniformBuffer;
|
|
24
28
|
private lightData;
|
|
25
29
|
private vertexBuffer;
|
|
@@ -44,14 +48,6 @@ export declare class Engine {
|
|
|
44
48
|
private renderPassDescriptor;
|
|
45
49
|
private readonly STENCIL_EYE_VALUE;
|
|
46
50
|
private readonly BLOOM_DOWNSCALE_FACTOR;
|
|
47
|
-
private static readonly DEFAULT_BLOOM_THRESHOLD;
|
|
48
|
-
private static readonly DEFAULT_BLOOM_INTENSITY;
|
|
49
|
-
private static readonly DEFAULT_RIM_LIGHT_INTENSITY;
|
|
50
|
-
private static readonly DEFAULT_CAMERA_DISTANCE;
|
|
51
|
-
private static readonly DEFAULT_CAMERA_TARGET;
|
|
52
|
-
private static readonly TRANSPARENCY_EPSILON;
|
|
53
|
-
private static readonly STATS_FPS_UPDATE_INTERVAL_MS;
|
|
54
|
-
private static readonly STATS_FRAME_TIME_ROUNDING;
|
|
55
51
|
private ambientColor;
|
|
56
52
|
private sceneRenderTexture;
|
|
57
53
|
private sceneRenderTextureView;
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAInC,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,IAAI,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { Camera } from "./camera";
|
|
2
2
|
import { Vec3 } from "./math";
|
|
3
3
|
import { PmxLoader } from "./pmx-loader";
|
|
4
|
+
export const DEFAULT_ENGINE_OPTIONS = {
|
|
5
|
+
ambientColor: new Vec3(1.0, 1.0, 1.0),
|
|
6
|
+
bloomIntensity: 0.12,
|
|
7
|
+
bloomThreshold: 0.5,
|
|
8
|
+
rimLightIntensity: 0.45,
|
|
9
|
+
cameraDistance: 26.6,
|
|
10
|
+
cameraTarget: new Vec3(0, 12.5, 0),
|
|
11
|
+
cameraFov: Math.PI / 4,
|
|
12
|
+
};
|
|
4
13
|
export class Engine {
|
|
5
14
|
constructor(canvas, options) {
|
|
6
15
|
this.cameraMatrixData = new Float32Array(36);
|
|
7
|
-
this.cameraDistance = 26.6;
|
|
8
|
-
this.cameraTarget = new Vec3(0, 12.5, 0);
|
|
9
16
|
this.lightData = new Float32Array(4);
|
|
10
17
|
this.resizeObserver = null;
|
|
11
18
|
this.sampleCount = 4;
|
|
12
19
|
// Constants
|
|
13
20
|
this.STENCIL_EYE_VALUE = 1;
|
|
14
21
|
this.BLOOM_DOWNSCALE_FACTOR = 2;
|
|
15
|
-
// Ambient light settings
|
|
16
|
-
this.ambientColor = new Vec3(1.0, 1.0, 1.0);
|
|
17
|
-
// Bloom settings
|
|
18
|
-
this.bloomThreshold = Engine.DEFAULT_BLOOM_THRESHOLD;
|
|
19
|
-
this.bloomIntensity = Engine.DEFAULT_BLOOM_INTENSITY;
|
|
20
|
-
// Rim light settings
|
|
21
|
-
this.rimLightIntensity = Engine.DEFAULT_RIM_LIGHT_INTENSITY;
|
|
22
22
|
this.currentModel = null;
|
|
23
23
|
this.modelDir = "";
|
|
24
24
|
this.textureCache = new Map();
|
|
@@ -38,11 +38,13 @@ export class Engine {
|
|
|
38
38
|
this.renderLoopCallback = null;
|
|
39
39
|
this.canvas = canvas;
|
|
40
40
|
if (options) {
|
|
41
|
-
this.ambientColor = options.ambientColor ??
|
|
42
|
-
this.bloomIntensity = options.bloomIntensity ??
|
|
43
|
-
this.
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
41
|
+
this.ambientColor = options.ambientColor ?? DEFAULT_ENGINE_OPTIONS.ambientColor;
|
|
42
|
+
this.bloomIntensity = options.bloomIntensity ?? DEFAULT_ENGINE_OPTIONS.bloomIntensity;
|
|
43
|
+
this.bloomThreshold = options.bloomThreshold ?? DEFAULT_ENGINE_OPTIONS.bloomThreshold;
|
|
44
|
+
this.rimLightIntensity = options.rimLightIntensity ?? DEFAULT_ENGINE_OPTIONS.rimLightIntensity;
|
|
45
|
+
this.cameraDistance = options.cameraDistance ?? DEFAULT_ENGINE_OPTIONS.cameraDistance;
|
|
46
|
+
this.cameraTarget = options.cameraTarget ?? DEFAULT_ENGINE_OPTIONS.cameraTarget;
|
|
47
|
+
this.cameraFov = options.cameraFov ?? DEFAULT_ENGINE_OPTIONS.cameraFov;
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
// Step 1: Get WebGPU device and context
|
|
@@ -890,7 +892,7 @@ export class Engine {
|
|
|
890
892
|
size: 40 * 4,
|
|
891
893
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
892
894
|
});
|
|
893
|
-
this.camera = new Camera(Math.PI, Math.PI / 2.5, this.cameraDistance, this.cameraTarget);
|
|
895
|
+
this.camera = new Camera(Math.PI, Math.PI / 2.5, this.cameraDistance, this.cameraTarget, this.cameraFov);
|
|
894
896
|
this.camera.aspect = this.canvas.width / this.canvas.height;
|
|
895
897
|
this.camera.attachControl(this.canvas);
|
|
896
898
|
}
|
|
@@ -1070,7 +1072,7 @@ export class Engine {
|
|
|
1070
1072
|
if (!diffuseTexture)
|
|
1071
1073
|
throw new Error(`Material "${mat.name}" has no diffuse texture`);
|
|
1072
1074
|
const materialAlpha = mat.diffuse[3];
|
|
1073
|
-
const isTransparent = materialAlpha < 1.0 -
|
|
1075
|
+
const isTransparent = materialAlpha < 1.0 - 0.001;
|
|
1074
1076
|
const materialUniformBuffer = this.createMaterialUniformBuffer(mat.name, materialAlpha, 0.0);
|
|
1075
1077
|
// Create bind groups using the shared bind group layout - All pipelines (main, eye, hair multiply, hair opaque) use the same shader and layout
|
|
1076
1078
|
const bindGroup = this.device.createBindGroup({
|
|
@@ -1460,26 +1462,15 @@ export class Engine {
|
|
|
1460
1462
|
this.frameTimeSum -= avg;
|
|
1461
1463
|
this.frameTimeCount = maxSamples;
|
|
1462
1464
|
}
|
|
1463
|
-
this.stats.frameTime =
|
|
1464
|
-
Math.round((this.frameTimeSum / this.frameTimeCount) * Engine.STATS_FRAME_TIME_ROUNDING) /
|
|
1465
|
-
Engine.STATS_FRAME_TIME_ROUNDING;
|
|
1465
|
+
this.stats.frameTime = Math.round((this.frameTimeSum / this.frameTimeCount) * 100) / 100;
|
|
1466
1466
|
// FPS tracking
|
|
1467
1467
|
const now = performance.now();
|
|
1468
1468
|
this.framesSinceLastUpdate++;
|
|
1469
1469
|
const elapsed = now - this.lastFpsUpdate;
|
|
1470
|
-
if (elapsed >=
|
|
1471
|
-
this.stats.fps = Math.round((this.framesSinceLastUpdate / elapsed) *
|
|
1470
|
+
if (elapsed >= 1000) {
|
|
1471
|
+
this.stats.fps = Math.round((this.framesSinceLastUpdate / elapsed) * 1000);
|
|
1472
1472
|
this.framesSinceLastUpdate = 0;
|
|
1473
1473
|
this.lastFpsUpdate = now;
|
|
1474
1474
|
}
|
|
1475
1475
|
}
|
|
1476
1476
|
}
|
|
1477
|
-
// Default values
|
|
1478
|
-
Engine.DEFAULT_BLOOM_THRESHOLD = 0.01;
|
|
1479
|
-
Engine.DEFAULT_BLOOM_INTENSITY = 0.12;
|
|
1480
|
-
Engine.DEFAULT_RIM_LIGHT_INTENSITY = 0.45;
|
|
1481
|
-
Engine.DEFAULT_CAMERA_DISTANCE = 26.6;
|
|
1482
|
-
Engine.DEFAULT_CAMERA_TARGET = new Vec3(0, 12.5, 0);
|
|
1483
|
-
Engine.TRANSPARENCY_EPSILON = 0.001;
|
|
1484
|
-
Engine.STATS_FPS_UPDATE_INTERVAL_MS = 1000;
|
|
1485
|
-
Engine.STATS_FRAME_TIME_ROUNDING = 100;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Quat, Vec3 } from "reze-mmd";
|
|
2
|
+
export type EngineOptions = {
|
|
3
|
+
ambientColor?: Vec3;
|
|
4
|
+
bloomIntensity?: number;
|
|
5
|
+
rimLightIntensity?: number;
|
|
6
|
+
cameraDistance?: number;
|
|
7
|
+
cameraTarget?: Vec3;
|
|
8
|
+
};
|
|
9
|
+
export interface EngineStats {
|
|
10
|
+
fps: number;
|
|
11
|
+
frameTime: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class Engine {
|
|
14
|
+
private canvas;
|
|
15
|
+
private device;
|
|
16
|
+
private context;
|
|
17
|
+
private presentationFormat;
|
|
18
|
+
private camera;
|
|
19
|
+
private cameraUniformBuffer;
|
|
20
|
+
private cameraMatrixData;
|
|
21
|
+
private cameraDistance;
|
|
22
|
+
private cameraTarget;
|
|
23
|
+
private lightUniformBuffer;
|
|
24
|
+
private lightData;
|
|
25
|
+
private vertexBuffer;
|
|
26
|
+
private indexBuffer?;
|
|
27
|
+
private resizeObserver;
|
|
28
|
+
private depthTexture;
|
|
29
|
+
private modelPipeline;
|
|
30
|
+
private eyePipeline;
|
|
31
|
+
private hairPipelineOverEyes;
|
|
32
|
+
private hairPipelineOverNonEyes;
|
|
33
|
+
private hairDepthPipeline;
|
|
34
|
+
private outlinePipeline;
|
|
35
|
+
private hairOutlinePipeline;
|
|
36
|
+
private mainBindGroupLayout;
|
|
37
|
+
private outlineBindGroupLayout;
|
|
38
|
+
private jointsBuffer;
|
|
39
|
+
private weightsBuffer;
|
|
40
|
+
private skinMatrixBuffer?;
|
|
41
|
+
private multisampleTexture;
|
|
42
|
+
private readonly sampleCount;
|
|
43
|
+
private renderPassDescriptor;
|
|
44
|
+
private readonly STENCIL_EYE_VALUE;
|
|
45
|
+
private readonly BLOOM_DOWNSCALE_FACTOR;
|
|
46
|
+
private static readonly DEFAULT_BLOOM_THRESHOLD;
|
|
47
|
+
private static readonly DEFAULT_BLOOM_INTENSITY;
|
|
48
|
+
private static readonly DEFAULT_RIM_LIGHT_INTENSITY;
|
|
49
|
+
private static readonly DEFAULT_CAMERA_DISTANCE;
|
|
50
|
+
private static readonly DEFAULT_CAMERA_TARGET;
|
|
51
|
+
private static readonly TRANSPARENCY_EPSILON;
|
|
52
|
+
private static readonly STATS_FPS_UPDATE_INTERVAL_MS;
|
|
53
|
+
private static readonly STATS_FRAME_TIME_ROUNDING;
|
|
54
|
+
private ambientColor;
|
|
55
|
+
private sceneRenderTexture;
|
|
56
|
+
private sceneRenderTextureView;
|
|
57
|
+
private bloomExtractTexture;
|
|
58
|
+
private bloomBlurTexture1;
|
|
59
|
+
private bloomBlurTexture2;
|
|
60
|
+
private bloomExtractPipeline;
|
|
61
|
+
private bloomBlurPipeline;
|
|
62
|
+
private bloomComposePipeline;
|
|
63
|
+
private blurDirectionBuffer;
|
|
64
|
+
private bloomIntensityBuffer;
|
|
65
|
+
private bloomThresholdBuffer;
|
|
66
|
+
private linearSampler;
|
|
67
|
+
private bloomExtractBindGroup?;
|
|
68
|
+
private bloomBlurHBindGroup?;
|
|
69
|
+
private bloomBlurVBindGroup?;
|
|
70
|
+
private bloomComposeBindGroup?;
|
|
71
|
+
private bloomThreshold;
|
|
72
|
+
private bloomIntensity;
|
|
73
|
+
private rimLightIntensity;
|
|
74
|
+
private model;
|
|
75
|
+
private modelDir;
|
|
76
|
+
private physics;
|
|
77
|
+
private materialSampler;
|
|
78
|
+
private textureCache;
|
|
79
|
+
private vertexBufferNeedsUpdate;
|
|
80
|
+
private drawCalls;
|
|
81
|
+
private lastFpsUpdate;
|
|
82
|
+
private framesSinceLastUpdate;
|
|
83
|
+
private lastFrameTime;
|
|
84
|
+
private frameTimeSum;
|
|
85
|
+
private frameTimeCount;
|
|
86
|
+
private stats;
|
|
87
|
+
private animationFrameId;
|
|
88
|
+
private renderLoopCallback;
|
|
89
|
+
private player;
|
|
90
|
+
private hasAnimation;
|
|
91
|
+
constructor(canvas: HTMLCanvasElement, options?: EngineOptions);
|
|
92
|
+
init(): Promise<void>;
|
|
93
|
+
private createRenderPipeline;
|
|
94
|
+
private createPipelines;
|
|
95
|
+
private createBloomPipelines;
|
|
96
|
+
private setupBloom;
|
|
97
|
+
private setupResize;
|
|
98
|
+
private handleResize;
|
|
99
|
+
private setupCamera;
|
|
100
|
+
private setupLighting;
|
|
101
|
+
private setAmbientColor;
|
|
102
|
+
loadAnimation(url: string): Promise<void>;
|
|
103
|
+
playAnimation(): void;
|
|
104
|
+
stopAnimation(): void;
|
|
105
|
+
pauseAnimation(): void;
|
|
106
|
+
seekAnimation(time: number): void;
|
|
107
|
+
getAnimationProgress(): import("./player").AnimationProgress;
|
|
108
|
+
getStats(): EngineStats;
|
|
109
|
+
runRenderLoop(callback?: () => void): void;
|
|
110
|
+
stopRenderLoop(): void;
|
|
111
|
+
dispose(): void;
|
|
112
|
+
loadModel(path: string): Promise<void>;
|
|
113
|
+
rotateBones(bones: string[], rotations: Quat[], durationMs?: number): void;
|
|
114
|
+
moveBones(bones: string[], relativeTranslations: Vec3[], durationMs?: number): void;
|
|
115
|
+
setMorphWeight(name: string, weight: number, durationMs?: number): void;
|
|
116
|
+
private updateVertexBuffer;
|
|
117
|
+
private setupModelBuffers;
|
|
118
|
+
private setupMaterials;
|
|
119
|
+
private createMaterialUniformBuffer;
|
|
120
|
+
private createUniformBuffer;
|
|
121
|
+
private createTextureFromPath;
|
|
122
|
+
private renderEyes;
|
|
123
|
+
private renderHair;
|
|
124
|
+
render(): void;
|
|
125
|
+
private applyBloom;
|
|
126
|
+
private updateCameraUniforms;
|
|
127
|
+
private updateRenderTarget;
|
|
128
|
+
private computeSkinMatrices;
|
|
129
|
+
private drawOutlines;
|
|
130
|
+
private updateStats;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=engine_r.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine_r.d.ts","sourceRoot":"","sources":["../src/engine_r.ts"],"names":[],"mappings":"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"}
|