reze-engine 0.9.2 → 0.9.4
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 +3 -0
- package/dist/engine.d.ts +4 -3
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +19 -31
- package/package.json +1 -1
- package/src/engine.ts +20 -29
package/README.md
CHANGED
|
@@ -97,12 +97,15 @@ engine.runRenderLoop()
|
|
|
97
97
|
cameraTarget: Vec3,
|
|
98
98
|
cameraFov: number,
|
|
99
99
|
onRaycast: (modelName, material, screenX, screenY) => void,
|
|
100
|
+
shadowLightDirection: Vec3,
|
|
100
101
|
physicsOptions: {
|
|
101
102
|
constraintSolverKeywords: string[],
|
|
102
103
|
},
|
|
103
104
|
}
|
|
104
105
|
```
|
|
105
106
|
|
|
107
|
+
`shadowLightDirection` — direction of the shadow-only light, independent of the visible directional light. Default `(0.12, -1, 0.16)` casts a near-top-down shadow with a slight offset so extended limbs still project visible shadows.
|
|
108
|
+
|
|
106
109
|
`constraintSolverKeywords` — joints whose name contains any keyword use the Bullet 2.75 constraint solver; all others keep the stable Ammo 2.82+ default. See [babylon-mmd: Fix Constraint Behavior](https://noname0310.github.io/babylon-mmd/docs/reference/runtime/apply-physics-to-mmd-models/#fix-constraint-behavior) for details.
|
|
107
110
|
|
|
108
111
|
## Projects Using This Engine
|
package/dist/engine.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type EngineOptions = {
|
|
|
12
12
|
cameraFov?: number;
|
|
13
13
|
onRaycast?: RaycastCallback;
|
|
14
14
|
physicsOptions?: PhysicsOptions;
|
|
15
|
+
shadowLightDirection?: Vec3;
|
|
15
16
|
};
|
|
16
17
|
export declare const DEFAULT_ENGINE_OPTIONS: {
|
|
17
18
|
ambientColor: Vec3;
|
|
@@ -25,6 +26,7 @@ export declare const DEFAULT_ENGINE_OPTIONS: {
|
|
|
25
26
|
physicsOptions: {
|
|
26
27
|
constraintSolverKeywords: string[];
|
|
27
28
|
};
|
|
29
|
+
shadowLightDirection: Vec3;
|
|
28
30
|
};
|
|
29
31
|
export interface EngineStats {
|
|
30
32
|
fps: number;
|
|
@@ -78,11 +80,9 @@ export declare class Engine {
|
|
|
78
80
|
private shadowComparisonSampler;
|
|
79
81
|
private groundShadowMaterialBuffer?;
|
|
80
82
|
private groundDrawCall;
|
|
81
|
-
private shadowVPLightX;
|
|
82
|
-
private shadowVPLightY;
|
|
83
|
-
private shadowVPLightZ;
|
|
84
83
|
private onRaycast?;
|
|
85
84
|
private physicsOptions;
|
|
85
|
+
private shadowLightDirection;
|
|
86
86
|
private lastTouchTime;
|
|
87
87
|
private readonly DOUBLE_TAP_DELAY;
|
|
88
88
|
private pickPipeline;
|
|
@@ -168,6 +168,7 @@ export declare class Engine {
|
|
|
168
168
|
private setupModelInstance;
|
|
169
169
|
private createGroundGeometry;
|
|
170
170
|
private createShadowGroundResources;
|
|
171
|
+
private shadowLightVPDirty;
|
|
171
172
|
private updateShadowLightVP;
|
|
172
173
|
private setupMaterialsForInstance;
|
|
173
174
|
private createMaterialUniformBuffer;
|
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,EAAQ,IAAI,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAE/B,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AAExD,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;AAEpH,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,CAAC,EAAE,IAAI,CAAA;IACnB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,cAAc,CAAC,EAAE,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -12,6 +12,7 @@ export const DEFAULT_ENGINE_OPTIONS = {
|
|
|
12
12
|
cameraFov: Math.PI / 4,
|
|
13
13
|
onRaycast: undefined,
|
|
14
14
|
physicsOptions: { constraintSolverKeywords: ["胸"] },
|
|
15
|
+
shadowLightDirection: new Vec3(0.12, -1, 0.16),
|
|
15
16
|
};
|
|
16
17
|
export class Engine {
|
|
17
18
|
static getInstance() {
|
|
@@ -28,10 +29,8 @@ export class Engine {
|
|
|
28
29
|
this.hasGround = false;
|
|
29
30
|
this.shadowLightVPMatrix = new Float32Array(16);
|
|
30
31
|
this.groundDrawCall = null;
|
|
31
|
-
this.shadowVPLightX = Number.NaN;
|
|
32
|
-
this.shadowVPLightY = Number.NaN;
|
|
33
|
-
this.shadowVPLightZ = Number.NaN;
|
|
34
32
|
this.physicsOptions = DEFAULT_ENGINE_OPTIONS.physicsOptions;
|
|
33
|
+
this.shadowLightDirection = DEFAULT_ENGINE_OPTIONS.shadowLightDirection;
|
|
35
34
|
this.lastTouchTime = 0;
|
|
36
35
|
this.DOUBLE_TAP_DELAY = 300;
|
|
37
36
|
this.pendingPick = null;
|
|
@@ -56,6 +55,8 @@ export class Engine {
|
|
|
56
55
|
};
|
|
57
56
|
this.animationFrameId = null;
|
|
58
57
|
this.renderLoopCallback = null;
|
|
58
|
+
// Shadow uses a fixed orthographic projection, independent of the visible light direction
|
|
59
|
+
this.shadowLightVPDirty = true;
|
|
59
60
|
this.handleCanvasDoubleClick = (event) => {
|
|
60
61
|
if (!this.onRaycast || this.modelInstances.size === 0)
|
|
61
62
|
return;
|
|
@@ -99,6 +100,7 @@ export class Engine {
|
|
|
99
100
|
this.cameraFov = options.cameraFov ?? DEFAULT_ENGINE_OPTIONS.cameraFov;
|
|
100
101
|
this.onRaycast = options.onRaycast;
|
|
101
102
|
this.physicsOptions = options.physicsOptions ?? DEFAULT_ENGINE_OPTIONS.physicsOptions;
|
|
103
|
+
this.shadowLightDirection = options.shadowLightDirection ?? DEFAULT_ENGINE_OPTIONS.shadowLightDirection;
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
// Step 1: Get WebGPU device and context
|
|
@@ -468,16 +470,12 @@ export class Engine {
|
|
|
468
470
|
let st = material.pcfTexel;
|
|
469
471
|
let compareZ = ndc.z - 0.0035;
|
|
470
472
|
var vis = 0.0;
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
vis
|
|
477
|
-
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, st), compareZ);
|
|
478
|
-
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(0.0, st), compareZ);
|
|
479
|
-
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, st), compareZ);
|
|
480
|
-
vis *= 0.1111111;
|
|
473
|
+
for (var y = -2; y <= 2; y++) {
|
|
474
|
+
for (var x = -2; x <= 2; x++) {
|
|
475
|
+
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(f32(x), f32(y)) * st, compareZ);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
vis *= 0.04;
|
|
481
479
|
let sun = light.ambientColor.xyz + light.lights[0].color.xyz * light.lights[0].color.w * max(dot(n, -light.lights[0].direction.xyz), 0.0);
|
|
482
480
|
let dark = (1.0 - vis) * material.shadowStrength;
|
|
483
481
|
let lit = material.diffuseColor * sun * (1.0 - dark * 0.65);
|
|
@@ -576,7 +574,7 @@ export class Engine {
|
|
|
576
574
|
// Screen-stable edgeline: extrusion ∝ camera distance (same idea as MMD viewers / babylon-mmd-style scaling)
|
|
577
575
|
let camDist = max(length(camera.viewPos - worldPos), 0.25);
|
|
578
576
|
let refDist = 30.0;
|
|
579
|
-
let edgeScale = 0.
|
|
577
|
+
let edgeScale = 0.032;
|
|
580
578
|
let expandedPos = worldPos + worldNormal * material.edgeSize * edgeScale * (camDist / refDist);
|
|
581
579
|
output.position = camera.projection * camera.view * vec4f(expandedPos, 1.0);
|
|
582
580
|
return output;
|
|
@@ -1188,7 +1186,7 @@ export class Engine {
|
|
|
1188
1186
|
gb[3] = fadeStart;
|
|
1189
1187
|
gb[4] = fadeEnd;
|
|
1190
1188
|
gb[5] = shadowStrength;
|
|
1191
|
-
gb[6] = 1
|
|
1189
|
+
gb[6] = 1 / shadowMapSize;
|
|
1192
1190
|
gb[7] = 0;
|
|
1193
1191
|
this.groundShadowMaterialBuffer = this.device.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
|
|
1194
1192
|
this.device.queue.writeBuffer(this.groundShadowMaterialBuffer, 0, gb);
|
|
@@ -1206,25 +1204,15 @@ export class Engine {
|
|
|
1206
1204
|
});
|
|
1207
1205
|
}
|
|
1208
1206
|
updateShadowLightVP() {
|
|
1209
|
-
|
|
1210
|
-
const ly = this.lightData[5];
|
|
1211
|
-
const lz = this.lightData[6];
|
|
1212
|
-
if (lx === this.shadowVPLightX && ly === this.shadowVPLightY && lz === this.shadowVPLightZ)
|
|
1207
|
+
if (!this.shadowLightVPDirty)
|
|
1213
1208
|
return;
|
|
1214
|
-
this.
|
|
1215
|
-
this.
|
|
1216
|
-
|
|
1217
|
-
const dir = new Vec3(lx, ly, lz);
|
|
1218
|
-
if (dir.length() < 1e-6) {
|
|
1219
|
-
dir.x = 0.35;
|
|
1220
|
-
dir.y = -1;
|
|
1221
|
-
dir.z = 0.2;
|
|
1222
|
-
}
|
|
1223
|
-
else
|
|
1224
|
-
dir.normalize();
|
|
1209
|
+
this.shadowLightVPDirty = false;
|
|
1210
|
+
const dir = new Vec3(this.shadowLightDirection.x, this.shadowLightDirection.y, this.shadowLightDirection.z);
|
|
1211
|
+
dir.normalize();
|
|
1225
1212
|
const target = new Vec3(0, 11, 0);
|
|
1226
1213
|
const eye = new Vec3(target.x - dir.x * 72, target.y - dir.y * 72, target.z - dir.z * 72);
|
|
1227
|
-
const
|
|
1214
|
+
const up = Math.abs(dir.y) > 0.99 ? new Vec3(0, 0, -1) : new Vec3(0, 1, 0);
|
|
1215
|
+
const view = Mat4.lookAt(eye, target, up);
|
|
1228
1216
|
const proj = Mat4.orthographicLh(-72, 72, -72, 72, 1, 140);
|
|
1229
1217
|
const vp = proj.multiply(view);
|
|
1230
1218
|
this.shadowLightVPMatrix.set(vp.values);
|
package/package.json
CHANGED
package/src/engine.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type EngineOptions = {
|
|
|
16
16
|
cameraFov?: number
|
|
17
17
|
onRaycast?: RaycastCallback
|
|
18
18
|
physicsOptions?: PhysicsOptions
|
|
19
|
+
shadowLightDirection?: Vec3
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export const DEFAULT_ENGINE_OPTIONS = {
|
|
@@ -28,6 +29,7 @@ export const DEFAULT_ENGINE_OPTIONS = {
|
|
|
28
29
|
cameraFov: Math.PI / 4,
|
|
29
30
|
onRaycast: undefined,
|
|
30
31
|
physicsOptions: { constraintSolverKeywords: ["胸"] },
|
|
32
|
+
shadowLightDirection: new Vec3(0.12, -1, 0.16),
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
export interface EngineStats {
|
|
@@ -136,12 +138,10 @@ export class Engine {
|
|
|
136
138
|
private shadowComparisonSampler!: GPUSampler
|
|
137
139
|
private groundShadowMaterialBuffer?: GPUBuffer
|
|
138
140
|
private groundDrawCall: DrawCall | null = null
|
|
139
|
-
private shadowVPLightX = Number.NaN
|
|
140
|
-
private shadowVPLightY = Number.NaN
|
|
141
|
-
private shadowVPLightZ = Number.NaN
|
|
142
141
|
|
|
143
142
|
private onRaycast?: RaycastCallback
|
|
144
143
|
private physicsOptions: PhysicsOptions = DEFAULT_ENGINE_OPTIONS.physicsOptions
|
|
144
|
+
private shadowLightDirection: Vec3 = DEFAULT_ENGINE_OPTIONS.shadowLightDirection
|
|
145
145
|
private lastTouchTime = 0
|
|
146
146
|
private readonly DOUBLE_TAP_DELAY = 300
|
|
147
147
|
// GPU picking
|
|
@@ -194,6 +194,7 @@ export class Engine {
|
|
|
194
194
|
this.cameraFov = options.cameraFov ?? DEFAULT_ENGINE_OPTIONS.cameraFov
|
|
195
195
|
this.onRaycast = options.onRaycast
|
|
196
196
|
this.physicsOptions = options.physicsOptions ?? DEFAULT_ENGINE_OPTIONS.physicsOptions
|
|
197
|
+
this.shadowLightDirection = options.shadowLightDirection ?? DEFAULT_ENGINE_OPTIONS.shadowLightDirection
|
|
197
198
|
}
|
|
198
199
|
}
|
|
199
200
|
|
|
@@ -589,16 +590,12 @@ export class Engine {
|
|
|
589
590
|
let st = material.pcfTexel;
|
|
590
591
|
let compareZ = ndc.z - 0.0035;
|
|
591
592
|
var vis = 0.0;
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
vis
|
|
598
|
-
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(-st, st), compareZ);
|
|
599
|
-
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(0.0, st), compareZ);
|
|
600
|
-
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(st, st), compareZ);
|
|
601
|
-
vis *= 0.1111111;
|
|
593
|
+
for (var y = -2; y <= 2; y++) {
|
|
594
|
+
for (var x = -2; x <= 2; x++) {
|
|
595
|
+
vis += textureSampleCompare(shadowMap, shadowSampler, suv_c + vec2f(f32(x), f32(y)) * st, compareZ);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
vis *= 0.04;
|
|
602
599
|
let sun = light.ambientColor.xyz + light.lights[0].color.xyz * light.lights[0].color.w * max(dot(n, -light.lights[0].direction.xyz), 0.0);
|
|
603
600
|
let dark = (1.0 - vis) * material.shadowStrength;
|
|
604
601
|
let lit = material.diffuseColor * sun * (1.0 - dark * 0.65);
|
|
@@ -701,7 +698,7 @@ export class Engine {
|
|
|
701
698
|
// Screen-stable edgeline: extrusion ∝ camera distance (same idea as MMD viewers / babylon-mmd-style scaling)
|
|
702
699
|
let camDist = max(length(camera.viewPos - worldPos), 0.25);
|
|
703
700
|
let refDist = 30.0;
|
|
704
|
-
let edgeScale = 0.
|
|
701
|
+
let edgeScale = 0.032;
|
|
705
702
|
let expandedPos = worldPos + worldNormal * material.edgeSize * edgeScale * (camDist / refDist);
|
|
706
703
|
output.position = camera.projection * camera.view * vec4f(expandedPos, 1.0);
|
|
707
704
|
return output;
|
|
@@ -1415,7 +1412,7 @@ export class Engine {
|
|
|
1415
1412
|
gb[3] = fadeStart
|
|
1416
1413
|
gb[4] = fadeEnd
|
|
1417
1414
|
gb[5] = shadowStrength
|
|
1418
|
-
gb[6] = 1
|
|
1415
|
+
gb[6] = 1 / shadowMapSize
|
|
1419
1416
|
gb[7] = 0
|
|
1420
1417
|
this.groundShadowMaterialBuffer = this.device.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST })
|
|
1421
1418
|
this.device.queue.writeBuffer(this.groundShadowMaterialBuffer, 0, gb)
|
|
@@ -1433,23 +1430,17 @@ export class Engine {
|
|
|
1433
1430
|
})
|
|
1434
1431
|
}
|
|
1435
1432
|
|
|
1433
|
+
// Shadow uses a fixed orthographic projection, independent of the visible light direction
|
|
1434
|
+
private shadowLightVPDirty = true
|
|
1436
1435
|
private updateShadowLightVP() {
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
this.shadowVPLightX = lx
|
|
1442
|
-
this.shadowVPLightY = ly
|
|
1443
|
-
this.shadowVPLightZ = lz
|
|
1444
|
-
const dir = new Vec3(lx, ly, lz)
|
|
1445
|
-
if (dir.length() < 1e-6) {
|
|
1446
|
-
dir.x = 0.35
|
|
1447
|
-
dir.y = -1
|
|
1448
|
-
dir.z = 0.2
|
|
1449
|
-
} else dir.normalize()
|
|
1436
|
+
if (!this.shadowLightVPDirty) return
|
|
1437
|
+
this.shadowLightVPDirty = false
|
|
1438
|
+
const dir = new Vec3(this.shadowLightDirection.x, this.shadowLightDirection.y, this.shadowLightDirection.z)
|
|
1439
|
+
dir.normalize()
|
|
1450
1440
|
const target = new Vec3(0, 11, 0)
|
|
1451
1441
|
const eye = new Vec3(target.x - dir.x * 72, target.y - dir.y * 72, target.z - dir.z * 72)
|
|
1452
|
-
const
|
|
1442
|
+
const up = Math.abs(dir.y) > 0.99 ? new Vec3(0, 0, -1) : new Vec3(0, 1, 0)
|
|
1443
|
+
const view = Mat4.lookAt(eye, target, up)
|
|
1453
1444
|
const proj = Mat4.orthographicLh(-72, 72, -72, 72, 1, 140)
|
|
1454
1445
|
const vp = proj.multiply(view)
|
|
1455
1446
|
this.shadowLightVPMatrix.set(vp.values)
|