@luma.gl/engine 9.0.0-beta.1 → 9.0.0-beta.10
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/animation/key-frames.js +54 -54
- package/dist/animation/timeline.d.ts.map +1 -1
- package/dist/animation/timeline.js +95 -100
- package/dist/animation-loop/animation-loop-template.d.ts +1 -1
- package/dist/animation-loop/animation-loop-template.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop-template.js +19 -5
- package/dist/animation-loop/animation-loop.d.ts +2 -2
- package/dist/animation-loop/animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/animation-loop.js +433 -356
- package/dist/animation-loop/animation-props.d.ts +2 -2
- package/dist/animation-loop/animation-props.d.ts.map +1 -1
- package/dist/animation-loop/animation-props.js +0 -1
- package/dist/animation-loop/make-animation-loop.d.ts +2 -2
- package/dist/animation-loop/make-animation-loop.d.ts.map +1 -1
- package/dist/animation-loop/make-animation-loop.js +28 -24
- package/dist/computation.d.ts +95 -0
- package/dist/computation.d.ts.map +1 -0
- package/dist/computation.js +248 -0
- package/dist/debug/copy-texture-to-image.d.ts.map +1 -1
- package/dist/debug/copy-texture-to-image.js +39 -42
- package/dist/debug/debug-framebuffer.d.ts.map +1 -1
- package/dist/debug/debug-framebuffer.js +43 -40
- package/dist/debug/debug-shader-layout.js +24 -25
- package/dist/debug/pixel-data-utils.d.ts.map +1 -1
- package/dist/debug/pixel-data-utils.js +34 -36
- package/dist/dist.dev.js +2538 -3027
- package/dist/dist.min.js +102 -0
- package/dist/geometries/cone-geometry.d.ts +1 -1
- package/dist/geometries/cone-geometry.d.ts.map +1 -1
- package/dist/geometries/cone-geometry.js +11 -17
- package/dist/geometries/cube-geometry.d.ts +1 -1
- package/dist/geometries/cube-geometry.d.ts.map +1 -1
- package/dist/geometries/cube-geometry.js +190 -61
- package/dist/geometries/cylinder-geometry.d.ts +1 -1
- package/dist/geometries/cylinder-geometry.d.ts.map +1 -1
- package/dist/geometries/cylinder-geometry.js +9 -14
- package/dist/geometries/ico-sphere-geometry.d.ts +1 -1
- package/dist/geometries/ico-sphere-geometry.d.ts.map +1 -1
- package/dist/geometries/ico-sphere-geometry.js +141 -160
- package/dist/geometries/plane-geometry.d.ts +1 -1
- package/dist/geometries/plane-geometry.d.ts.map +1 -1
- package/dist/geometries/plane-geometry.js +92 -110
- package/dist/geometries/sphere-geometry.d.ts +1 -1
- package/dist/geometries/sphere-geometry.d.ts.map +1 -1
- package/dist/geometries/sphere-geometry.js +76 -95
- package/dist/geometries/truncated-cone-geometry.d.ts +1 -1
- package/dist/geometries/truncated-cone-geometry.d.ts.map +1 -1
- package/dist/geometries/truncated-cone-geometry.js +99 -117
- package/dist/geometry/geometry-table.d.ts.map +1 -1
- package/dist/geometry/geometry-table.js +3 -1
- package/dist/geometry/geometry-utils.js +35 -32
- package/dist/geometry/geometry.d.ts.map +1 -1
- package/dist/geometry/geometry.js +80 -71
- package/dist/geometry/gpu-geometry.d.ts +1 -1
- package/dist/geometry/gpu-geometry.d.ts.map +1 -1
- package/dist/geometry/gpu-geometry.js +79 -99
- package/dist/geometry/gpu-table.js +41 -1
- package/dist/index.cjs +725 -409
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +43 -40
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/lib/clip-space.d.ts +2 -2
- package/dist/lib/clip-space.d.ts.map +1 -1
- package/dist/lib/clip-space.js +28 -34
- package/dist/lib/pipeline-factory.d.ts +13 -14
- package/dist/lib/pipeline-factory.d.ts.map +1 -1
- package/dist/lib/pipeline-factory.js +86 -85
- package/dist/lib/shader-factory.d.ts +17 -0
- package/dist/lib/shader-factory.d.ts.map +1 -0
- package/dist/lib/shader-factory.js +46 -0
- package/dist/model/model.d.ts +59 -46
- package/dist/model/model.d.ts.map +1 -1
- package/dist/model/model.js +635 -411
- package/dist/scenegraph/group-node.d.ts +1 -1
- package/dist/scenegraph/group-node.d.ts.map +1 -1
- package/dist/scenegraph/group-node.js +73 -83
- package/dist/scenegraph/model-node.d.ts +3 -3
- package/dist/scenegraph/model-node.d.ts.map +1 -1
- package/dist/scenegraph/model-node.js +31 -24
- package/dist/scenegraph/scenegraph-node.d.ts.map +1 -1
- package/dist/scenegraph/scenegraph-node.js +136 -124
- package/dist/shader-inputs.d.ts.map +1 -1
- package/dist/shader-inputs.js +99 -58
- package/dist/transform/buffer-transform.d.ts +1 -1
- package/dist/transform/buffer-transform.d.ts.map +1 -1
- package/dist/transform/buffer-transform.js +65 -57
- package/dist/transform/texture-transform.d.ts +1 -1
- package/dist/transform/texture-transform.d.ts.map +1 -1
- package/dist/transform/texture-transform.js +109 -114
- package/dist.min.js +3 -271
- package/package.json +10 -9
- package/src/animation/timeline.ts +20 -20
- package/src/animation-loop/animation-loop-template.ts +10 -8
- package/src/animation-loop/animation-loop.ts +20 -10
- package/src/animation-loop/animation-props.ts +1 -1
- package/src/animation-loop/make-animation-loop.ts +17 -8
- package/src/computation.ts +346 -0
- package/src/debug/copy-texture-to-image.ts +9 -11
- package/src/debug/debug-framebuffer.ts +16 -3
- package/src/debug/debug-shader-layout.ts +1 -1
- package/src/debug/pixel-data-utils.ts +3 -6
- package/src/geometries/cube-geometry.ts +17 -13
- package/src/geometries/ico-sphere-geometry.ts +1 -1
- package/src/geometries/plane-geometry.ts +1 -1
- package/src/geometries/sphere-geometry.ts +1 -1
- package/src/geometries/truncated-cone-geometry.ts +2 -1
- package/src/geometry/geometry-table.ts +9 -6
- package/src/geometry/geometry-utils.ts +16 -0
- package/src/geometry/geometry.ts +9 -6
- package/src/geometry/gpu-geometry.ts +18 -11
- package/src/index.ts +4 -1
- package/src/lib/clip-space.ts +16 -19
- package/src/lib/pipeline-factory.ts +71 -64
- package/src/lib/shader-factory.ts +57 -0
- package/src/model/model.ts +255 -146
- package/src/scenegraph/group-node.ts +14 -10
- package/src/scenegraph/model-node.ts +2 -2
- package/src/scenegraph/scenegraph-node.ts +2 -2
- package/src/shader-inputs.ts +19 -12
- package/src/transform/buffer-transform.ts +16 -8
- package/src/transform/texture-transform.ts +14 -15
- package/dist/animation/key-frames.js.map +0 -1
- package/dist/animation/timeline.js.map +0 -1
- package/dist/animation-loop/animation-loop-template.js.map +0 -1
- package/dist/animation-loop/animation-loop.js.map +0 -1
- package/dist/animation-loop/animation-props.js.map +0 -1
- package/dist/animation-loop/make-animation-loop.js.map +0 -1
- package/dist/debug/copy-texture-to-image.js.map +0 -1
- package/dist/debug/debug-framebuffer.js.map +0 -1
- package/dist/debug/debug-shader-layout.js.map +0 -1
- package/dist/debug/pixel-data-utils.js.map +0 -1
- package/dist/geometries/cone-geometry.js.map +0 -1
- package/dist/geometries/cube-geometry.js.map +0 -1
- package/dist/geometries/cylinder-geometry.js.map +0 -1
- package/dist/geometries/ico-sphere-geometry.js.map +0 -1
- package/dist/geometries/plane-geometry.js.map +0 -1
- package/dist/geometries/sphere-geometry.js.map +0 -1
- package/dist/geometries/truncated-cone-geometry.js.map +0 -1
- package/dist/geometry/geometry-table.js.map +0 -1
- package/dist/geometry/geometry-utils.js.map +0 -1
- package/dist/geometry/geometry.js.map +0 -1
- package/dist/geometry/gpu-geometry.js.map +0 -1
- package/dist/geometry/gpu-table.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/clip-space.js.map +0 -1
- package/dist/lib/pipeline-factory.js.map +0 -1
- package/dist/model/model.js.map +0 -1
- package/dist/scenegraph/group-node.js.map +0 -1
- package/dist/scenegraph/model-node.js.map +0 -1
- package/dist/scenegraph/scenegraph-node.js.map +0 -1
- package/dist/shader-inputs.js.map +0 -1
- package/dist/transform/buffer-transform.js.map +0 -1
- package/dist/transform/texture-transform.js.map +0 -1
|
@@ -10,7 +10,21 @@ let ctx: CanvasRenderingContext2D | null = null;
|
|
|
10
10
|
// eslint-disable-next-line
|
|
11
11
|
export function debugFramebuffer(
|
|
12
12
|
fbo: Framebuffer | Texture,
|
|
13
|
-
{
|
|
13
|
+
{
|
|
14
|
+
id,
|
|
15
|
+
minimap,
|
|
16
|
+
opaque,
|
|
17
|
+
top = '0',
|
|
18
|
+
left = '0',
|
|
19
|
+
rgbaScale = 1
|
|
20
|
+
}: {
|
|
21
|
+
id: string;
|
|
22
|
+
minimap?: boolean;
|
|
23
|
+
opaque?: boolean;
|
|
24
|
+
top?: string;
|
|
25
|
+
left?: string;
|
|
26
|
+
rgbaScale?: number;
|
|
27
|
+
}
|
|
14
28
|
) {
|
|
15
29
|
if (!canvas) {
|
|
16
30
|
canvas = document.createElement('canvas');
|
|
@@ -34,7 +48,6 @@ export function debugFramebuffer(
|
|
|
34
48
|
canvas.height = fbo.height / 2;
|
|
35
49
|
canvas.style.width = '400px';
|
|
36
50
|
canvas.style.height = '400px';
|
|
37
|
-
|
|
38
51
|
}
|
|
39
52
|
|
|
40
53
|
// const image = copyTextureToImage(fbo, {targetMaxHeight: 100, targetImage});
|
|
@@ -54,4 +67,4 @@ export function debugFramebuffer(
|
|
|
54
67
|
imageData.data[offset + i + 3] = opaque ? 255 : color[i + 3] * rgbaScale;
|
|
55
68
|
}
|
|
56
69
|
ctx.putImageData(imageData, 0, 0);
|
|
57
|
-
}
|
|
70
|
+
}
|
|
@@ -8,7 +8,7 @@ import type {ShaderLayout} from '@luma.gl/core';
|
|
|
8
8
|
* Extracts a table suitable for `console.table()` from a shader layout to assist in debugging.
|
|
9
9
|
* @param layout shader layout
|
|
10
10
|
* @param name app should provide the most meaningful name, usually the model or pipeline name / id.
|
|
11
|
-
* @returns
|
|
11
|
+
* @returns
|
|
12
12
|
*/
|
|
13
13
|
export function getDebugTableForShaderLayout(
|
|
14
14
|
layout: ShaderLayout,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// luma.gl
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
2
3
|
// Copyright (c) vis.gl contributors
|
|
3
4
|
|
|
4
5
|
import {TypedArray} from '@luma.gl/core';
|
|
@@ -33,11 +34,7 @@ export function flipRows(options: {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
export function scalePixels(options: {
|
|
37
|
-
data: TypedArray;
|
|
38
|
-
width: number;
|
|
39
|
-
height: number;
|
|
40
|
-
}): {
|
|
37
|
+
export function scalePixels(options: {data: TypedArray; width: number; height: number}): {
|
|
41
38
|
data: Uint8Array;
|
|
42
39
|
width: number;
|
|
43
40
|
height: number;
|
|
@@ -11,19 +11,23 @@ export type CubeGeometryProps = {
|
|
|
11
11
|
export class CubeGeometry extends Geometry {
|
|
12
12
|
constructor(props: CubeGeometryProps = {}) {
|
|
13
13
|
const {id = uid('cube-geometry'), indices = true} = props;
|
|
14
|
-
super(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
super(
|
|
15
|
+
indices
|
|
16
|
+
? {
|
|
17
|
+
...props,
|
|
18
|
+
id,
|
|
19
|
+
topology: 'triangle-list',
|
|
20
|
+
indices: {size: 1, value: CUBE_INDICES},
|
|
21
|
+
attributes: {...ATTRIBUTES, ...props.attributes}
|
|
22
|
+
}
|
|
23
|
+
: {
|
|
24
|
+
...props,
|
|
25
|
+
id,
|
|
26
|
+
topology: 'triangle-list',
|
|
27
|
+
indices: undefined,
|
|
28
|
+
attributes: {...NON_INDEXED_ATTRIBUTES, ...props.attributes}
|
|
29
|
+
}
|
|
30
|
+
);
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -36,7 +36,8 @@ export class TruncatedConeGeometry extends Geometry {
|
|
|
36
36
|
POSITION: {size: 3, value: attributes.POSITION},
|
|
37
37
|
NORMAL: {size: 3, value: attributes.NORMAL},
|
|
38
38
|
TEXCOORD_0: {size: 2, value: attributes.TEXCOORD_0},
|
|
39
|
-
...props.attributes
|
|
39
|
+
...props.attributes
|
|
40
|
+
}
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
// luma.gl
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
2
5
|
import type {TypedArray, VertexFormat} from '@luma.gl/core';
|
|
3
6
|
|
|
4
7
|
/** Holds one geometry */
|
|
@@ -6,11 +9,11 @@ export type GeometryTable = {
|
|
|
6
9
|
length: number;
|
|
7
10
|
schema?: Record<string, VertexFormat>;
|
|
8
11
|
attributes: {
|
|
9
|
-
POSITION: TypedArray
|
|
10
|
-
NORMAL: TypedArray
|
|
11
|
-
TEXCOORD_0: TypedArray
|
|
12
|
-
[key: string]: TypedArray
|
|
12
|
+
POSITION: TypedArray;
|
|
13
|
+
NORMAL: TypedArray;
|
|
14
|
+
TEXCOORD_0: TypedArray;
|
|
15
|
+
[key: string]: TypedArray;
|
|
13
16
|
};
|
|
14
17
|
indices?: Uint16Array | Uint32Array;
|
|
15
18
|
topology?: 'point-list' | 'line-list' | 'line-strip' | 'triangle-list' | 'triangle-strip';
|
|
16
|
-
}
|
|
19
|
+
};
|
|
@@ -29,3 +29,19 @@ export function unpackIndexedGeometry(geometry: any) {
|
|
|
29
29
|
attributes: Object.assign({}, attributes, unpackedAttributes)
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
// export function calculateVertexNormals(positions: Float32Array): Uint8Array {
|
|
34
|
+
// let normals = new Uint8Array(positions.length / 3);
|
|
35
|
+
|
|
36
|
+
// for (let i = 0; i < positions.length; i++) {
|
|
37
|
+
// const vec1 = new Vector3(positions.subarray(i * 3, i + 0, i + 3));
|
|
38
|
+
// const vec2 = new Vector3(positions.subarray(i + 3, i + 6));
|
|
39
|
+
// const vec3 = new Vector3(positions.subarray(i + 6, i + 9));
|
|
40
|
+
|
|
41
|
+
// const normal = new Vector3(vec1).cross(vec2).normalize();
|
|
42
|
+
// normals.set(normal[0], i + 4);
|
|
43
|
+
// normals.set(normal[1], i + 4 + 1);
|
|
44
|
+
// normals.set(normal[2], i + 2);
|
|
45
|
+
// }
|
|
46
|
+
// const normal = new Vector3(vec1).cross(vec2).normalize();
|
|
47
|
+
// }
|
package/src/geometry/geometry.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
// luma.gl
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
2
5
|
import type {PrimitiveTopology, TypedArray} from '@luma.gl/core';
|
|
3
6
|
import {uid, assert} from '@luma.gl/core';
|
|
4
7
|
|
|
@@ -98,7 +101,7 @@ export class Geometry {
|
|
|
98
101
|
return this.vertexCount;
|
|
99
102
|
}
|
|
100
103
|
|
|
101
|
-
/**
|
|
104
|
+
/**
|
|
102
105
|
* Return an object with all attributes plus indices added as a field.
|
|
103
106
|
* TODO Geometry types are a mess
|
|
104
107
|
*/
|
|
@@ -118,10 +121,10 @@ export class Geometry {
|
|
|
118
121
|
* type: indices, vertices, uvs
|
|
119
122
|
* size: elements per vertex
|
|
120
123
|
* target: WebGL buffer type (string or constant)
|
|
121
|
-
*
|
|
122
|
-
* @param attributes
|
|
123
|
-
* @param indices
|
|
124
|
-
* @returns
|
|
124
|
+
*
|
|
125
|
+
* @param attributes
|
|
126
|
+
* @param indices
|
|
127
|
+
* @returns
|
|
125
128
|
*/
|
|
126
129
|
_setAttributes(attributes: Record<string, GeometryAttribute>, indices: any): this {
|
|
127
130
|
return this;
|
|
@@ -48,11 +48,10 @@ export class GPUGeometry {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
destroy(): void {
|
|
51
|
-
this.indices
|
|
52
|
-
this.attributes
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.attributes.colors?.destroy();
|
|
51
|
+
this.indices?.destroy();
|
|
52
|
+
for (const attribute of Object.values(this.attributes)) {
|
|
53
|
+
attribute.destroy();
|
|
54
|
+
}
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
getVertexCount(): number {
|
|
@@ -101,7 +100,7 @@ export function getIndexBufferFromGeometry(device: Device, geometry: Geometry):
|
|
|
101
100
|
export function getAttributeBuffersFromGeometry(
|
|
102
101
|
device: Device,
|
|
103
102
|
geometry: Geometry
|
|
104
|
-
): {attributes: Record<string, Buffer
|
|
103
|
+
): {attributes: Record<string, Buffer>; bufferLayout: BufferLayout[]; vertexCount: number} {
|
|
105
104
|
const bufferLayout: BufferLayout[] = [];
|
|
106
105
|
|
|
107
106
|
const attributes: Record<string, Buffer> = {};
|
|
@@ -109,17 +108,25 @@ export function getAttributeBuffersFromGeometry(
|
|
|
109
108
|
let name: string = attributeName;
|
|
110
109
|
// TODO Map some GLTF attribute names (is this still needed?)
|
|
111
110
|
switch (attributeName) {
|
|
112
|
-
case 'POSITION':
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
case '
|
|
111
|
+
case 'POSITION':
|
|
112
|
+
name = 'positions';
|
|
113
|
+
break;
|
|
114
|
+
case 'NORMAL':
|
|
115
|
+
name = 'normals';
|
|
116
|
+
break;
|
|
117
|
+
case 'TEXCOORD_0':
|
|
118
|
+
name = 'texCoords';
|
|
119
|
+
break;
|
|
120
|
+
case 'COLOR_0':
|
|
121
|
+
name = 'colors';
|
|
122
|
+
break;
|
|
116
123
|
}
|
|
117
124
|
attributes[name] = device.createBuffer({data: attribute.value, id: `${attributeName}-buffer`});
|
|
118
125
|
const {value, size, normalized} = attribute;
|
|
119
126
|
bufferLayout.push({name, format: getVertexFormatFromAttribute(value, size, normalized)});
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices)
|
|
129
|
+
const vertexCount = geometry._calculateVertexCount(geometry.attributes, geometry.indices);
|
|
123
130
|
|
|
124
131
|
return {attributes, bufferLayout, vertexCount};
|
|
125
132
|
}
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export type {TextureTransformProps} from './transform/texture-transform';
|
|
|
23
23
|
export {TextureTransform} from './transform/texture-transform';
|
|
24
24
|
|
|
25
25
|
export {PipelineFactory} from './lib/pipeline-factory';
|
|
26
|
+
export {ShaderFactory} from './lib/shader-factory';
|
|
26
27
|
|
|
27
28
|
// Utils
|
|
28
29
|
export {ClipSpace} from './lib/clip-space';
|
|
@@ -34,7 +35,7 @@ export type {ModelNodeProps} from './scenegraph/model-node';
|
|
|
34
35
|
export {ModelNode} from './scenegraph/model-node';
|
|
35
36
|
|
|
36
37
|
// Geometries
|
|
37
|
-
export type {GeometryProps} from './geometry/geometry';
|
|
38
|
+
export type {GeometryProps, GeometryAttribute} from './geometry/geometry';
|
|
38
39
|
export {Geometry} from './geometry/geometry';
|
|
39
40
|
export type {GPUGeometryProps} from './geometry/gpu-geometry';
|
|
40
41
|
export {GPUGeometry} from './geometry/gpu-geometry';
|
|
@@ -58,3 +59,5 @@ export {TruncatedConeGeometry} from './geometries/truncated-cone-geometry';
|
|
|
58
59
|
// EXPERIMENTAL
|
|
59
60
|
export type {ShaderModuleInputs} from './shader-inputs';
|
|
60
61
|
export {ShaderInputs as _ShaderInputs} from './shader-inputs';
|
|
62
|
+
export type {ComputationProps} from './computation';
|
|
63
|
+
export {Computation} from './computation';
|
package/src/lib/clip-space.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
1
|
// ClipSpace
|
|
3
2
|
import {Device, glsl} from '@luma.gl/core';
|
|
4
3
|
import {Model, ModelProps} from '../model/model';
|
|
5
4
|
import {Geometry} from '../geometry/geometry';
|
|
6
5
|
|
|
7
6
|
const CLIPSPACE_VERTEX_SHADER = glsl`\
|
|
7
|
+
#version 300 es
|
|
8
8
|
in vec2 aClipSpacePosition;
|
|
9
9
|
in vec2 aTexCoord;
|
|
10
10
|
in vec2 aCoordinate;
|
|
@@ -28,25 +28,22 @@ const POSITIONS = [-1, -1, 1, -1, -1, 1, 1, 1];
|
|
|
28
28
|
* A flat geometry that covers the "visible area" that the GPU renders.
|
|
29
29
|
*/
|
|
30
30
|
export class ClipSpace extends Model {
|
|
31
|
-
constructor(device: Device, opts
|
|
32
|
-
const TEX_COORDS = POSITIONS.map(
|
|
31
|
+
constructor(device: Device, opts: Omit<ModelProps, 'vs' | 'vertexCount' | 'geometry'>) {
|
|
32
|
+
const TEX_COORDS = POSITIONS.map(coord => (coord === -1 ? 0 : coord));
|
|
33
33
|
|
|
34
|
-
super(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
super(device, {
|
|
35
|
+
...opts,
|
|
36
|
+
vs: CLIPSPACE_VERTEX_SHADER,
|
|
37
|
+
vertexCount: 4,
|
|
38
|
+
geometry: new Geometry({
|
|
39
|
+
topology: 'triangle-strip',
|
|
39
40
|
vertexCount: 4,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
}
|
|
50
|
-
);
|
|
41
|
+
attributes: {
|
|
42
|
+
aClipSpacePosition: {size: 2, value: new Float32Array(POSITIONS)},
|
|
43
|
+
aTexCoord: {size: 2, value: new Float32Array(TEX_COORDS)},
|
|
44
|
+
aCoordinate: {size: 2, value: new Float32Array(TEX_COORDS)}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
});
|
|
51
48
|
}
|
|
52
49
|
}
|
|
@@ -1,33 +1,35 @@
|
|
|
1
|
-
// luma.gl
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {RenderPipelineProps, ComputePipelineProps} from '@luma.gl/core';
|
|
6
|
+
import {Device, RenderPipeline, ComputePipeline} from '@luma.gl/core';
|
|
7
|
+
|
|
8
|
+
export type PipelineFactoryProps = RenderPipelineProps;
|
|
9
|
+
|
|
10
|
+
/**
|
|
13
11
|
* Efficiently creates / caches pipelines
|
|
14
12
|
*/
|
|
15
13
|
export class PipelineFactory {
|
|
16
|
-
static defaultProps: Required<PipelineFactoryProps> = {
|
|
17
|
-
...RenderPipeline.defaultProps,
|
|
18
|
-
vs: undefined!,
|
|
19
|
-
fs: undefined!
|
|
20
|
-
}
|
|
14
|
+
static defaultProps: Required<PipelineFactoryProps> = {...RenderPipeline.defaultProps};
|
|
21
15
|
|
|
22
16
|
readonly device: Device;
|
|
23
17
|
|
|
24
18
|
private _hashCounter: number = 0;
|
|
25
19
|
private readonly _hashes: Record<string, number> = {};
|
|
26
|
-
private readonly
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
private readonly _renderPipelineCache: Record<
|
|
21
|
+
string,
|
|
22
|
+
{pipeline: RenderPipeline; useCount: number}
|
|
23
|
+
> = {};
|
|
24
|
+
private readonly _computePipelineCache: Record<
|
|
25
|
+
string,
|
|
26
|
+
{pipeline: ComputePipeline; useCount: number}
|
|
27
|
+
> = {};
|
|
28
|
+
|
|
29
|
+
/** Get the singleton default pipeline factory for the specified device */
|
|
29
30
|
static getDefaultPipelineFactory(device: Device): PipelineFactory {
|
|
30
|
-
device._lumaData.defaultPipelineFactory =
|
|
31
|
+
device._lumaData.defaultPipelineFactory =
|
|
32
|
+
device._lumaData.defaultPipelineFactory || new PipelineFactory(device);
|
|
31
33
|
return device._lumaData.defaultPipelineFactory as PipelineFactory;
|
|
32
34
|
}
|
|
33
35
|
|
|
@@ -35,83 +37,88 @@ export class PipelineFactory {
|
|
|
35
37
|
this.device = device;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
/** Return a RenderPipeline matching props. Reuses a similar pipeline if already created. */
|
|
41
|
+
createRenderPipeline(props: RenderPipelineProps): RenderPipeline {
|
|
42
|
+
const allProps: Required<RenderPipelineProps> = {...RenderPipeline.defaultProps, ...props};
|
|
40
43
|
|
|
41
|
-
const hash = this._hashRenderPipeline(
|
|
44
|
+
const hash = this._hashRenderPipeline(allProps);
|
|
42
45
|
|
|
43
|
-
if (!this.
|
|
46
|
+
if (!this._renderPipelineCache[hash]) {
|
|
44
47
|
const pipeline = this.device.createRenderPipeline({
|
|
45
|
-
...
|
|
46
|
-
|
|
47
|
-
fs: props.fs ? this.device.createShader({stage: 'fragment', source: props.fs}) : null,
|
|
48
|
+
...allProps,
|
|
49
|
+
id: allProps.id ? `${allProps.id}-cached` : undefined
|
|
48
50
|
});
|
|
49
|
-
|
|
50
51
|
pipeline.hash = hash;
|
|
51
|
-
this.
|
|
52
|
-
this._useCounts[hash] = 0;
|
|
52
|
+
this._renderPipelineCache[hash] = {pipeline, useCount: 0};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
this.
|
|
55
|
+
this._renderPipelineCache[hash].useCount++;
|
|
56
|
+
return this._renderPipelineCache[hash].pipeline;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
createComputePipeline(props: ComputePipelineProps): ComputePipeline {
|
|
60
|
+
const allProps: Required<ComputePipelineProps> = {...ComputePipeline.defaultProps, ...props};
|
|
61
|
+
|
|
62
|
+
const hash = this._hashComputePipeline(allProps);
|
|
63
|
+
|
|
64
|
+
if (!this._computePipelineCache[hash]) {
|
|
65
|
+
const pipeline = this.device.createComputePipeline({
|
|
66
|
+
...allProps,
|
|
67
|
+
id: allProps.id ? `${allProps.id}-cached` : undefined
|
|
68
|
+
});
|
|
69
|
+
pipeline.hash = hash;
|
|
70
|
+
this._computePipelineCache[hash] = {pipeline, useCount: 0};
|
|
71
|
+
}
|
|
56
72
|
|
|
57
|
-
|
|
73
|
+
this._computePipelineCache[hash].useCount++;
|
|
74
|
+
return this._computePipelineCache[hash].pipeline;
|
|
58
75
|
}
|
|
59
76
|
|
|
60
|
-
release(pipeline: RenderPipeline): void {
|
|
77
|
+
release(pipeline: RenderPipeline | ComputePipeline): void {
|
|
61
78
|
const hash = pipeline.hash;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
79
|
+
const cache =
|
|
80
|
+
pipeline instanceof ComputePipeline ? this._computePipelineCache : this._renderPipelineCache;
|
|
81
|
+
cache[hash].useCount--;
|
|
82
|
+
if (cache[hash].useCount === 0) {
|
|
83
|
+
cache[hash].pipeline.destroy();
|
|
84
|
+
delete cache[hash];
|
|
67
85
|
}
|
|
68
86
|
}
|
|
69
87
|
|
|
70
88
|
// PRIVATE
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
throw new Error('fs');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const pipeline = this.device.createRenderPipeline({
|
|
78
|
-
...props,
|
|
79
|
-
vs: this.device.createShader({stage: 'vertex', source: props.vs}),
|
|
80
|
-
fs: props.fs ? this.device.createShader({stage: 'fragment', source: props.fs}) : null,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return pipeline;
|
|
89
|
+
private _hashComputePipeline(props: ComputePipelineProps): string {
|
|
90
|
+
const shaderHash = this._getHash(props.shader.source);
|
|
91
|
+
return `${shaderHash}`;
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
/** Calculate a hash based on all the inputs for a render pipeline */
|
|
87
|
-
_hashRenderPipeline(props:
|
|
88
|
-
const vsHash = this._getHash(props.vs);
|
|
89
|
-
const fsHash = props.fs ? this._getHash(props.fs) : 0;
|
|
95
|
+
private _hashRenderPipeline(props: RenderPipelineProps): string {
|
|
96
|
+
const vsHash = this._getHash(props.vs.source);
|
|
97
|
+
const fsHash = props.fs ? this._getHash(props.fs.source) : 0;
|
|
90
98
|
|
|
91
99
|
// WebGL specific
|
|
92
100
|
// const {varyings = [], bufferMode = {}} = props;
|
|
93
101
|
// const varyingHashes = varyings.map((v) => this._getHash(v));
|
|
94
102
|
const varyingHash = '-'; // `${varyingHashes.join('/')}B${bufferMode}`
|
|
103
|
+
const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
|
|
95
104
|
|
|
96
|
-
switch (this.device.
|
|
97
|
-
case '
|
|
105
|
+
switch (this.device.type) {
|
|
106
|
+
// case 'webgl':
|
|
107
|
+
// WebGL is more dynamic
|
|
108
|
+
// return `${vsHash}/${fsHash}V${varyingHash}BL${bufferLayoutHash}`;
|
|
109
|
+
default:
|
|
98
110
|
// On WebGPU we need to rebuild the pipeline if topology, parameters or bufferLayout change
|
|
99
111
|
const parameterHash = this._getHash(JSON.stringify(props.parameters));
|
|
100
|
-
const bufferLayoutHash = this._getHash(JSON.stringify(props.bufferLayout));
|
|
101
112
|
// TODO - Can json.stringify() generate different strings for equivalent objects if order of params is different?
|
|
102
113
|
// create a deepHash() to deduplicate?
|
|
103
|
-
return `${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}
|
|
104
|
-
default:
|
|
105
|
-
// WebGL is more dynamic
|
|
106
|
-
return `${vsHash}/${fsHash}V${varyingHash}`;
|
|
114
|
+
return `${vsHash}/${fsHash}V${varyingHash}T${props.topology}P${parameterHash}BL${bufferLayoutHash}`;
|
|
107
115
|
}
|
|
108
116
|
}
|
|
109
117
|
|
|
110
|
-
_getHash(key: string): number {
|
|
118
|
+
private _getHash(key: string): number {
|
|
111
119
|
if (this._hashes[key] === undefined) {
|
|
112
120
|
this._hashes[key] = this._hashCounter++;
|
|
113
121
|
}
|
|
114
122
|
return this._hashes[key];
|
|
115
123
|
}
|
|
116
124
|
}
|
|
117
|
-
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {Device, Shader, ShaderProps} from '@luma.gl/core';
|
|
2
|
+
|
|
3
|
+
/** Manages a cached pool of Shaders for reuse. */
|
|
4
|
+
export class ShaderFactory {
|
|
5
|
+
static readonly defaultProps: Required<ShaderProps> = {...Shader.defaultProps};
|
|
6
|
+
|
|
7
|
+
public readonly device: Device;
|
|
8
|
+
|
|
9
|
+
private readonly _cache: Record<string, {shader: Shader; useCount: number}> = {};
|
|
10
|
+
|
|
11
|
+
/** Returns the default ShaderFactory for the given {@link Device}, creating one if necessary. */
|
|
12
|
+
static getDefaultShaderFactory(device: Device): ShaderFactory {
|
|
13
|
+
device._lumaData.defaultShaderFactory ||= new ShaderFactory(device);
|
|
14
|
+
return device._lumaData.defaultShaderFactory as ShaderFactory;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** @internal */
|
|
18
|
+
constructor(device: Device) {
|
|
19
|
+
this.device = device;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Requests a {@link Shader} from the cache, creating a new Shader only if necessary. */
|
|
23
|
+
createShader(props: ShaderProps): Shader {
|
|
24
|
+
const key = this._hashShader(props);
|
|
25
|
+
|
|
26
|
+
let cacheEntry = this._cache[key];
|
|
27
|
+
if (!cacheEntry) {
|
|
28
|
+
const shader = this.device.createShader({
|
|
29
|
+
...props,
|
|
30
|
+
id: props.id ? `${props.id}-cached` : undefined
|
|
31
|
+
});
|
|
32
|
+
this._cache[key] = cacheEntry = {shader, useCount: 0};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
cacheEntry.useCount++;
|
|
36
|
+
return cacheEntry.shader;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Releases a previously-requested {@link Shader}, destroying it if no users remain. */
|
|
40
|
+
release(shader: Shader): void {
|
|
41
|
+
const key = this._hashShader(shader);
|
|
42
|
+
const cacheEntry = this._cache[key];
|
|
43
|
+
if (cacheEntry) {
|
|
44
|
+
cacheEntry.useCount--;
|
|
45
|
+
if (cacheEntry.useCount === 0) {
|
|
46
|
+
delete this._cache[key];
|
|
47
|
+
cacheEntry.shader.destroy();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// PRIVATE
|
|
53
|
+
|
|
54
|
+
private _hashShader(value: Shader | ShaderProps): string {
|
|
55
|
+
return `${value.stage}:${value.source}`;
|
|
56
|
+
}
|
|
57
|
+
}
|