@multiplekex/shallot 0.1.12 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -4
- package/src/core/builder.ts +71 -32
- package/src/core/component.ts +25 -11
- package/src/core/index.ts +14 -13
- package/src/core/math.ts +135 -0
- package/src/core/runtime.ts +0 -1
- package/src/core/state.ts +9 -68
- package/src/core/xml.ts +381 -265
- package/src/editor/format.ts +5 -0
- package/src/editor/index.ts +101 -0
- package/src/extras/arrows/index.ts +28 -69
- package/src/extras/gradient/index.ts +36 -52
- package/src/extras/lines/index.ts +51 -122
- package/src/extras/orbit/index.ts +40 -15
- package/src/extras/text/font.ts +546 -0
- package/src/extras/text/index.ts +158 -204
- package/src/extras/text/sdf.ts +429 -0
- package/src/standard/activity/index.ts +172 -0
- package/src/standard/compute/graph.ts +23 -23
- package/src/standard/compute/index.ts +76 -61
- package/src/standard/defaults.ts +8 -5
- package/src/standard/index.ts +1 -0
- package/src/standard/input/index.ts +30 -19
- package/src/standard/loading/index.ts +18 -13
- package/src/standard/render/bvh/blas.ts +752 -0
- package/src/standard/render/bvh/radix.ts +476 -0
- package/src/standard/render/bvh/structs.ts +167 -0
- package/src/standard/render/bvh/tlas.ts +886 -0
- package/src/standard/render/bvh/traverse.ts +467 -0
- package/src/standard/render/camera.ts +302 -27
- package/src/standard/render/data.ts +93 -0
- package/src/standard/render/depth.ts +117 -0
- package/src/standard/render/forward/index.ts +259 -0
- package/src/standard/render/forward/raster.ts +228 -0
- package/src/standard/render/index.ts +443 -70
- package/src/standard/render/indirect.ts +40 -0
- package/src/standard/render/instance.ts +214 -0
- package/src/standard/render/intersection.ts +72 -0
- package/src/standard/render/light.ts +16 -16
- package/src/standard/render/mesh/index.ts +67 -75
- package/src/standard/render/mesh/unified.ts +96 -0
- package/src/standard/render/{transparent.ts → overlay.ts} +14 -15
- package/src/standard/render/pass.ts +10 -4
- package/src/standard/render/postprocess.ts +142 -64
- package/src/standard/render/ray.ts +61 -0
- package/src/standard/render/scene.ts +38 -164
- package/src/standard/render/shaders.ts +484 -0
- package/src/standard/render/surface/compile.ts +3 -10
- package/src/standard/render/surface/index.ts +60 -30
- package/src/standard/render/surface/noise.ts +45 -0
- package/src/standard/render/surface/structs.ts +60 -19
- package/src/standard/render/surface/wgsl.ts +573 -0
- package/src/standard/render/triangle.ts +84 -0
- package/src/standard/transforms/index.ts +4 -6
- package/src/standard/tween/index.ts +10 -1
- package/src/standard/tween/sequence.ts +24 -16
- package/src/standard/tween/tween.ts +67 -16
- package/src/core/types.ts +0 -37
- package/src/standard/compute/inspect.ts +0 -201
- package/src/standard/compute/pass.ts +0 -23
- package/src/standard/compute/timing.ts +0 -139
- package/src/standard/render/forward.ts +0 -273
|
@@ -1,71 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
MAX_ENTITIES,
|
|
3
|
+
resource,
|
|
4
|
+
createFieldProxy,
|
|
5
|
+
type Plugin,
|
|
6
|
+
type State,
|
|
7
|
+
type System,
|
|
8
|
+
type FieldProxy,
|
|
9
|
+
} from "../../core";
|
|
10
|
+
import { setTraits } from "../../core/component";
|
|
3
11
|
import { Compute, ComputePlugin, createEntityIdBuffer } from "../../standard/compute";
|
|
4
12
|
import {
|
|
5
13
|
Render,
|
|
6
14
|
RenderPlugin,
|
|
7
|
-
DEPTH_FORMAT,
|
|
8
15
|
Pass,
|
|
9
16
|
registerDraw,
|
|
10
17
|
type Draw,
|
|
11
18
|
type SharedPassContext,
|
|
12
19
|
} from "../../standard/render";
|
|
20
|
+
import { DEPTH_FORMAT } from "../../standard/render/scene";
|
|
21
|
+
import { SCENE_STRUCT_WGSL } from "../../standard/render/shaders";
|
|
13
22
|
import { Transform } from "../../standard/transforms";
|
|
14
23
|
|
|
15
24
|
export const LineData = {
|
|
16
25
|
data: new Float32Array(MAX_ENTITIES * 12),
|
|
17
26
|
};
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function lineProxy(offset: number): LineProxy {
|
|
22
|
-
const data = LineData.data;
|
|
23
|
-
|
|
24
|
-
function getValue(eid: number): number {
|
|
25
|
-
return data[eid * 12 + offset];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function setValue(eid: number, value: number): void {
|
|
29
|
-
data[eid * 12 + offset] = value;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return new Proxy([] as unknown as LineProxy, {
|
|
33
|
-
get(_, prop) {
|
|
34
|
-
if (prop === "get") return getValue;
|
|
35
|
-
if (prop === "set") return setValue;
|
|
36
|
-
const eid = Number(prop);
|
|
37
|
-
if (Number.isNaN(eid)) return undefined;
|
|
38
|
-
return getValue(eid);
|
|
39
|
-
},
|
|
40
|
-
set(_, prop, value) {
|
|
41
|
-
const eid = Number(prop);
|
|
42
|
-
if (Number.isNaN(eid)) return false;
|
|
43
|
-
setValue(eid, value);
|
|
44
|
-
return true;
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function colorProxy(): LineProxy {
|
|
50
|
-
const data = LineData.data;
|
|
51
|
-
|
|
28
|
+
function packedColorProxy(data: Float32Array, stride: number, offset: number): FieldProxy {
|
|
52
29
|
function getValue(eid: number): number {
|
|
53
|
-
const
|
|
54
|
-
const r = Math.round(data[
|
|
55
|
-
const g = Math.round(data[
|
|
56
|
-
const b = Math.round(data[
|
|
30
|
+
const o = eid * stride + offset;
|
|
31
|
+
const r = Math.round(data[o] * 255);
|
|
32
|
+
const g = Math.round(data[o + 1] * 255);
|
|
33
|
+
const b = Math.round(data[o + 2] * 255);
|
|
57
34
|
return (r << 16) | (g << 8) | b;
|
|
58
35
|
}
|
|
59
36
|
|
|
60
37
|
function setValue(eid: number, value: number): void {
|
|
61
|
-
const
|
|
62
|
-
data[
|
|
63
|
-
data[
|
|
64
|
-
data[
|
|
65
|
-
data[
|
|
38
|
+
const o = eid * stride + offset;
|
|
39
|
+
data[o] = ((value >> 16) & 0xff) / 255;
|
|
40
|
+
data[o + 1] = ((value >> 8) & 0xff) / 255;
|
|
41
|
+
data[o + 2] = (value & 0xff) / 255;
|
|
42
|
+
data[o + 3] = 1;
|
|
66
43
|
}
|
|
67
44
|
|
|
68
|
-
return new Proxy([] as unknown as
|
|
45
|
+
return new Proxy([] as unknown as FieldProxy, {
|
|
69
46
|
get(_, prop) {
|
|
70
47
|
if (prop === "get") return getValue;
|
|
71
48
|
if (prop === "set") return setValue;
|
|
@@ -82,56 +59,30 @@ function colorProxy(): LineProxy {
|
|
|
82
59
|
});
|
|
83
60
|
}
|
|
84
61
|
|
|
85
|
-
|
|
86
|
-
const data = LineData.data;
|
|
87
|
-
|
|
88
|
-
function getValue(eid: number): number {
|
|
89
|
-
return data[eid * 12 + 8 + channelIndex];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function setValue(eid: number, value: number): void {
|
|
93
|
-
data[eid * 12 + 8 + channelIndex] = value;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return new Proxy([] as unknown as LineProxy, {
|
|
97
|
-
get(_, prop) {
|
|
98
|
-
if (prop === "get") return getValue;
|
|
99
|
-
if (prop === "set") return setValue;
|
|
100
|
-
const eid = Number(prop);
|
|
101
|
-
if (Number.isNaN(eid)) return undefined;
|
|
102
|
-
return getValue(eid);
|
|
103
|
-
},
|
|
104
|
-
set(_, prop, value) {
|
|
105
|
-
const eid = Number(prop);
|
|
106
|
-
if (Number.isNaN(eid)) return false;
|
|
107
|
-
setValue(eid, value);
|
|
108
|
-
return true;
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
}
|
|
62
|
+
const data = LineData.data;
|
|
112
63
|
|
|
113
64
|
export const Line: {
|
|
114
|
-
offsetX:
|
|
115
|
-
offsetY:
|
|
116
|
-
offsetZ:
|
|
117
|
-
thickness:
|
|
118
|
-
visible:
|
|
119
|
-
opacity:
|
|
120
|
-
color:
|
|
121
|
-
colorR:
|
|
122
|
-
colorG:
|
|
123
|
-
colorB:
|
|
65
|
+
offsetX: FieldProxy;
|
|
66
|
+
offsetY: FieldProxy;
|
|
67
|
+
offsetZ: FieldProxy;
|
|
68
|
+
thickness: FieldProxy;
|
|
69
|
+
visible: FieldProxy;
|
|
70
|
+
opacity: FieldProxy;
|
|
71
|
+
color: FieldProxy;
|
|
72
|
+
colorR: FieldProxy;
|
|
73
|
+
colorG: FieldProxy;
|
|
74
|
+
colorB: FieldProxy;
|
|
124
75
|
} = {
|
|
125
|
-
offsetX:
|
|
126
|
-
offsetY:
|
|
127
|
-
offsetZ:
|
|
128
|
-
thickness:
|
|
129
|
-
visible:
|
|
130
|
-
opacity:
|
|
131
|
-
color:
|
|
132
|
-
colorR:
|
|
133
|
-
colorG:
|
|
134
|
-
colorB:
|
|
76
|
+
offsetX: createFieldProxy(data, 12, 0),
|
|
77
|
+
offsetY: createFieldProxy(data, 12, 1),
|
|
78
|
+
offsetZ: createFieldProxy(data, 12, 2),
|
|
79
|
+
thickness: createFieldProxy(data, 12, 3),
|
|
80
|
+
visible: createFieldProxy(data, 12, 4),
|
|
81
|
+
opacity: createFieldProxy(data, 12, 7),
|
|
82
|
+
color: packedColorProxy(data, 12, 8),
|
|
83
|
+
colorR: createFieldProxy(data, 12, 8),
|
|
84
|
+
colorG: createFieldProxy(data, 12, 9),
|
|
85
|
+
colorB: createFieldProxy(data, 12, 10),
|
|
135
86
|
};
|
|
136
87
|
|
|
137
88
|
setTraits(Line, {
|
|
@@ -144,18 +95,6 @@ setTraits(Line, {
|
|
|
144
95
|
opacity: 1,
|
|
145
96
|
color: 0xffffff,
|
|
146
97
|
}),
|
|
147
|
-
accessors: {
|
|
148
|
-
offsetX: Line.offsetX,
|
|
149
|
-
offsetY: Line.offsetY,
|
|
150
|
-
offsetZ: Line.offsetZ,
|
|
151
|
-
thickness: Line.thickness,
|
|
152
|
-
visible: Line.visible,
|
|
153
|
-
opacity: Line.opacity,
|
|
154
|
-
color: Line.color,
|
|
155
|
-
colorR: Line.colorR,
|
|
156
|
-
colorG: Line.colorG,
|
|
157
|
-
colorB: Line.colorB,
|
|
158
|
-
},
|
|
159
98
|
});
|
|
160
99
|
|
|
161
100
|
export interface LinesConfig {
|
|
@@ -174,16 +113,7 @@ struct VertexOutput {
|
|
|
174
113
|
@location(2) halfWidth: f32,
|
|
175
114
|
}
|
|
176
115
|
|
|
177
|
-
|
|
178
|
-
viewProj: mat4x4<f32>,
|
|
179
|
-
cameraWorld: mat4x4<f32>,
|
|
180
|
-
ambientColor: vec4<f32>,
|
|
181
|
-
sunDirection: vec4<f32>,
|
|
182
|
-
sunColor: vec4<f32>,
|
|
183
|
-
cameraMode: f32,
|
|
184
|
-
cameraSize: f32,
|
|
185
|
-
viewport: vec2<f32>,
|
|
186
|
-
}
|
|
116
|
+
${SCENE_STRUCT_WGSL}
|
|
187
117
|
|
|
188
118
|
struct LineData {
|
|
189
119
|
offset: vec3<f32>,
|
|
@@ -220,8 +150,8 @@ fn vs(@builtin(vertex_index) vid: u32, @builtin(instance_index) iid: u32) -> Ver
|
|
|
220
150
|
let len = length(dir);
|
|
221
151
|
let normDir = select(vec2(1.0, 0.0), dir / len, len > 0.0001);
|
|
222
152
|
|
|
223
|
-
|
|
224
|
-
let halfWidth = line.thickness * 0.5;
|
|
153
|
+
let scale = scene.viewport.y / 1080.0;
|
|
154
|
+
let halfWidth = line.thickness * 0.5 * scale;
|
|
225
155
|
let aaPadding = 1.0;
|
|
226
156
|
let totalHalf = halfWidth + aaPadding;
|
|
227
157
|
let perpNDC = vec2(-normDir.y, normDir.x) * totalHalf * 2.0 / scene.viewport;
|
|
@@ -241,7 +171,6 @@ fn vs(@builtin(vertex_index) vid: u32, @builtin(instance_index) iid: u32) -> Ver
|
|
|
241
171
|
|
|
242
172
|
let depth = mix(startClip.z / startClip.w, endClip.z / endClip.w, t);
|
|
243
173
|
|
|
244
|
-
// edge is -1 to +1 across quad, convert to pixel distance from line center
|
|
245
174
|
let pixelDist = edge * totalHalf;
|
|
246
175
|
|
|
247
176
|
var out: VertexOutput;
|
|
@@ -323,7 +252,7 @@ function createLinesDraw(config: LinesConfig): Draw {
|
|
|
323
252
|
|
|
324
253
|
return {
|
|
325
254
|
id: "lines",
|
|
326
|
-
pass: Pass.
|
|
255
|
+
pass: Pass.Overlay,
|
|
327
256
|
order: 0,
|
|
328
257
|
|
|
329
258
|
execute() {},
|
|
@@ -355,13 +284,13 @@ function createLinesDraw(config: LinesConfig): Draw {
|
|
|
355
284
|
};
|
|
356
285
|
}
|
|
357
286
|
|
|
358
|
-
export interface
|
|
287
|
+
export interface Lines {
|
|
359
288
|
buffer: GPUBuffer;
|
|
360
289
|
entityIds: GPUBuffer;
|
|
361
290
|
count: number;
|
|
362
291
|
}
|
|
363
292
|
|
|
364
|
-
export const Lines = resource<
|
|
293
|
+
export const Lines = resource<Lines>("lines");
|
|
365
294
|
|
|
366
295
|
const entityIdArray = new Uint32Array(MAX_ENTITIES);
|
|
367
296
|
|
|
@@ -400,7 +329,7 @@ export const LinesPlugin: Plugin = {
|
|
|
400
329
|
|
|
401
330
|
const { device } = compute;
|
|
402
331
|
|
|
403
|
-
const linesState:
|
|
332
|
+
const linesState: Lines = {
|
|
404
333
|
buffer: device.createBuffer({
|
|
405
334
|
label: "lines",
|
|
406
335
|
size: MAX_ENTITIES * 12 * 4,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { setTraits } from "../../core/component";
|
|
2
|
-
import { clamp, lookAt, type State, type System, type Plugin
|
|
2
|
+
import { clamp, lookAt, type State, type System, type Plugin } from "../../core";
|
|
3
3
|
import { Transform } from "../../standard/transforms";
|
|
4
|
-
import {
|
|
4
|
+
import { Inputs, InputPlugin, type Mouse } from "../../standard/input";
|
|
5
|
+
import { Camera, CameraMode } from "../../standard/render/camera";
|
|
5
6
|
|
|
6
7
|
const Tau = Math.PI * 2;
|
|
7
8
|
|
|
@@ -23,6 +24,9 @@ export const Orbit = {
|
|
|
23
24
|
maxPitch: [] as number[],
|
|
24
25
|
minDistance: [] as number[],
|
|
25
26
|
maxDistance: [] as number[],
|
|
27
|
+
minSize: [] as number[],
|
|
28
|
+
maxSize: [] as number[],
|
|
29
|
+
targetSize: [] as number[],
|
|
26
30
|
smoothness: [] as number[],
|
|
27
31
|
sensitivity: [] as number[],
|
|
28
32
|
zoomSpeed: [] as number[],
|
|
@@ -42,6 +46,9 @@ setTraits(Orbit, {
|
|
|
42
46
|
maxPitch: Math.PI / 2 - 0.01,
|
|
43
47
|
minDistance: 1,
|
|
44
48
|
maxDistance: 25,
|
|
49
|
+
minSize: 0.5,
|
|
50
|
+
maxSize: 50,
|
|
51
|
+
targetSize: 5,
|
|
45
52
|
smoothness: 0.3,
|
|
46
53
|
sensitivity: 0.005,
|
|
47
54
|
zoomSpeed: 0.025,
|
|
@@ -63,7 +70,7 @@ function angleDiff(from: number, to: number): number {
|
|
|
63
70
|
return diff > Math.PI ? diff - Tau : diff;
|
|
64
71
|
}
|
|
65
72
|
|
|
66
|
-
function isOrbitButton(mouse: Readonly<
|
|
73
|
+
function isOrbitButton(mouse: Readonly<Mouse>, button: number): boolean {
|
|
67
74
|
if (button === OrbitButton.Left) return mouse.left;
|
|
68
75
|
if (button === OrbitButton.Middle) return mouse.middle;
|
|
69
76
|
return mouse.right;
|
|
@@ -73,7 +80,7 @@ export const OrbitSystem: System = {
|
|
|
73
80
|
group: "simulation",
|
|
74
81
|
|
|
75
82
|
update(state: State) {
|
|
76
|
-
const input =
|
|
83
|
+
const input = Inputs.from(state);
|
|
77
84
|
const dt = state.time.deltaTime;
|
|
78
85
|
|
|
79
86
|
for (const eid of state.query([Orbit, Transform])) {
|
|
@@ -81,10 +88,11 @@ export const OrbitSystem: System = {
|
|
|
81
88
|
const zoomSpeed = Orbit.zoomSpeed[eid];
|
|
82
89
|
const minPitch = Orbit.minPitch[eid];
|
|
83
90
|
const maxPitch = Orbit.maxPitch[eid];
|
|
84
|
-
const minDistance = Orbit.minDistance[eid];
|
|
85
|
-
const maxDistance = Orbit.maxDistance[eid];
|
|
86
91
|
const smoothness = Orbit.smoothness[eid];
|
|
87
92
|
|
|
93
|
+
const hasCamera = state.hasComponent(eid, Camera);
|
|
94
|
+
const isOrtho = hasCamera && Camera.mode[eid] === CameraMode.Orthographic;
|
|
95
|
+
|
|
88
96
|
if (input && isOrbitButton(input.mouse, Orbit.button[eid])) {
|
|
89
97
|
Orbit.targetYaw[eid] -= input.mouse.deltaX * sensitivity;
|
|
90
98
|
Orbit.targetPitch[eid] = clamp(
|
|
@@ -94,15 +102,26 @@ export const OrbitSystem: System = {
|
|
|
94
102
|
);
|
|
95
103
|
}
|
|
96
104
|
|
|
97
|
-
if (input && input.mouse.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
if (input && input.mouse.scroll !== 0) {
|
|
106
|
+
if (isOrtho) {
|
|
107
|
+
const currentSize = Orbit.targetSize[eid];
|
|
108
|
+
const sizeScale = Math.max(0.1, currentSize * 0.08);
|
|
109
|
+
const zoomDelta = input.mouse.scroll * zoomSpeed * sizeScale;
|
|
110
|
+
Orbit.targetSize[eid] = clamp(
|
|
111
|
+
currentSize + zoomDelta,
|
|
112
|
+
Orbit.minSize[eid],
|
|
113
|
+
Orbit.maxSize[eid]
|
|
114
|
+
);
|
|
115
|
+
} else {
|
|
116
|
+
const currentDistance = Orbit.targetDistance[eid];
|
|
117
|
+
const distanceScale = Math.max(0.3, currentDistance * 0.08);
|
|
118
|
+
const zoomDelta = input.mouse.scroll * zoomSpeed * distanceScale;
|
|
119
|
+
Orbit.targetDistance[eid] = clamp(
|
|
120
|
+
currentDistance + zoomDelta,
|
|
121
|
+
Orbit.minDistance[eid],
|
|
122
|
+
Orbit.maxDistance[eid]
|
|
123
|
+
);
|
|
124
|
+
}
|
|
106
125
|
}
|
|
107
126
|
|
|
108
127
|
const t = smoothLerp(smoothness, dt);
|
|
@@ -110,6 +129,12 @@ export const OrbitSystem: System = {
|
|
|
110
129
|
Orbit.pitch[eid] += (Orbit.targetPitch[eid] - Orbit.pitch[eid]) * t;
|
|
111
130
|
Orbit.distance[eid] += (Orbit.targetDistance[eid] - Orbit.distance[eid]) * t;
|
|
112
131
|
|
|
132
|
+
if (isOrtho) {
|
|
133
|
+
const currentSize = Camera.size[eid];
|
|
134
|
+
const targetSize = Orbit.targetSize[eid];
|
|
135
|
+
Camera.size[eid] = currentSize + (targetSize - currentSize) * t;
|
|
136
|
+
}
|
|
137
|
+
|
|
113
138
|
const yaw = Orbit.yaw[eid];
|
|
114
139
|
const pitch = Orbit.pitch[eid];
|
|
115
140
|
const distance = Orbit.distance[eid];
|