@takram/three-geospatial 0.7.1 → 0.9.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/CHANGELOG.md +41 -0
- package/README.md +1 -1
- package/build/index.cjs +1 -1
- package/build/index.cjs.map +1 -1
- package/build/index.js +580 -598
- package/build/index.js.map +1 -1
- package/build/r3f.cjs +1 -1
- package/build/r3f.js +1 -1
- package/build/shared2.cjs +1 -1
- package/build/shared2.cjs.map +1 -1
- package/build/shared2.js +27 -212
- package/build/shared2.js.map +1 -1
- package/build/shared3.cjs +1 -1
- package/build/shared3.cjs.map +1 -1
- package/build/shared3.js +213 -8
- package/build/shared3.js.map +1 -1
- package/build/webgpu.cjs +6 -1
- package/build/webgpu.cjs.map +1 -1
- package/build/webgpu.js +1111 -768
- package/build/webgpu.js.map +1 -1
- package/package.json +1 -1
- package/src/EllipsoidGeometry.ts +1 -1
- package/src/PointOfView.ts +12 -5
- package/src/STBNLoader.ts +41 -19
- package/src/unrollLoops.ts +1 -1
- package/src/webgpu/CascadedShadowMapsNode.ts +48 -0
- package/src/webgpu/DualMipmapFilterNode.ts +8 -4
- package/src/webgpu/FilterNode.ts +5 -3
- package/src/webgpu/FnLayout.ts +17 -16
- package/src/webgpu/HighpVelocityNode.ts +9 -4
- package/src/webgpu/LensFlareNode.ts +12 -16
- package/src/webgpu/LensGlareNode.ts +28 -32
- package/src/webgpu/LensHaloNode.ts +2 -1
- package/src/webgpu/OutputTexture3DNode.ts +10 -0
- package/src/webgpu/OutputTextureNode.ts +10 -0
- package/src/webgpu/STBNTextureNode.ts +58 -0
- package/src/webgpu/ScreenSpaceShadowNode.ts +685 -0
- package/src/webgpu/SeparableFilterNode.ts +8 -5
- package/src/webgpu/SingleFilterNode.ts +5 -2
- package/src/webgpu/StorageTexture3DNode.ts +30 -0
- package/src/webgpu/TemporalAntialiasNode.ts +178 -137
- package/src/webgpu/accessors.ts +75 -36
- package/src/webgpu/debug.ts +38 -47
- package/src/webgpu/events.ts +18 -0
- package/src/webgpu/index.ts +5 -1
- package/src/webgpu/math.ts +116 -15
- package/src/webgpu/sampling.ts +39 -5
- package/src/webgpu/transformations.ts +71 -44
- package/types/PointOfView.d.ts +1 -1
- package/types/STBNLoader.d.ts +3 -4
- package/types/webgpu/CascadedShadowMapsNode.d.ts +13 -0
- package/types/webgpu/DualMipmapFilterNode.d.ts +1 -2
- package/types/webgpu/FnLayout.d.ts +4 -4
- package/types/webgpu/HighpVelocityNode.d.ts +1 -0
- package/types/webgpu/LensFlareNode.d.ts +2 -3
- package/types/webgpu/LensGlareNode.d.ts +1 -1
- package/types/webgpu/STBNTextureNode.d.ts +9 -0
- package/types/webgpu/ScreenSpaceShadowNode.d.ts +33 -0
- package/types/webgpu/SeparableFilterNode.d.ts +2 -3
- package/types/webgpu/SingleFilterNode.d.ts +1 -2
- package/types/webgpu/StorageTexture3DNode.d.ts +9 -0
- package/types/webgpu/TemporalAntialiasNode.d.ts +9 -10
- package/types/webgpu/accessors.d.ts +9 -8
- package/types/webgpu/debug.d.ts +4 -3
- package/types/webgpu/events.d.ts +3 -0
- package/types/webgpu/index.d.ts +5 -1
- package/types/webgpu/math.d.ts +3 -0
- package/types/webgpu/sampling.d.ts +2 -1
- package/types/webgpu/transformations.d.ts +7 -10
- package/src/webgpu/RTTextureNode.ts +0 -130
- package/types/webgpu/RTTextureNode.d.ts +0 -22
package/src/webgpu/accessors.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { Camera, Vector3 } from 'three'
|
|
2
|
+
import {
|
|
3
|
+
cameraFar as cameraFarTSL,
|
|
4
|
+
cameraNear as cameraNearTSL,
|
|
5
|
+
cameraPosition,
|
|
6
|
+
cameraProjectionMatrix,
|
|
7
|
+
cameraProjectionMatrixInverse,
|
|
8
|
+
cameraViewMatrix,
|
|
9
|
+
cameraWorldMatrix,
|
|
10
|
+
depth,
|
|
11
|
+
Fn,
|
|
12
|
+
reference,
|
|
13
|
+
uniform
|
|
14
|
+
} from 'three/tsl'
|
|
3
15
|
import type { UniformNode } from 'three/webgpu'
|
|
4
16
|
|
|
5
17
|
import type { Node } from './node'
|
|
18
|
+
import { depthToViewZ } from './transformations'
|
|
6
19
|
|
|
7
20
|
let caches: WeakMap<{}, Record<string, {}>> | undefined
|
|
8
21
|
|
|
@@ -23,43 +36,69 @@ function getCache<T extends {}, U extends {}>(
|
|
|
23
36
|
return (cache[name] ??= callback()) as U
|
|
24
37
|
}
|
|
25
38
|
|
|
26
|
-
export const projectionMatrix = (camera
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
export const projectionMatrix = (camera?: Camera | null): Node<'mat4'> =>
|
|
40
|
+
camera != null
|
|
41
|
+
? getCache(camera, 'projectionMatrix', () =>
|
|
42
|
+
reference('projectionMatrix', 'mat4', camera).setName(
|
|
43
|
+
'projectionMatrix'
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
: cameraProjectionMatrix
|
|
30
47
|
|
|
31
|
-
export const viewMatrix = (camera
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
48
|
+
export const viewMatrix = (camera?: Camera | null): Node<'mat4'> =>
|
|
49
|
+
camera != null
|
|
50
|
+
? getCache(camera, 'viewMatrix', () =>
|
|
51
|
+
reference('matrixWorldInverse', 'mat4', camera).setName('viewMatrix')
|
|
52
|
+
)
|
|
53
|
+
: cameraViewMatrix
|
|
35
54
|
|
|
36
|
-
export const inverseProjectionMatrix = (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
41
|
-
|
|
55
|
+
export const inverseProjectionMatrix = (
|
|
56
|
+
camera?: Camera | null
|
|
57
|
+
): Node<'mat4'> =>
|
|
58
|
+
camera != null
|
|
59
|
+
? getCache(camera, 'inverseProjectionMatrix', () =>
|
|
60
|
+
reference('projectionMatrixInverse', 'mat4', camera).setName(
|
|
61
|
+
'inverseProjectionMatrix'
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
: cameraProjectionMatrixInverse
|
|
42
65
|
|
|
43
|
-
export const inverseViewMatrix = (camera
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
export const inverseViewMatrix = (camera?: Camera | null): Node<'mat4'> =>
|
|
67
|
+
camera != null
|
|
68
|
+
? getCache(camera, 'inverseViewMatrix', () =>
|
|
69
|
+
reference('matrixWorld', 'mat4', camera).setName('inverseViewMatrix')
|
|
70
|
+
)
|
|
71
|
+
: cameraWorldMatrix // TODO: Not always
|
|
47
72
|
|
|
48
|
-
export const cameraPositionWorld = (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
73
|
+
export const cameraPositionWorld = (
|
|
74
|
+
camera?: Camera | null
|
|
75
|
+
): UniformNode<Vector3> =>
|
|
76
|
+
camera != null
|
|
77
|
+
? getCache(camera, 'cameraPositionWorld', () =>
|
|
78
|
+
uniform('vec3')
|
|
79
|
+
.setName('cameraPositionWorld')
|
|
80
|
+
.onRenderUpdate((_, { value }) => {
|
|
81
|
+
value.setFromMatrixPosition(camera.matrixWorld)
|
|
82
|
+
})
|
|
83
|
+
)
|
|
84
|
+
: cameraPosition
|
|
56
85
|
|
|
57
|
-
export const cameraNear = (camera
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
86
|
+
export const cameraNear = (camera?: Camera | null): Node<'float'> =>
|
|
87
|
+
camera != null
|
|
88
|
+
? getCache(camera, 'cameraNear', () =>
|
|
89
|
+
reference('near', 'float', camera).setName('cameraNear')
|
|
90
|
+
)
|
|
91
|
+
: cameraNearTSL
|
|
61
92
|
|
|
62
|
-
export const cameraFar = (camera
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
93
|
+
export const cameraFar = (camera?: Camera | null): Node<'float'> =>
|
|
94
|
+
camera != null
|
|
95
|
+
? getCache(camera, 'cameraFar', () =>
|
|
96
|
+
reference('far', 'float', camera).setName('cameraFar')
|
|
97
|
+
)
|
|
98
|
+
: cameraFarTSL
|
|
99
|
+
|
|
100
|
+
export const viewZ = Fn(
|
|
101
|
+
({ camera }): Node<'float'> => depthToViewZ(depth, camera)
|
|
102
|
+
)
|
|
103
|
+
.once()()
|
|
104
|
+
.toVar('viewZ')
|
package/src/webgpu/debug.ts
CHANGED
|
@@ -6,65 +6,56 @@ import { QuadGeometry } from '../QuadGeometry'
|
|
|
6
6
|
|
|
7
7
|
async function debugShader(
|
|
8
8
|
renderer: Renderer,
|
|
9
|
-
|
|
10
|
-
): Promise<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
return { fragmentShader: null, vertexShader: null }
|
|
24
|
-
})
|
|
9
|
+
material: NodeMaterial
|
|
10
|
+
): Promise<{
|
|
11
|
+
vertexShader: string | null
|
|
12
|
+
fragmentShader: string | null
|
|
13
|
+
}> {
|
|
14
|
+
const mesh = new Mesh(new QuadGeometry(), material)
|
|
15
|
+
try {
|
|
16
|
+
return await renderer.debug.getShaderAsync(new Scene(), new Camera(), mesh)
|
|
17
|
+
} catch (error: unknown) {
|
|
18
|
+
console.error(error)
|
|
19
|
+
return { vertexShader: null, fragmentShader: null }
|
|
20
|
+
} finally {
|
|
21
|
+
mesh.geometry.dispose()
|
|
22
|
+
}
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
export function
|
|
25
|
+
export async function debugMaterial(
|
|
28
26
|
renderer: Renderer,
|
|
29
27
|
material: NodeMaterial
|
|
30
|
-
):
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
36
|
-
.finally(() => {
|
|
37
|
-
mesh.geometry.dispose()
|
|
38
|
-
})
|
|
28
|
+
): Promise<string | null> {
|
|
29
|
+
const { vertexShader, fragmentShader } = await debugShader(renderer, material)
|
|
30
|
+
return vertexShader != null && fragmentShader != null
|
|
31
|
+
? `// Vertex shader\n\n${vertexShader}\n// Fragment shader\n\n${fragmentShader}`
|
|
32
|
+
: null
|
|
39
33
|
}
|
|
40
34
|
|
|
41
|
-
export function debugVertexNode(
|
|
35
|
+
export async function debugVertexNode(
|
|
42
36
|
renderer: Renderer,
|
|
43
37
|
material: NodeMaterial
|
|
44
|
-
):
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
): Promise<string | null> {
|
|
39
|
+
return (await debugShader(renderer, material)).vertexShader
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function debugFragmentNode(
|
|
43
|
+
renderer: Renderer,
|
|
44
|
+
material: NodeMaterial
|
|
45
|
+
): Promise<string | null> {
|
|
46
|
+
return (await debugShader(renderer, material)).fragmentShader
|
|
53
47
|
}
|
|
54
48
|
|
|
55
|
-
export function debugNode(
|
|
49
|
+
export async function debugNode(
|
|
50
|
+
renderer: Renderer,
|
|
51
|
+
node: Node
|
|
52
|
+
): Promise<string | null> {
|
|
56
53
|
const material = new NodeMaterial()
|
|
57
54
|
material.vertexNode = vec4(positionGeometry.xy, 0, 1)
|
|
58
|
-
material.fragmentNode = node
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
console.log(result.fragmentShader)
|
|
63
|
-
})
|
|
64
|
-
.finally(() => {
|
|
65
|
-
material.dispose()
|
|
66
|
-
mesh.geometry.dispose()
|
|
67
|
-
})
|
|
55
|
+
material.fragmentNode = node.toConst('debugNode')
|
|
56
|
+
const shader = await debugShader(renderer, material)
|
|
57
|
+
material.dispose()
|
|
58
|
+
return shader.fragmentShader
|
|
68
59
|
}
|
|
69
60
|
|
|
70
61
|
export function hookFunction<
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OnBeforeObjectUpdate, OnObjectUpdate } from 'three/tsl'
|
|
2
|
+
import { NodeUpdateType, type Node, type NodeFrame } from 'three/webgpu'
|
|
3
|
+
|
|
4
|
+
// TODO: File a PR for these:
|
|
5
|
+
|
|
6
|
+
export const OnFrameUpdate = (callback: (frame: NodeFrame) => void): Node => {
|
|
7
|
+
const node = OnObjectUpdate(callback)
|
|
8
|
+
node.updateType = NodeUpdateType.NONE
|
|
9
|
+
return node
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const OnBeforeFrameUpdate = (
|
|
13
|
+
callback: (frame: NodeFrame) => void
|
|
14
|
+
): Node => {
|
|
15
|
+
const node = OnBeforeObjectUpdate(callback)
|
|
16
|
+
node.updateBeforeType = NodeUpdateType.FRAME
|
|
17
|
+
return node
|
|
18
|
+
}
|
package/src/webgpu/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './accessors'
|
|
2
|
+
export * from './CascadedShadowMapsNode'
|
|
2
3
|
export * from './debug'
|
|
3
4
|
export * from './DownsampleThresholdNode'
|
|
5
|
+
export * from './events'
|
|
4
6
|
export * from './FnLayout'
|
|
5
7
|
export * from './FnVar'
|
|
6
8
|
export * from './GaussianBlurNode'
|
|
@@ -14,8 +16,10 @@ export * from './MipmapSurfaceBlurNode'
|
|
|
14
16
|
export * from './node'
|
|
15
17
|
export * from './OutputTexture3DNode'
|
|
16
18
|
export * from './OutputTextureNode'
|
|
17
|
-
export * from './RTTextureNode'
|
|
18
19
|
export * from './sampling'
|
|
20
|
+
export * from './ScreenSpaceShadowNode'
|
|
21
|
+
export * from './STBNTextureNode'
|
|
22
|
+
export * from './StorageTexture3DNode'
|
|
19
23
|
export * from './TemporalAntialiasNode'
|
|
20
24
|
export * from './transformations'
|
|
21
25
|
export * from './utils'
|
package/src/webgpu/math.ts
CHANGED
|
@@ -1,8 +1,110 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
bool,
|
|
3
|
+
bvec2,
|
|
4
|
+
bvec3,
|
|
5
|
+
bvec4,
|
|
6
|
+
dot,
|
|
7
|
+
If,
|
|
8
|
+
overloadingFn,
|
|
9
|
+
sqrt,
|
|
10
|
+
struct,
|
|
11
|
+
uvec2,
|
|
12
|
+
uvec3,
|
|
13
|
+
uvec4,
|
|
14
|
+
vec2
|
|
15
|
+
} from 'three/tsl'
|
|
2
16
|
|
|
17
|
+
import { FnLayout } from './FnLayout'
|
|
3
18
|
import { FnVar } from './FnVar'
|
|
4
19
|
import type { Node } from './node'
|
|
5
20
|
|
|
21
|
+
const bvec2Not = /*#__PURE__*/ FnLayout({
|
|
22
|
+
name: 'bvec2Not',
|
|
23
|
+
type: 'bvec2',
|
|
24
|
+
inputs: [{ name: 'x', type: 'bvec2' }]
|
|
25
|
+
})(([x]) => x.notEqual(bool(true)))
|
|
26
|
+
|
|
27
|
+
const bvec3Not = /*#__PURE__*/ FnLayout({
|
|
28
|
+
name: 'bvec3Not',
|
|
29
|
+
type: 'bvec3',
|
|
30
|
+
inputs: [{ name: 'x', type: 'bvec3' }]
|
|
31
|
+
})(([x]) => x.notEqual(bool(true)))
|
|
32
|
+
|
|
33
|
+
const bvec4Not = /*#__PURE__*/ FnLayout({
|
|
34
|
+
name: 'bvec4Not',
|
|
35
|
+
type: 'bvec4',
|
|
36
|
+
inputs: [{ name: 'x', type: 'bvec4' }]
|
|
37
|
+
})(([x]) => x.notEqual(bool(true)))
|
|
38
|
+
|
|
39
|
+
// WORKAROUND: PR on this https://github.com/mrdoob/three.js/pull/33442
|
|
40
|
+
export const bvecNot = /*#__PURE__*/ overloadingFn([
|
|
41
|
+
bvec2Not,
|
|
42
|
+
bvec3Not,
|
|
43
|
+
bvec4Not
|
|
44
|
+
])
|
|
45
|
+
|
|
46
|
+
const bvec2And = /*#__PURE__*/ FnLayout({
|
|
47
|
+
name: 'bvec2And',
|
|
48
|
+
type: 'bvec2',
|
|
49
|
+
inputs: [
|
|
50
|
+
{ name: 'x', type: 'bvec2' },
|
|
51
|
+
{ name: 'y', type: 'bvec2' }
|
|
52
|
+
]
|
|
53
|
+
})(([x, y]) => bvec2(uvec2(x).mul(uvec2(y))))
|
|
54
|
+
|
|
55
|
+
const bvec3And = /*#__PURE__*/ FnLayout({
|
|
56
|
+
name: 'bvec3And',
|
|
57
|
+
type: 'bvec3',
|
|
58
|
+
inputs: [
|
|
59
|
+
{ name: 'x', type: 'bvec3' },
|
|
60
|
+
{ name: 'y', type: 'bvec3' }
|
|
61
|
+
]
|
|
62
|
+
})(([x, y]) => bvec3(uvec3(x).mul(uvec3(y))))
|
|
63
|
+
|
|
64
|
+
const bvec4And = /*#__PURE__*/ FnLayout({
|
|
65
|
+
name: 'bvec4And',
|
|
66
|
+
type: 'bvec4',
|
|
67
|
+
inputs: [
|
|
68
|
+
{ name: 'x', type: 'bvec4' },
|
|
69
|
+
{ name: 'y', type: 'bvec4' }
|
|
70
|
+
]
|
|
71
|
+
})(([x, y]) => bvec4(uvec4(x).mul(uvec4(y))))
|
|
72
|
+
|
|
73
|
+
export const bvecAnd = /*#__PURE__*/ overloadingFn([
|
|
74
|
+
bvec2And,
|
|
75
|
+
bvec3And,
|
|
76
|
+
bvec4And
|
|
77
|
+
])
|
|
78
|
+
|
|
79
|
+
const bvec2Or = /*#__PURE__*/ FnLayout({
|
|
80
|
+
name: 'bvec2Or',
|
|
81
|
+
type: 'bvec2',
|
|
82
|
+
inputs: [
|
|
83
|
+
{ name: 'x', type: 'bvec2' },
|
|
84
|
+
{ name: 'y', type: 'bvec2' }
|
|
85
|
+
]
|
|
86
|
+
})(([x, y]) => uvec2(x).add(uvec2(y)).notEqual(0))
|
|
87
|
+
|
|
88
|
+
const bvec3Or = /*#__PURE__*/ FnLayout({
|
|
89
|
+
name: 'bvec3Or',
|
|
90
|
+
type: 'bvec3',
|
|
91
|
+
inputs: [
|
|
92
|
+
{ name: 'x', type: 'bvec3' },
|
|
93
|
+
{ name: 'y', type: 'bvec3' }
|
|
94
|
+
]
|
|
95
|
+
})(([x, y]) => uvec3(x).add(uvec3(y)).notEqual(0))
|
|
96
|
+
|
|
97
|
+
const bvec4Or = /*#__PURE__*/ FnLayout({
|
|
98
|
+
name: 'bvec4Or',
|
|
99
|
+
type: 'bvec4',
|
|
100
|
+
inputs: [
|
|
101
|
+
{ name: 'x', type: 'bvec4' },
|
|
102
|
+
{ name: 'y', type: 'bvec4' }
|
|
103
|
+
]
|
|
104
|
+
})(([x, y]) => uvec4(x).add(uvec4(y)).notEqual(0))
|
|
105
|
+
|
|
106
|
+
export const bvecOr = /*#__PURE__*/ overloadingFn([bvec2Or, bvec3Or, bvec4Or])
|
|
107
|
+
|
|
6
108
|
// Reference: https://iquilezles.org/articles/intersectors/
|
|
7
109
|
|
|
8
110
|
export const raySphereIntersection = /*#__PURE__*/ FnVar(
|
|
@@ -15,7 +117,7 @@ export const raySphereIntersection = /*#__PURE__*/ FnVar(
|
|
|
15
117
|
const a = rayOrigin.sub(center)
|
|
16
118
|
const b = dot(rayDirection, a)
|
|
17
119
|
const c = dot(a, a).sub(radius.pow2())
|
|
18
|
-
const discriminant = b.pow2().sub(c).
|
|
120
|
+
const discriminant = b.pow2().sub(c).toConst()
|
|
19
121
|
|
|
20
122
|
const intersection = vec2(-1)
|
|
21
123
|
If(discriminant.greaterThanEqual(0), () => {
|
|
@@ -26,10 +128,10 @@ export const raySphereIntersection = /*#__PURE__*/ FnVar(
|
|
|
26
128
|
}
|
|
27
129
|
)
|
|
28
130
|
|
|
29
|
-
export const raySpheresIntersectionsStruct = /*#__PURE__*/ struct(
|
|
30
|
-
|
|
31
|
-
'
|
|
32
|
-
)
|
|
131
|
+
export const raySpheresIntersectionsStruct = /*#__PURE__*/ struct({
|
|
132
|
+
near: 'vec4',
|
|
133
|
+
far: 'vec4'
|
|
134
|
+
})
|
|
33
135
|
|
|
34
136
|
// Derive ray-sphere intersections with multiple radii at once:
|
|
35
137
|
export const raySpheresIntersections = /*#__PURE__*/ FnVar(
|
|
@@ -42,15 +144,14 @@ export const raySpheresIntersections = /*#__PURE__*/ FnVar(
|
|
|
42
144
|
const a = rayOrigin.sub(center)
|
|
43
145
|
const b = dot(rayDirection, a)
|
|
44
146
|
const c = dot(a, a).sub(radii.pow2())
|
|
45
|
-
const discriminant = b.pow2().sub(c).
|
|
147
|
+
const discriminant = b.pow2().sub(c).toConst()
|
|
46
148
|
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
149
|
+
// Reference: https://github.com/GameTechDev/OutdoorLightScattering/blob/master/fx/Common.fxh#L148
|
|
150
|
+
const mask = vec2(discriminant.greaterThanEqual(0)).toConst()
|
|
151
|
+
const inverseMask = mask.oneMinus().toConst()
|
|
152
|
+
const Q = sqrt(discriminant.max(0)).toConst()
|
|
153
|
+
const near = mask.mul(b.negate().sub(Q)).sub(inverseMask)
|
|
154
|
+
const far = mask.mul(b.negate().add(Q)).sub(inverseMask)
|
|
54
155
|
return raySpheresIntersectionsStruct(near, far)
|
|
55
156
|
}
|
|
56
157
|
)
|
|
@@ -69,7 +170,7 @@ export const rayEllipsoidIntersection = /*#__PURE__*/ FnVar(
|
|
|
69
170
|
const discriminant = b
|
|
70
171
|
.pow2()
|
|
71
172
|
.sub(a.mul(c.sub(1)))
|
|
72
|
-
.
|
|
173
|
+
.toConst()
|
|
73
174
|
|
|
74
175
|
const intersections = vec2(-1)
|
|
75
176
|
If(discriminant.greaterThanEqual(0), () => {
|
package/src/webgpu/sampling.ts
CHANGED
|
@@ -1,16 +1,50 @@
|
|
|
1
|
-
import { add, sub,
|
|
2
|
-
import type { TextureNode } from 'three/webgpu'
|
|
1
|
+
import { add, ivec2, ivec4, sub, uv, vec2, vec4 } from 'three/tsl'
|
|
2
|
+
import type { ConstNode, TextureNode } from 'three/webgpu'
|
|
3
3
|
|
|
4
|
+
import { reinterpretType } from '../types'
|
|
4
5
|
import { FnVar } from './FnVar'
|
|
5
6
|
import type { Node } from './node'
|
|
6
7
|
|
|
8
|
+
const components = ['x', 'y', 'z', 'w'] as const
|
|
9
|
+
|
|
10
|
+
// WORKAROUND: TextureNode doesn't have gather() yet.
|
|
11
|
+
// See: https://www.w3.org/TR/WGSL/#texturegather
|
|
12
|
+
export const textureGather = /*#__PURE__*/ FnVar(
|
|
13
|
+
(
|
|
14
|
+
textureNode: TextureNode,
|
|
15
|
+
uvNode: Node<'vec2'>,
|
|
16
|
+
component = 0
|
|
17
|
+
): Node<'vec4'> => {
|
|
18
|
+
let componentValue
|
|
19
|
+
if (typeof component === 'number') {
|
|
20
|
+
componentValue = component
|
|
21
|
+
} else if ((component as any)?.isConstNode === true) {
|
|
22
|
+
reinterpretType<ConstNode<number>>(component)
|
|
23
|
+
componentValue = component.value
|
|
24
|
+
} else {
|
|
25
|
+
throw new Error('Component must be a constant.')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const size = textureNode.size()
|
|
29
|
+
const coord = ivec2(uvNode.mul(size).sub(0.5).floor()).toConst()
|
|
30
|
+
const i = ivec4(coord, coord.add(1)).toConst()
|
|
31
|
+
const c = components[componentValue] // element() fails for depth textures
|
|
32
|
+
return vec4(
|
|
33
|
+
textureNode.load(i.xw)[c], // min, max
|
|
34
|
+
textureNode.load(i.zw)[c], // max, max
|
|
35
|
+
textureNode.load(i.zy)[c], // max, min
|
|
36
|
+
textureNode.load(i.xy)[c] // min, min
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
7
41
|
// 9-taps version of Catmull-Rom sampling.
|
|
8
42
|
// Reference: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
|
|
9
43
|
export const textureCatmullRom = /*#__PURE__*/ FnVar(
|
|
10
|
-
(textureNode: TextureNode,
|
|
11
|
-
const size = vec2(
|
|
44
|
+
(textureNode: TextureNode, uvNode: Node<'vec2'> = uv()): Node<'vec4'> => {
|
|
45
|
+
const size = vec2(textureNode.size())
|
|
12
46
|
const texelSize = size.reciprocal()
|
|
13
|
-
const position =
|
|
47
|
+
const position = uvNode.mul(size)
|
|
14
48
|
const centerPosition = position.sub(0.5).floor().add(0.5)
|
|
15
49
|
|
|
16
50
|
// Compute the fractional offset from our starting texel to our original
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { Camera } from 'three'
|
|
1
2
|
import {
|
|
3
|
+
cameraFar as cameraFarTSL,
|
|
4
|
+
cameraNear as cameraNearTSL,
|
|
2
5
|
cos,
|
|
3
6
|
int,
|
|
4
7
|
logarithmicDepthToViewZ,
|
|
@@ -14,44 +17,54 @@ import {
|
|
|
14
17
|
viewZToPerspectiveDepth
|
|
15
18
|
} from 'three/tsl'
|
|
16
19
|
|
|
20
|
+
import { cameraFar, cameraNear } from './accessors'
|
|
21
|
+
import { FnLayout } from './FnLayout'
|
|
22
|
+
import { FnVar } from './FnVar'
|
|
17
23
|
import type { Node } from './node'
|
|
18
24
|
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
export const depthToViewZ = /*#__PURE__*/ FnVar(
|
|
26
|
+
(
|
|
27
|
+
depth: Node<'float'>,
|
|
28
|
+
camera?: Camera | null,
|
|
29
|
+
near?: Node<'float'> | null,
|
|
30
|
+
far?: Node<'float'> | null
|
|
31
|
+
) =>
|
|
32
|
+
(builder): Node<'float'> => {
|
|
33
|
+
near ??= cameraNear(camera)
|
|
34
|
+
far ??= cameraFar(camera)
|
|
35
|
+
const perspective = camera?.isPerspectiveCamera === true
|
|
36
|
+
const logarithmic = builder.renderer.logarithmicDepthBuffer
|
|
37
|
+
return logarithmic
|
|
38
|
+
? logarithmicDepthToViewZ(depth, near, far)
|
|
39
|
+
: perspective
|
|
40
|
+
? perspectiveDepthToViewZ(depth, near, far)
|
|
41
|
+
: orthographicDepthToViewZ(depth, near, far)
|
|
42
|
+
}
|
|
43
|
+
)
|
|
36
44
|
|
|
37
45
|
export const logarithmicToPerspectiveDepth = (
|
|
38
46
|
depth: Node<'float'>,
|
|
39
|
-
near
|
|
40
|
-
far
|
|
47
|
+
near?: Node<'float'> | null,
|
|
48
|
+
far?: Node<'float'> | null
|
|
41
49
|
): Node<'float'> => {
|
|
50
|
+
near ??= cameraNearTSL
|
|
51
|
+
far ??= cameraFarTSL
|
|
42
52
|
const viewZ = logarithmicDepthToViewZ(depth, near, far)
|
|
43
53
|
return viewZToPerspectiveDepth(viewZ, near, far)
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
export const perspectiveToLogarithmicDepth = (
|
|
47
57
|
depth: Node<'float'>,
|
|
48
|
-
near
|
|
49
|
-
far
|
|
58
|
+
near?: Node<'float'> | null,
|
|
59
|
+
far?: Node<'float'> | null
|
|
50
60
|
): Node<'float'> => {
|
|
61
|
+
near ??= cameraNearTSL
|
|
62
|
+
far ??= cameraFarTSL
|
|
51
63
|
const viewZ = perspectiveDepthToViewZ(depth, near, far)
|
|
52
64
|
return viewZToLogarithmicDepth(viewZ, near, far)
|
|
53
65
|
}
|
|
54
66
|
|
|
67
|
+
// TODO: Reconsider interface
|
|
55
68
|
export const screenToPositionView = (
|
|
56
69
|
uv: Node<'vec2'>,
|
|
57
70
|
depth: Node<'float'>,
|
|
@@ -68,34 +81,48 @@ export const screenToPositionView = (
|
|
|
68
81
|
|
|
69
82
|
// A fifth-order polynomial approximation of Turbo color map.
|
|
70
83
|
// See: https://observablehq.com/@mbostock/turbo
|
|
71
|
-
const turboCoeffs = [
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
const turboCoeffs: ReadonlyArray<[number, number, number]> = [
|
|
85
|
+
[58.1375, 2.7747, 26.8183],
|
|
86
|
+
[-150.5666, 4.2109, -88.5066],
|
|
87
|
+
[130.5887, -14.0195, 109.0745],
|
|
88
|
+
[-42.3277, 4.8052, -60.1097],
|
|
89
|
+
[4.5974, 2.1856, 12.5925],
|
|
90
|
+
[0.1357, 0.0914, 0.1067]
|
|
78
91
|
]
|
|
79
92
|
|
|
80
|
-
export const turbo = (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
93
|
+
export const turbo = /*#__PURE__*/ FnLayout({
|
|
94
|
+
name: 'turbo',
|
|
95
|
+
type: 'vec3',
|
|
96
|
+
inputs: [{ name: 'x', type: 'float' }]
|
|
97
|
+
})(([x]) => {
|
|
98
|
+
const y = vec3(...turboCoeffs[0]).toVar()
|
|
99
|
+
for (let i = 1; i < turboCoeffs.length; ++i) {
|
|
100
|
+
y.assign(vec3(...turboCoeffs[i]).add(x.mul(y)))
|
|
101
|
+
}
|
|
102
|
+
return y
|
|
103
|
+
})
|
|
85
104
|
|
|
86
|
-
export const depthToColor = (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
export const depthToColor = FnVar(
|
|
106
|
+
(
|
|
107
|
+
depth: Node<'float'>,
|
|
108
|
+
camera?: Camera,
|
|
109
|
+
near?: Node<'float'>,
|
|
110
|
+
far?: Node<'float'>
|
|
111
|
+
): Node<'vec3'> => {
|
|
112
|
+
near ??= cameraNear(camera)
|
|
113
|
+
far ??= cameraFar(camera)
|
|
114
|
+
const viewZ = depthToViewZ(depth, camera, near, far)
|
|
115
|
+
return turbo(viewZToLogarithmicDepth(viewZ, near, far))
|
|
116
|
+
}
|
|
117
|
+
)
|
|
95
118
|
|
|
96
|
-
export const equirectToDirectionWorld = (
|
|
119
|
+
export const equirectToDirectionWorld = /*#__PURE__*/ FnLayout({
|
|
120
|
+
name: 'equirectToDirectionWorld',
|
|
121
|
+
type: 'vec3',
|
|
122
|
+
inputs: [{ name: 'uv', type: 'vec2' }]
|
|
123
|
+
})(([uv]) => {
|
|
97
124
|
const lambda = sub(0.5, uv.x).mul(PI2)
|
|
98
125
|
const phi = sub(uv.y, 0.5).mul(PI)
|
|
99
126
|
const cosPhi = cos(phi)
|
|
100
127
|
return vec3(cosPhi.mul(cos(lambda)), sin(phi), cosPhi.mul(sin(lambda)))
|
|
101
|
-
}
|
|
128
|
+
})
|
package/types/PointOfView.d.ts
CHANGED
|
@@ -15,5 +15,5 @@ export declare class PointOfView {
|
|
|
15
15
|
copy(other: PointOfView): this;
|
|
16
16
|
equals(other: PointOfView): boolean;
|
|
17
17
|
decompose(target: Vector3, eye: Vector3, quaternion: Quaternion, up?: Vector3, ellipsoid?: Ellipsoid): void;
|
|
18
|
-
setFromCamera(camera: Camera, ellipsoid?: Ellipsoid): this | undefined;
|
|
18
|
+
setFromCamera(camera: Camera, ellipsoid?: Ellipsoid, target?: Vector3): this | undefined;
|
|
19
19
|
}
|
package/types/STBNLoader.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Data3DTexture,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
constructor(manager?: LoadingManager);
|
|
1
|
+
import { Data3DTexture, Loader } from 'three';
|
|
2
|
+
export declare class STBNLoader extends Loader<Data3DTexture> {
|
|
3
|
+
load(url: string, onLoad?: (data: Data3DTexture) => void, onProgress?: (event: ProgressEvent) => void, onError?: (error: unknown) => void): Data3DTexture;
|
|
5
4
|
}
|