phoria2 1.0.0 → 1.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/README.md +71 -13
- package/dist/bloom.js +1 -1
- package/dist/charts.js +397 -384
- package/dist/charts.js.map +1 -1
- package/dist/core.js +4451 -3568
- package/dist/core.js.map +1 -1
- package/dist/edit.js +67 -67
- package/dist/edit.js.map +1 -1
- package/dist/explain.js +6 -2
- package/dist/explain.js.map +1 -1
- package/dist/gltf.js +211 -166
- package/dist/gltf.js.map +1 -1
- package/dist/motion.js +26 -26
- package/dist/motion.js.map +1 -1
- package/dist/particles.js +49 -49
- package/dist/particles.js.map +1 -1
- package/dist/passes.js +188 -86
- package/dist/passes.js.map +1 -1
- package/dist/phoria2.js +1 -1
- package/dist/picking.js +8 -13
- package/dist/picking.js.map +1 -1
- package/dist/snapshot.js +1 -1
- package/dist/tooltip.js +3 -3
- package/dist/tooltip.js.map +1 -1
- package/dist/types/OrbitControl.d.ts +6 -2
- package/dist/types/Raycaster.d.ts +10 -0
- package/dist/types/View.d.ts +64 -1
- package/dist/types/charts/Chart.d.ts +7 -0
- package/dist/types/explain.d.ts +3 -0
- package/dist/types/frame.d.ts +7 -0
- package/dist/types/geometry/Geometry.d.ts +14 -2
- package/dist/types/keyboard.d.ts +48 -0
- package/dist/types/labels.d.ts +4 -0
- package/dist/types/material/Material.d.ts +125 -0
- package/dist/types/material/Texture.d.ts +37 -5
- package/dist/types/scene/Node.d.ts +19 -14
- package/dist/types/scene/drawables.d.ts +32 -14
- package/dist/types/scene/lights.d.ts +16 -2
- package/dist/types/shadow.d.ts +2 -1
- package/dist/types/types.d.ts +14 -0
- package/dist/types/value/Color.d.ts +0 -4
- package/dist/types/value/Quat.d.ts +4 -2
- package/dist/types/webgl/WebGLRenderer.d.ts +6 -0
- package/dist/types/webgl/passes.d.ts +37 -13
- package/dist/types/webgl/resources.d.ts +24 -2
- package/dist/types/webgl/shaders.d.ts +4 -2
- package/llms-full.txt +153 -15
- package/package.json +4 -1
- package/schema/scene.schema.json +146 -1
- package/src/OrbitControl.js +7 -3
- package/src/Raycaster.js +58 -0
- package/src/View.js +207 -42
- package/src/charts/Chart.js +20 -2
- package/src/explain.js +6 -2
- package/src/frame.js +29 -9
- package/src/geometry/Geometry.js +24 -4
- package/src/gltf/load.js +50 -6
- package/src/keyboard.js +298 -0
- package/src/labels.js +4 -1
- package/src/material/Material.js +104 -19
- package/src/material/Texture.js +116 -11
- package/src/scene/Node.js +20 -9
- package/src/scene/Scene.js +2 -0
- package/src/scene/cameras.js +4 -1
- package/src/scene/drawables.js +48 -12
- package/src/scene/lights.js +40 -6
- package/src/shadow.js +27 -4
- package/src/types.js +6 -0
- package/src/value/Color.js +21 -0
- package/src/value/Quat.js +15 -6
- package/src/watch.js +25 -1
- package/src/webgl/WebGLRenderer.js +51 -12
- package/src/webgl/passes.js +190 -32
- package/src/webgl/picking.js +0 -1
- package/src/webgl/resources.js +89 -8
- package/src/webgl/shaders.js +350 -48
|
@@ -4,7 +4,7 @@ import type { Geometry } from '../geometry/Geometry.js';
|
|
|
4
4
|
import type { Material, MaterialOptions } from '../material/Material.js';
|
|
5
5
|
import type { GeometryOptions } from '../geometry/Geometry.js';
|
|
6
6
|
import type { NodeOptions } from './Node.js';
|
|
7
|
-
import type { ColorInput, Vec3Input } from '../types.js';
|
|
7
|
+
import type { ColorInput, QuatInput, Vec3Input } from '../types.js';
|
|
8
8
|
export type DrawableOptions = NodeOptions & {
|
|
9
9
|
geometry: Geometry | GeometryOptions;
|
|
10
10
|
material?: Material | MaterialOptions;
|
|
@@ -52,6 +52,11 @@ export type LabelPlacement = {
|
|
|
52
52
|
* the edge and up or down (default null: by its point)
|
|
53
53
|
*/
|
|
54
54
|
edge?: 'left' | 'right' | null;
|
|
55
|
+
/**
|
|
56
|
+
* show the label only when zoomed in this far: at least this many CSS pixels to
|
|
57
|
+
* one world unit, at the label's point - details that appear as you come closer (default 0: always)
|
|
58
|
+
*/
|
|
59
|
+
minScale?: number;
|
|
55
60
|
};
|
|
56
61
|
export type LabelPlace = 'center' | 'above' | 'below' | 'left' | 'right';
|
|
57
62
|
export type InstanceLabels = Omit<LabelPlacement, 'priority'> & {
|
|
@@ -64,7 +69,7 @@ export type InstanceLabels = Omit<LabelPlacement, 'priority'> & {
|
|
|
64
69
|
/** @import { Material, MaterialOptions } from '../material/Material.js' */
|
|
65
70
|
/** @import { GeometryOptions } from '../geometry/Geometry.js' */
|
|
66
71
|
/** @import { NodeOptions } from './Node.js' */
|
|
67
|
-
/** @import { ColorInput, Vec3Input } from '../types.js' */
|
|
72
|
+
/** @import { ColorInput, QuatInput, Vec3Input } from '../types.js' */
|
|
68
73
|
/**
|
|
69
74
|
* @typedef {NodeOptions & {
|
|
70
75
|
* geometry: Geometry | GeometryOptions,
|
|
@@ -95,10 +100,13 @@ export type InstanceLabels = Omit<LabelPlacement, 'priority'> & {
|
|
|
95
100
|
* @property {'left' | 'right' | null} [edge] set the label at the view's left or right edge, level with its
|
|
96
101
|
* point - callouts in a column down the side of a diagram, with leader: true. offset then moves it in from
|
|
97
102
|
* the edge and up or down (default null: by its point)
|
|
103
|
+
* @property {number} [minScale] show the label only when zoomed in this far: at least this many CSS pixels to
|
|
104
|
+
* one world unit, at the label's point - details that appear as you come closer (default 0: always)
|
|
98
105
|
*/
|
|
99
106
|
/** @typedef {'center' | 'above' | 'below' | 'left' | 'right'} LabelPlace */
|
|
100
107
|
/**
|
|
101
|
-
* One label per instance or point, from its row of data
|
|
108
|
+
* One label per instance or point, from its row of data - or a list of these, for several each (a symbol
|
|
109
|
+
* always, its details when zoomed in).
|
|
102
110
|
* @typedef {Omit<LabelPlacement, 'priority'> & {
|
|
103
111
|
* text: (datum: any, index: number) => string | number | null | undefined,
|
|
104
112
|
* priority?: number | ((datum: any, index: number) => number),
|
|
@@ -109,10 +117,12 @@ export type InstanceLabels = Omit<LabelPlacement, 'priority'> & {
|
|
|
109
117
|
* label the point itself.
|
|
110
118
|
*/
|
|
111
119
|
export declare const LABEL_PLACES: LabelPlace[];
|
|
112
|
-
|
|
113
|
-
declare function instanceLabels(owner: string, v: unknown): (InstanceLabels & Required<Omit<LabelPlacement, 'priority'>> & {
|
|
120
|
+
export type CheckedLabels = InstanceLabels & Required<Omit<LabelPlacement, 'priority'>> & {
|
|
114
121
|
priority: number | ((datum: any, index: number) => number);
|
|
115
|
-
}
|
|
122
|
+
};
|
|
123
|
+
/** @typedef {InstanceLabels & Required<Omit<LabelPlacement, 'priority'>> & { priority: number | ((datum: any, index: number) => number) }} CheckedLabels */
|
|
124
|
+
/** @param {string} owner @param {unknown} v @returns {CheckedLabels | CheckedLabels[] | null} */
|
|
125
|
+
declare function instanceLabels(owner: string, v: unknown): CheckedLabels | CheckedLabels[] | null;
|
|
116
126
|
/** Base for nodes with geometry and a material: Mesh, InstancedMesh, Points and Lines. */
|
|
117
127
|
export declare class Drawable extends Node {
|
|
118
128
|
#private;
|
|
@@ -157,7 +167,10 @@ export type InstanceOptions = {
|
|
|
157
167
|
* Euler angles in radians, XYZ order
|
|
158
168
|
*/
|
|
159
169
|
rotation?: Vec3Input | Euler;
|
|
160
|
-
|
|
170
|
+
/**
|
|
171
|
+
* [x, y, z, w] or { x, y, z, w } - as physics engines give them
|
|
172
|
+
*/
|
|
173
|
+
quaternion?: QuatInput;
|
|
161
174
|
scale?: Vec3Input | number;
|
|
162
175
|
/**
|
|
163
176
|
* multiplies the material colour
|
|
@@ -166,7 +179,8 @@ export type InstanceOptions = {
|
|
|
166
179
|
};
|
|
167
180
|
/**
|
|
168
181
|
* Many copies of one geometry and material, drawn together. Set each copy with setInstance().
|
|
169
|
-
* Picking reports which instance was hit.
|
|
182
|
+
* Picking reports which instance was hit. An instance scaled to 0 is hidden - it draws nothing, and
|
|
183
|
+
* framing, culling, shadows and labels leave it out - so a pool of instances can keep spares.
|
|
170
184
|
*/
|
|
171
185
|
export declare class InstancedMesh extends Mesh {
|
|
172
186
|
#private;
|
|
@@ -178,11 +192,11 @@ export declare class InstancedMesh extends Mesh {
|
|
|
178
192
|
instanceMatrices: Float32Array;
|
|
179
193
|
/** Linear rgb per instance, or null until a colour is set. @type {Float32Array | null} */
|
|
180
194
|
instanceColors: Float32Array | null;
|
|
181
|
-
/** A label per instance
|
|
195
|
+
/** A label per instance from its row of data - or a list of them, several per instance. @type {ReturnType<typeof instanceLabels>} */
|
|
182
196
|
labels: ReturnType<typeof instanceLabels>;
|
|
183
197
|
/**
|
|
184
198
|
* @param {DrawableOptions & { count?: number, instances?: InstanceOptions[], instanceMatrices?: ArrayLike<number>,
|
|
185
|
-
* instanceColors?: ArrayLike<number>, labels?: InstanceLabels | null }} options count defaults to the number
|
|
199
|
+
* instanceColors?: ArrayLike<number>, labels?: InstanceLabels | InstanceLabels[] | null }} options count defaults to the number
|
|
186
200
|
* of instances or rows of data; instanceMatrices/instanceColors are raw data, as toJSON() writes
|
|
187
201
|
*/
|
|
188
202
|
constructor(options: DrawableOptions & {
|
|
@@ -190,7 +204,7 @@ export declare class InstancedMesh extends Mesh {
|
|
|
190
204
|
instances?: InstanceOptions[];
|
|
191
205
|
instanceMatrices?: ArrayLike<number>;
|
|
192
206
|
instanceColors?: ArrayLike<number>;
|
|
193
|
-
labels?: InstanceLabels | null;
|
|
207
|
+
labels?: InstanceLabels | InstanceLabels[] | null;
|
|
194
208
|
});
|
|
195
209
|
/**
|
|
196
210
|
* Set an instance's transform and optional colour. Unset transform parts default to identity.
|
|
@@ -222,11 +236,11 @@ export declare class InstancedMesh extends Mesh {
|
|
|
222
236
|
export declare class Points extends Drawable {
|
|
223
237
|
static type: string;
|
|
224
238
|
static get OPTIONS(): string[];
|
|
225
|
-
/** A label per point
|
|
239
|
+
/** A label per point from its row of data - or a list of them, several per point. @type {ReturnType<typeof instanceLabels>} */
|
|
226
240
|
labels: ReturnType<typeof instanceLabels>;
|
|
227
|
-
/** @param {DrawableOptions & { labels?: InstanceLabels | null }} options */
|
|
241
|
+
/** @param {DrawableOptions & { labels?: InstanceLabels | InstanceLabels[] | null }} options */
|
|
228
242
|
constructor(options: DrawableOptions & {
|
|
229
|
-
labels?: InstanceLabels | null;
|
|
243
|
+
labels?: InstanceLabels | InstanceLabels[] | null;
|
|
230
244
|
});
|
|
231
245
|
/** @returns {'points'} */
|
|
232
246
|
get drawMode(): 'points';
|
|
@@ -261,6 +275,8 @@ export declare class Label extends Node {
|
|
|
261
275
|
pointer: string;
|
|
262
276
|
anchor: string;
|
|
263
277
|
zIndex: string;
|
|
278
|
+
minZoom: string;
|
|
279
|
+
lod: string;
|
|
264
280
|
collision: string;
|
|
265
281
|
};
|
|
266
282
|
text: string;
|
|
@@ -280,6 +296,8 @@ export declare class Label extends Node {
|
|
|
280
296
|
leader: boolean;
|
|
281
297
|
/** Set at the view's left or right edge, level with its point, or null for by its point. @type {'left' | 'right' | null} */
|
|
282
298
|
edge: 'left' | 'right' | null;
|
|
299
|
+
/** Shown only when zoomed in this far: CSS pixels to one world unit at its point; 0 for always. */
|
|
300
|
+
minScale: number;
|
|
283
301
|
/** @param {LabelOptions} options */
|
|
284
302
|
constructor(options: LabelOptions);
|
|
285
303
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Color } from '../value/Color.js';
|
|
2
2
|
import { Vec3 } from '../value/Vec3.js';
|
|
3
|
+
import { Box3 } from '../value/Box3.js';
|
|
3
4
|
import { Node } from './Node.js';
|
|
4
5
|
import type { NodeOptions } from './Node.js';
|
|
5
|
-
import type { ColorInput, Vec3Input } from '../types.js';
|
|
6
|
+
import type { Box3Input, ColorInput, Vec3Input } from '../types.js';
|
|
6
7
|
export type LightOptions = NodeOptions & {
|
|
7
8
|
color?: ColorInput;
|
|
8
9
|
intensity?: number;
|
|
@@ -87,13 +88,26 @@ declare class AimedLight extends Light {
|
|
|
87
88
|
}
|
|
88
89
|
/** Parallel light from far away, like the sun. Position only matters for its shadow. */
|
|
89
90
|
export declare class DirectionalLight extends AimedLight {
|
|
91
|
+
#private;
|
|
90
92
|
static type: string;
|
|
91
93
|
static get OPTIONS(): string[];
|
|
92
94
|
castShadow: boolean;
|
|
93
|
-
/** @param {AimedLightOptions & { castShadow?: boolean }} [options] */
|
|
95
|
+
/** @param {AimedLightOptions & { castShadow?: boolean, shadowBounds?: Box3Input | null }} [options] */
|
|
94
96
|
constructor(options?: AimedLightOptions & {
|
|
95
97
|
castShadow?: boolean;
|
|
98
|
+
shadowBounds?: Box3Input | null;
|
|
96
99
|
});
|
|
100
|
+
/**
|
|
101
|
+
* The part of the world, in world units, that has shadows - or null (the default) to follow
|
|
102
|
+
* whatever casts them. The shadow map is fitted to what casts every frame, so one caster flung far
|
|
103
|
+
* off spreads its texels over everything and every shadow blurs; set the area where things happen
|
|
104
|
+
* and its shadows stay sharp. Casters outside it still shadow it, from wherever they stand.
|
|
105
|
+
* Assigning copies.
|
|
106
|
+
* @returns {Box3 | null}
|
|
107
|
+
*/
|
|
108
|
+
get shadowBounds(): Box3 | null;
|
|
109
|
+
/** @param {Box3Input | null} v */
|
|
110
|
+
set shadowBounds(v: Box3Input | null);
|
|
97
111
|
}
|
|
98
112
|
/** Light from a point in all directions, falling off with the square of the distance. */
|
|
99
113
|
export declare class PointLight extends Light {
|
package/dist/types/shadow.d.ts
CHANGED
|
@@ -25,9 +25,10 @@ export type ShadowFit = {
|
|
|
25
25
|
* @param {Box3[]} casters world bounds
|
|
26
26
|
* @param {Box3[]} receivers world bounds
|
|
27
27
|
* @param {number} [size] map size in texels
|
|
28
|
+
* @param {Box3 | null} [area] the light's shadowBounds: the map covers this across, whatever casts
|
|
28
29
|
* @returns {ShadowFit | null}
|
|
29
30
|
*/
|
|
30
|
-
export declare function fitShadow(direction: ArrayLike<number>, casters: Box3[], receivers: Box3[], size?: number): ShadowFit | null;
|
|
31
|
+
export declare function fitShadow(direction: ArrayLike<number>, casters: Box3[], receivers: Box3[], size?: number, area?: Box3 | null): ShadowFit | null;
|
|
31
32
|
/** Spot shadows' map: four tiles of half its size, one a light. */
|
|
32
33
|
export declare const SPOT_ATLAS_SIZE = 2048;
|
|
33
34
|
export declare const SPOT_TILES = 4;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -7,12 +7,26 @@ export type XYZ = {
|
|
|
7
7
|
z: number;
|
|
8
8
|
};
|
|
9
9
|
export type Vec3Input = Vec3Like | XYZ;
|
|
10
|
+
export type XYZW = {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
z: number;
|
|
14
|
+
w: number;
|
|
15
|
+
};
|
|
16
|
+
export type QuatInput = ArrayLike<number> | XYZW;
|
|
17
|
+
export type Box3Input = import('./value/Box3.js').Box3 | {
|
|
18
|
+
min: Vec3Input;
|
|
19
|
+
max: Vec3Input;
|
|
20
|
+
};
|
|
10
21
|
export type ColorInput = string | number | number[] | Float32Array | import('./value/Color.js').Color;
|
|
11
22
|
/** @typedef {Float32Array | number[]} Vec2Like */
|
|
12
23
|
/** @typedef {Float32Array | number[]} Vec3Like */
|
|
13
24
|
/** @typedef {Float32Array | number[]} Vec4Like */
|
|
14
25
|
/** A position or direction as an object literal. @typedef {{ x: number, y: number, z: number }} XYZ */
|
|
15
26
|
/** A vector as accepted on input: [x, y, z], { x, y, z } or a Vec3. @typedef {Vec3Like | XYZ} Vec3Input */
|
|
27
|
+
/** A quaternion as an object literal - as physics engines such as Rapier return them. @typedef {{ x: number, y: number, z: number, w: number }} XYZW */
|
|
28
|
+
/** A rotation quaternion as accepted on input: [x, y, z, w], { x, y, z, w } or a Quat. @typedef {ArrayLike<number> | XYZW} QuatInput */
|
|
29
|
+
/** A box as accepted on input: a Box3, or its lowest and highest corners. @typedef {import('./value/Box3.js').Box3 | { min: Vec3Input, max: Vec3Input }} Box3Input */
|
|
16
30
|
/**
|
|
17
31
|
* A colour as accepted on input, in sRGB: '#ff8800', '#f80', 0xff8800, 'rgb(255 136 0)',
|
|
18
32
|
* 'hsl(32 100% 50%)', a CSS colour name, or [r, g, b] with components 0-1.
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import type { ColorInput } from '../types.js';
|
|
2
|
-
/**
|
|
3
|
-
* An RGB colour. Input is sRGB, as everywhere in phoria2; the components are stored **linear**,
|
|
4
|
-
* ready for lighting maths. `toJSON()` gives sRGB '#rrggbb' back.
|
|
5
|
-
*/
|
|
6
2
|
export declare class Color extends Float32Array {
|
|
7
3
|
#private;
|
|
8
4
|
0: any;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { QuatInput } from '../types.js';
|
|
2
|
+
/** @import { QuatInput } from '../types.js' */
|
|
1
3
|
/**
|
|
2
4
|
* A rotation quaternion [x, y, z, w]: a Float32Array(4) with accessors and chainable methods.
|
|
3
5
|
* A node's quaternion and its Euler `rotation` keep each other in sync through these setters;
|
|
@@ -44,8 +46,8 @@ export declare class Quat extends Float32Array {
|
|
|
44
46
|
*/
|
|
45
47
|
/** @param {number | ArrayLike<number>} x @param {number} [y] @param {number} [z] @param {number} [w] */
|
|
46
48
|
set(array: ArrayLike<number>, offset?: number): void;
|
|
47
|
-
/** @param {
|
|
48
|
-
copy(q:
|
|
49
|
+
/** @param {QuatInput} q [x, y, z, w], or { x, y, z, w } as physics engines give them @param {string} [owner] @returns {this} */
|
|
50
|
+
copy(q: QuatInput, owner?: string): this;
|
|
49
51
|
/** @returns {Quat} */
|
|
50
52
|
clone(): Quat;
|
|
51
53
|
/** @returns {this} */
|
|
@@ -29,6 +29,10 @@ export type WebGLRendererOptions = {
|
|
|
29
29
|
* multisampling (default true; a shared context always has it)
|
|
30
30
|
*/
|
|
31
31
|
antialias?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* soft-edged outlines with round corners (default: as antialias)
|
|
34
|
+
*/
|
|
35
|
+
outlineAntialias?: boolean;
|
|
32
36
|
/**
|
|
33
37
|
* how lit colours are mapped to the screen: 'neutral' keeps colours
|
|
34
38
|
* true (Khronos PBR Neutral, the default), 'aces' is filmic, 'none' clips
|
|
@@ -80,6 +84,8 @@ export declare class WebGLRenderer {
|
|
|
80
84
|
/** @type {ToneMapping} */ toneMapping: ToneMapping;
|
|
81
85
|
exposure: number;
|
|
82
86
|
pixelRatio: number;
|
|
87
|
+
/** Outlines with soft edges and round corners, or hard pixel steps; takes effect on the next frame. */
|
|
88
|
+
outlineAntialias: boolean;
|
|
83
89
|
/** Counts from the last frame and the GPU caches. */
|
|
84
90
|
info: {
|
|
85
91
|
drawCalls: number;
|
|
@@ -24,6 +24,30 @@ export type ShadowMap = {
|
|
|
24
24
|
sampler: string;
|
|
25
25
|
texture: WebGLTexture;
|
|
26
26
|
};
|
|
27
|
+
export type Target = {
|
|
28
|
+
texture: WebGLTexture;
|
|
29
|
+
framebuffer: WebGLFramebuffer;
|
|
30
|
+
};
|
|
31
|
+
export type OutlineTargets = {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
smooth: boolean;
|
|
35
|
+
mask: Target;
|
|
36
|
+
wide: Target;
|
|
37
|
+
coverage: Target | null;
|
|
38
|
+
msaa: {
|
|
39
|
+
framebuffer: WebGLFramebuffer;
|
|
40
|
+
renderbuffers: WebGLRenderbuffer[];
|
|
41
|
+
} | null;
|
|
42
|
+
};
|
|
43
|
+
export type OutlineMask = {
|
|
44
|
+
mask: WebGLTexture;
|
|
45
|
+
wide: WebGLTexture;
|
|
46
|
+
coverage: WebGLTexture | null;
|
|
47
|
+
radius: number;
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
};
|
|
27
51
|
/**
|
|
28
52
|
* @typedef {object} Environment
|
|
29
53
|
* @property {WebGLTexture} source the HDR image, mipmapped
|
|
@@ -38,6 +62,12 @@ export type ShadowMap = {
|
|
|
38
62
|
* a pass that returns one of these.
|
|
39
63
|
* @typedef {{ define: string, uniforms: Record<string, unknown>, sampler: string, texture: WebGLTexture }} ShadowMap
|
|
40
64
|
*/
|
|
65
|
+
/**
|
|
66
|
+
* @typedef {{ texture: WebGLTexture, framebuffer: WebGLFramebuffer }} Target
|
|
67
|
+
* @typedef {{ width: number, height: number, smooth: boolean, mask: Target, wide: Target, coverage: Target | null,
|
|
68
|
+
* msaa: { framebuffer: WebGLFramebuffer, renderbuffers: WebGLRenderbuffer[] } | null }} OutlineTargets
|
|
69
|
+
* @typedef {{ mask: WebGLTexture, wide: WebGLTexture, coverage: WebGLTexture | null, radius: number, width: number, height: number }} OutlineMask
|
|
70
|
+
*/
|
|
41
71
|
export declare class Passes {
|
|
42
72
|
#private;
|
|
43
73
|
gl: WebGL2RenderingContext;
|
|
@@ -88,25 +118,19 @@ export declare class Passes {
|
|
|
88
118
|
* The first half of drawing outlines, before the scene: a mask of the outlined subtrees - each
|
|
89
119
|
* pixel they cover in their colour, with the line's width in alpha - then that mask widened
|
|
90
120
|
* sideways. outlineComposite() widens it up and down and draws the ring left round each mask.
|
|
121
|
+
* Smooth outlines draw the mask multisampled, with how much of each pixel it covers, and measure
|
|
122
|
+
* the ring from the shape's edge; otherwise each pixel is in or out.
|
|
91
123
|
* @param {FrameOutline[]} outlines @param {FrameDescription} frame
|
|
92
124
|
* @param {number} width @param {number} height drawing buffer pixels
|
|
93
125
|
* @param {number} pixelRatio
|
|
94
|
-
* @
|
|
126
|
+
* @param {boolean} smooth antialiased: soft edges and round corners
|
|
127
|
+
* @returns {OutlineMask}
|
|
95
128
|
*/
|
|
96
|
-
outlineMask(outlines: FrameOutline[], frame: FrameDescription, width: number, height: number, pixelRatio: number):
|
|
97
|
-
mask: WebGLTexture;
|
|
98
|
-
wide: WebGLTexture;
|
|
99
|
-
radius: number;
|
|
100
|
-
};
|
|
129
|
+
outlineMask(outlines: FrameOutline[], frame: FrameDescription, width: number, height: number, pixelRatio: number, smooth: boolean): OutlineMask;
|
|
101
130
|
/**
|
|
102
131
|
* Draw the outlines over the finished scene, into whatever is bound: the sideways-widened mask
|
|
103
132
|
* widened up and down too, less the mask itself, so a ring is left round each subtree.
|
|
104
|
-
* @param {
|
|
105
|
-
* @param {number} height drawing buffer pixels
|
|
133
|
+
* @param {OutlineMask} outline
|
|
106
134
|
*/
|
|
107
|
-
outlineComposite(outline:
|
|
108
|
-
mask: WebGLTexture;
|
|
109
|
-
wide: WebGLTexture;
|
|
110
|
-
radius: number;
|
|
111
|
-
}, height: number): void;
|
|
135
|
+
outlineComposite(outline: OutlineMask): void;
|
|
112
136
|
}
|
|
@@ -41,6 +41,26 @@ export type MeshBuffers = {
|
|
|
41
41
|
*/
|
|
42
42
|
layout?: string;
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Per-vertex tangents along the UVs' u, with the way v runs in w (Lengyel's method): smooth where
|
|
46
|
+
* the normals are. Without UVs, around the mesh's up axis.
|
|
47
|
+
* @param {Geometry} g
|
|
48
|
+
* @returns {Float32Array}
|
|
49
|
+
*/
|
|
50
|
+
export declare function tangentsOf(g: Geometry): Float32Array;
|
|
51
|
+
/**
|
|
52
|
+
* A map's UV transform as a 3x3 (column-major): repeat, then rotation about its centre, then offset -
|
|
53
|
+
* glTF's KHR_texture_transform order, turning the way three.js and glTF viewers do. Written into one
|
|
54
|
+
* shared array, so set it as a uniform straight away.
|
|
55
|
+
* @param {{ repeat: number[], offset: number[], rotation: number, center: number[] }} t
|
|
56
|
+
* @returns {Float32Array}
|
|
57
|
+
*/
|
|
58
|
+
export declare function uvMatrix(t: {
|
|
59
|
+
repeat: number[];
|
|
60
|
+
offset: number[];
|
|
61
|
+
rotation: number;
|
|
62
|
+
center: number[];
|
|
63
|
+
}): Float32Array;
|
|
44
64
|
export declare class Resources {
|
|
45
65
|
#private;
|
|
46
66
|
/** @type {WebGL2RenderingContext} */ gl: WebGL2RenderingContext;
|
|
@@ -59,17 +79,19 @@ export declare class Resources {
|
|
|
59
79
|
* @param {Geometry} geometry
|
|
60
80
|
* @param {{ instanceMatrices: Float32Array, instanceColors: Float32Array | null, version: number } | null} instances
|
|
61
81
|
* @param {boolean} withNormals
|
|
82
|
+
* @param {boolean} [withTangents] add tangents, for brushed metal - kept once added
|
|
62
83
|
* @returns {MeshBuffers}
|
|
63
84
|
*/
|
|
64
85
|
mesh(geometry: Geometry, instances: {
|
|
65
86
|
instanceMatrices: Float32Array;
|
|
66
87
|
instanceColors: Float32Array | null;
|
|
67
88
|
version: number;
|
|
68
|
-
} | null, withNormals: boolean): MeshBuffers;
|
|
89
|
+
} | null, withNormals: boolean, withTangents?: boolean): MeshBuffers;
|
|
69
90
|
/**
|
|
70
91
|
* Draw a mesh's triangles - instanced or not, indexed or not - with the program in use, as far as
|
|
71
92
|
* its drawn count goes. Every pass that draws meshes draws them this way.
|
|
72
93
|
* @param {Geometry} geometry @param {{ instanceMatrices: Float32Array, instanceColors: Float32Array | null, version: number, count: number } | null} instances
|
|
94
|
+
* @param {boolean} [withTangents] for brushed metal
|
|
73
95
|
* @returns {number} triangles drawn
|
|
74
96
|
*/
|
|
75
97
|
drawTriangles(geometry: Geometry, instances: {
|
|
@@ -77,7 +99,7 @@ export declare class Resources {
|
|
|
77
99
|
instanceColors: Float32Array | null;
|
|
78
100
|
version: number;
|
|
79
101
|
count: number;
|
|
80
|
-
} | null): number;
|
|
102
|
+
} | null, withTangents?: boolean): number;
|
|
81
103
|
/**
|
|
82
104
|
* Vertex array for Lines: one instance per segment with its two endpoints (and colours),
|
|
83
105
|
* expanded to a screen-space quad in the vertex shader.
|
|
@@ -6,6 +6,8 @@ export declare const ATTRIBUTES: {
|
|
|
6
6
|
color: number;
|
|
7
7
|
instanceMatrix: number;
|
|
8
8
|
instanceColor: number;
|
|
9
|
+
tangent: number;
|
|
10
|
+
uv2: number;
|
|
9
11
|
segmentStart: number;
|
|
10
12
|
segmentEnd: number;
|
|
11
13
|
segmentColorStart: number;
|
|
@@ -14,12 +16,12 @@ export declare const ATTRIBUTES: {
|
|
|
14
16
|
};
|
|
15
17
|
export declare const CLIP = "\n#ifdef CLIP\nuniform vec4 uClipPlane; // world space, unit normal: cut away where dot(n, p) + d > 0\nvoid clipAway(vec3 p) {\n if (dot(uClipPlane.xyz, p) + uClipPlane.w > 0.0) discard;\n}\n#else\nvoid clipAway(vec3 p) {}\n#endif\n";
|
|
16
18
|
export declare const FOG = "\n#ifdef FOG\nuniform vec3 uFogColor; // linear\nuniform vec2 uFogRange; // linear fog: near, far\nuniform float uFogDensity; // exponential fog\nin float vFogDepth;\nvec3 fogged(vec3 c) {\n#ifdef FOG_LINEAR\n float f = clamp((vFogDepth - uFogRange.x) / max(uFogRange.y - uFogRange.x, 1e-4), 0.0, 1.0);\n#else\n float d = uFogDensity * vFogDepth;\n float f = 1.0 - exp(-d * d);\n#endif\n#ifdef FOG_ADD\n return c * (1.0 - f);\n#elif defined(FOG_MULTIPLY)\n // a filter in the fog fades to white, which leaves what is behind it as it was\n return mix(c, vec3(1.0), f);\n#else\n return mix(c, uFogColor, f);\n#endif\n}\n#else\nvec3 fogged(vec3 c) { return c; }\n#endif\n";
|
|
17
|
-
export declare const CLIP_ONLY_FRAGMENT
|
|
19
|
+
export declare const CLIP_ONLY_FRAGMENT: string;
|
|
18
20
|
export declare const COMMON = "\nvec3 srgbToLinear(vec3 c) {\n return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));\n}\nvec3 linearToSrgb(vec3 c) {\n c = clamp(c, 0.0, 1.0);\n return mix(c * 12.92, 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, step(0.0031308, c));\n}\n";
|
|
19
21
|
export declare const EQUIRECT = "\nvec2 equirectUv(vec3 d) {\n return vec2(atan(d.z, d.x) * 0.15915494 + 0.5, acos(clamp(d.y, -1.0, 1.0)) * 0.31830989);\n}\nvec3 equirectDirection(vec2 uv) {\n float phi = (uv.x - 0.5) * 6.28318531, theta = uv.y * 3.14159265;\n return vec3(cos(phi) * sin(theta), cos(theta), sin(phi) * sin(theta));\n}\n";
|
|
20
22
|
export declare const FULLSCREEN_VERTEX = "\nout vec2 vUv;\nvoid main() {\n vec2 p = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));\n vUv = p;\n gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);\n}\n";
|
|
21
23
|
export declare const TONE_MAP = "\nuniform float uExposure;\nuniform int uToneMapping; // 0 none, 1 aces, 2 neutral\n\nvec3 toneMap(vec3 c) {\n c *= uExposure;\n if (uToneMapping == 1) {\n // ACES filmic, Narkowicz's fit\n c = clamp((c * (2.51 * c + 0.03)) / (c * (2.43 * c + 0.59) + 0.14), 0.0, 1.0);\n } else if (uToneMapping == 2) {\n // Khronos PBR Neutral\n float x = min(c.r, min(c.g, c.b));\n float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n c -= offset;\n float peak = max(c.r, max(c.g, c.b));\n if (peak > 0.8) {\n float d = 0.2;\n float newPeak = 1.0 - d * d / (peak + d - 0.8);\n c *= newPeak / peak;\n float g = 1.0 - 1.0 / (0.15 * (peak - newPeak) + 1.0);\n c = mix(c, vec3(newPeak), g);\n }\n }\n return c;\n}\n";
|
|
22
|
-
export declare const MESH_VERTEX = "\nlayout(location = 0) in vec3 position;\nlayout(location = 1) in vec3 normal;\nlayout(location = 2) in vec2 uv;\nlayout(location = 3) in vec3 color;\n#ifdef INSTANCED\nlayout(location = 4) in mat4 instanceMatrix;\nlayout(location = 8) in vec3 instanceColor;\n#endif\n\nuniform mat4 uModel;\nuniform mat3 uNormalMatrix;\nuniform mat4 uViewProjection;\nuniform
|
|
24
|
+
export declare const MESH_VERTEX = "\nlayout(location = 0) in vec3 position;\nlayout(location = 1) in vec3 normal;\nlayout(location = 2) in vec2 uv;\nlayout(location = 3) in vec3 color;\n#ifdef INSTANCED\nlayout(location = 4) in mat4 instanceMatrix;\nlayout(location = 8) in vec3 instanceColor;\n#endif\n#ifdef ANISOTROPY\nlayout(location = 9) in vec4 tangent;\nout vec4 vTangent;\n#endif\n#ifdef UV2\nlayout(location = 10) in vec2 uv2;\nout vec2 vUv2;\n#endif\n\nuniform mat4 uModel;\nuniform mat3 uNormalMatrix;\nuniform mat4 uViewProjection;\nuniform int uHighlightIndex; // -2 none, -1 the whole node, otherwise the instance\n#ifdef FOG\nuniform mat4 uView;\nout float vFogDepth;\n#endif\n\nout vec3 vWorldPosition;\nout vec3 vNormal;\nout vec2 vUv;\nout vec3 vColor;\nflat out float vHighlight;\n#ifdef TRIPLANAR\n// the mesh's own space, so projected maps stay on it as it moves; and how its normals turn into the world\nout vec3 vObjectPosition;\nout vec3 vObjectNormal;\nout mat3 vObjectToWorld;\n#endif\n#ifdef PICK\nflat out uint vPickElement; // which instance, point or segment, for GPU picking\n#endif\n\n\nvec3 srgbToLinear(vec3 c) {\n return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));\n}\nvec3 linearToSrgb(vec3 c) {\n c = clamp(c, 0.0, 1.0);\n return mix(c * 12.92, 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, step(0.0031308, c));\n}\n\n\n// Matrices times vectors only - a matrix times a matrix per vertex is four times the work, and\n// with 100,000 instances the vertex stage is most of the frame.\nvoid main() {\n vColor = vec3(1.0);\n vHighlight = uHighlightIndex == -1 ? 1.0 : 0.0;\n#ifdef INSTANCED\n vec4 local = instanceMatrix * vec4(position, 1.0);\n // the instance's normal matrix as its cofactor: the inverse transpose up to scale, from three\n // cross products, flipped back for mirroring transforms\n mat3 m = mat3(instanceMatrix);\n mat3 instanceNormal = mat3(cross(m[1], m[2]), cross(m[2], m[0]), cross(m[0], m[1])) * sign(dot(m[0], cross(m[1], m[2])));\n vec3 n = instanceNormal * normal;\n vColor *= instanceColor;\n if (gl_InstanceID == uHighlightIndex) vHighlight = 1.0;\n#else\n vec4 local = vec4(position, 1.0);\n vec3 n = normal;\n#endif\n#ifdef VERTEX_COLORS\n vColor *= srgbToLinear(color);\n#endif\n vec4 world = uModel * local;\n vWorldPosition = world.xyz;\n vNormal = uNormalMatrix * n;\n vUv = uv;\n#ifdef UV2\n vUv2 = uv2;\n#endif\n#ifdef ANISOTROPY\n // a direction along the surface, so it turns as the model does\n#ifdef INSTANCED\n vTangent = vec4(mat3(uModel) * (m * tangent.xyz), tangent.w);\n#else\n vTangent = vec4(mat3(uModel) * tangent.xyz, tangent.w);\n#endif\n#endif\n#ifdef TRIPLANAR\n vObjectPosition = position;\n vObjectNormal = normal;\n#ifdef INSTANCED\n vObjectToWorld = uNormalMatrix * instanceNormal;\n#else\n vObjectToWorld = uNormalMatrix;\n#endif\n#endif\n gl_Position = uViewProjection * world;\n#ifdef FOG\n vFogDepth = -(uView * world).z;\n#endif\n#ifdef PICK\n vPickElement = uint(gl_InstanceID);\n#endif\n}\n";
|
|
23
25
|
export declare const POINTS_VERTEX = "\nlayout(location = 0) in vec3 position;\nlayout(location = 3) in vec3 color;\n\nuniform mat4 uModel;\nuniform mat4 uView;\nuniform mat4 uProjection;\nuniform float uSize; // pixels (with the pixel ratio applied), or world units when attenuated\nuniform float uScale; // projection focal term x half the buffer height: world size -> pixels at depth 1\nuniform int uHighlightIndex; // -2 none, -1 every point, otherwise the point\n\nout vec3 vColor;\nflat out float vHighlight;\n#ifdef PICK\nflat out uint vPickElement; // which instance, point or segment, for GPU picking\n#endif\n#ifdef FOG\nout float vFogDepth;\n#endif\n\n\nvec3 srgbToLinear(vec3 c) {\n return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));\n}\nvec3 linearToSrgb(vec3 c) {\n c = clamp(c, 0.0, 1.0);\n return mix(c * 12.92, 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, step(0.0031308, c));\n}\n\n\nvoid main() {\n vec4 viewPosition = uView * (uModel * vec4(position, 1.0));\n gl_Position = uProjection * viewPosition;\n#ifdef FOG\n vFogDepth = -viewPosition.z;\n#endif\n#ifdef SIZE_ATTENUATION\n // perspective shrinks with distance; an orthographic projection (w row 0, 0, 0, 1) doesn't\n float depth = uProjection[3][3] == 1.0 ? 1.0 : max(-viewPosition.z, 1e-4);\n gl_PointSize = uSize * uScale / depth;\n#else\n gl_PointSize = uSize;\n#endif\n vColor = vec3(1.0);\n#ifdef VERTEX_COLORS\n vColor = srgbToLinear(color);\n#endif\n vHighlight = uHighlightIndex == -1 || gl_VertexID == uHighlightIndex ? 1.0 : 0.0;\n#ifdef PICK\n vPickElement = uint(gl_VertexID);\n#endif\n}\n";
|
|
24
26
|
export declare const LINES_VERTEX = "\nlayout(location = 0) in vec3 segmentStart;\nlayout(location = 1) in vec3 segmentEnd;\nlayout(location = 2) in vec3 segmentColorStart;\nlayout(location = 3) in vec3 segmentColorEnd;\nlayout(location = 4) in vec2 corner; // x: 0 at start, 1 at end; y: -1 or 1 across\n\nuniform mat4 uModel;\nuniform mat4 uView;\nuniform mat4 uProjection;\nuniform vec2 uResolution; // drawing buffer size in pixels\nuniform float uWidth; // pixels, already scaled by the pixel ratio\nuniform float uNear;\n\nout vec3 vColor;\n#ifdef PICK\nflat out uint vPickElement; // which instance, point or segment, for GPU picking\n#endif\n#ifdef FOG\nout float vFogDepth;\n#endif\n\n\nvec3 srgbToLinear(vec3 c) {\n return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));\n}\nvec3 linearToSrgb(vec3 c) {\n c = clamp(c, 0.0, 1.0);\n return mix(c * 12.92, 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, step(0.0031308, c));\n}\n\n\nvoid main() {\n vec4 a = uView * (uModel * vec4(segmentStart, 1.0));\n vec4 b = uView * (uModel * vec4(segmentEnd, 1.0));\n // clip the segment to the near plane so lines passing behind the camera stay correct\n float clipZ = -uNear;\n if (a.z > clipZ && b.z > clipZ) {\n gl_Position = vec4(2.0, 2.0, 2.0, 1.0); // wholly behind: off screen\n return;\n }\n if (a.z > clipZ) a = mix(a, b, (clipZ - a.z) / (b.z - a.z));\n if (b.z > clipZ) b = mix(b, a, (clipZ - b.z) / (a.z - b.z));\n\n vec4 ca = uProjection * a;\n vec4 cb = uProjection * b;\n vec2 sa = ca.xy / ca.w * uResolution * 0.5;\n vec2 sb = cb.xy / cb.w * uResolution * 0.5;\n vec2 dir = sb - sa;\n float len = length(dir);\n dir = len > 0.0 ? dir / len : vec2(1.0, 0.0);\n vec2 normal = vec2(-dir.y, dir.x);\n\n vec4 clip = mix(ca, cb, corner.x);\n#ifdef FOG\n vFogDepth = -mix(a.z, b.z, corner.x);\n#endif\n // extend past each end by half the width so joins look continuous\n vec2 offset = normal * corner.y * uWidth * 0.5 + dir * (corner.x * 2.0 - 1.0) * uWidth * 0.5;\n clip.xy += offset / (uResolution * 0.5) * clip.w;\n gl_Position = clip;\n#ifdef PICK\n vPickElement = uint(gl_InstanceID);\n#endif\n\n vColor = vec3(1.0);\n#ifdef VERTEX_COLORS\n vColor = srgbToLinear(mix(segmentColorStart, segmentColorEnd, corner.x));\n#endif\n}\n";
|
|
25
27
|
export type ShaderKind = 'mesh' | 'points' | 'lines';
|