@takram/three-geospatial 0.8.0 → 0.9.1
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 +29 -0
- 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 +1002 -812
- package/build/webgpu.js.map +1 -1
- package/package.json +1 -1
- package/src/PointOfView.ts +12 -5
- package/src/STBNLoader.ts +41 -19
- package/src/webgpu/CascadedShadowMapsNode.ts +48 -0
- package/src/webgpu/DualMipmapFilterNode.ts +8 -4
- package/src/webgpu/FilterNode.ts +3 -2
- package/src/webgpu/FnLayout.ts +17 -16
- package/src/webgpu/HighpVelocityNode.ts +2 -2
- package/src/webgpu/LensFlareNode.ts +1 -1
- package/src/webgpu/LensGlareNode.ts +26 -26
- package/src/webgpu/LensHaloNode.ts +2 -1
- package/src/webgpu/OutputTexture3DNode.ts +10 -1
- package/src/webgpu/OutputTextureNode.ts +10 -1
- package/src/webgpu/STBNTextureNode.ts +72 -0
- package/src/webgpu/ScreenSpaceShadowNode.ts +30 -35
- 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 +50 -31
- package/src/webgpu/accessors.ts +72 -36
- package/src/webgpu/debug.ts +38 -47
- package/src/webgpu/events.ts +18 -0
- package/src/webgpu/index.ts +4 -0
- 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/LensGlareNode.d.ts +1 -1
- package/types/webgpu/STBNTextureNode.d.ts +10 -0
- package/types/webgpu/ScreenSpaceShadowNode.d.ts +2 -4
- 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 +1 -1
- 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 +4 -0
- 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/FnLayout.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ProxiedTuple,
|
|
3
3
|
ShaderCallNodeInternal,
|
|
4
|
-
ShaderNodeFn
|
|
5
|
-
Struct
|
|
4
|
+
ShaderNodeFn
|
|
6
5
|
} from 'three/src/nodes/TSL.js'
|
|
7
6
|
import { Fn } from 'three/tsl'
|
|
8
|
-
import
|
|
7
|
+
import { StructTypeNode, type NodeBuilder } from 'three/webgpu'
|
|
9
8
|
|
|
10
9
|
import type { Node, NodeType } from './node'
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
type FnLayoutType =
|
|
12
|
+
| NodeType
|
|
13
|
+
| (new (...args: any[]) => any)
|
|
14
|
+
| ((...args: any[]) => any)
|
|
15
15
|
|
|
16
16
|
export interface FnLayoutInput<T extends FnLayoutType = FnLayoutType> {
|
|
17
17
|
name: string
|
|
@@ -30,13 +30,11 @@ export interface FnLayout<
|
|
|
30
30
|
|
|
31
31
|
type InferNodeObject<T extends FnLayoutType> = T extends NodeType
|
|
32
32
|
? Node<T>
|
|
33
|
-
: T extends
|
|
34
|
-
?
|
|
35
|
-
: T extends
|
|
36
|
-
?
|
|
37
|
-
:
|
|
38
|
-
? Texture3DNode
|
|
39
|
-
: never
|
|
33
|
+
: T extends new (...args: any[]) => any
|
|
34
|
+
? InstanceType<T>
|
|
35
|
+
: T extends (...args: any[]) => any
|
|
36
|
+
? ReturnType<T>
|
|
37
|
+
: never
|
|
40
38
|
|
|
41
39
|
type InferNodeObjects<Inputs extends readonly FnLayoutInput[]> = {
|
|
42
40
|
[K in keyof Inputs]: Inputs[K] extends FnLayoutInput<infer T>
|
|
@@ -58,10 +56,13 @@ function transformType(type: FnLayoutType): string {
|
|
|
58
56
|
if (typeof type === 'string') {
|
|
59
57
|
return type
|
|
60
58
|
}
|
|
61
|
-
if (type.layout
|
|
62
|
-
|
|
59
|
+
if ('layout' in type && type.layout instanceof StructTypeNode) {
|
|
60
|
+
if (type.layout.name == null) {
|
|
61
|
+
throw new Error('Struct name is required.')
|
|
62
|
+
}
|
|
63
|
+
return type.layout.name
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
+
throw new Error(`Unsupported layout type: ${type}`)
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
export function FnLayout<
|
|
@@ -20,10 +20,10 @@ export class HighpVelocityNode extends TempNode {
|
|
|
20
20
|
|
|
21
21
|
projectionMatrix?: Matrix4 | null
|
|
22
22
|
|
|
23
|
-
private readonly currentProjectionMatrix = uniform(
|
|
23
|
+
private readonly currentProjectionMatrix = uniform('mat4')
|
|
24
24
|
private readonly previousProjectionMatrix = uniform('mat4')
|
|
25
25
|
|
|
26
|
-
private readonly currentModelViewMatrix = uniform(
|
|
26
|
+
private readonly currentModelViewMatrix = uniform('mat4')
|
|
27
27
|
private readonly previousModelViewMatrix = uniform('mat4')
|
|
28
28
|
private readonly objectModelViewMatrices = new WeakMap<Object3D, Matrix4>()
|
|
29
29
|
|
|
@@ -45,7 +45,7 @@ export class LensFlareNode extends TempNode {
|
|
|
45
45
|
this.glareNode = new LensGlareNode()
|
|
46
46
|
|
|
47
47
|
this.featuresNode = rtt(add(this.ghostNode, this.haloNode))
|
|
48
|
-
this.featuresNode.value.name = '
|
|
48
|
+
this.featuresNode.value.name = 'LensFlare_features'
|
|
49
49
|
this.featuresNode.pixelRatio = 0.5
|
|
50
50
|
|
|
51
51
|
// Use the full resolution because the thresholdNode already downsamples the
|
|
@@ -29,9 +29,9 @@ import {
|
|
|
29
29
|
vec4
|
|
30
30
|
} from 'three/tsl'
|
|
31
31
|
import {
|
|
32
|
+
IndirectStorageBufferAttribute,
|
|
32
33
|
MeshBasicNodeMaterial,
|
|
33
34
|
RendererUtils,
|
|
34
|
-
StorageBufferAttribute,
|
|
35
35
|
type ComputeNode,
|
|
36
36
|
type NodeBuilder,
|
|
37
37
|
type NodeFrame,
|
|
@@ -92,7 +92,12 @@ export class LensGlareNode extends FilterNode {
|
|
|
92
92
|
|
|
93
93
|
private computeNode?: ComputeNode
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
// drawIndexedIndirect format:
|
|
96
|
+
// [indexCount, instanceCount, firstIndex, baseVertex, firstInstance]
|
|
97
|
+
private readonly indirectBuffer = new IndirectStorageBufferAttribute(
|
|
98
|
+
new Uint32Array([6, 0, 0, 0, 0]),
|
|
99
|
+
1
|
|
100
|
+
)
|
|
96
101
|
private instanceBuffer = instancedArray(1, instanceStruct)
|
|
97
102
|
|
|
98
103
|
private readonly renderTarget = this.createRenderTarget()
|
|
@@ -106,16 +111,19 @@ export class LensGlareNode extends FilterNode {
|
|
|
106
111
|
private readonly camera = new PerspectiveCamera()
|
|
107
112
|
private rendererState?: RendererUtils.RendererState
|
|
108
113
|
|
|
109
|
-
private readonly inputTexelSize = uniform(
|
|
110
|
-
private readonly outputTexelSize = uniform(
|
|
111
|
-
private readonly geometryRatio = uniform(
|
|
114
|
+
private readonly inputTexelSize = uniform('vec2')
|
|
115
|
+
private readonly outputTexelSize = uniform('vec2')
|
|
116
|
+
private readonly geometryRatio = uniform('vec2')
|
|
112
117
|
|
|
113
118
|
constructor(inputNode?: TextureNode | null) {
|
|
114
119
|
super(inputNode)
|
|
120
|
+
this.material.name = 'LensGlare'
|
|
121
|
+
|
|
115
122
|
this.inputNode = inputNode
|
|
116
123
|
this.resolutionScale = 0.5
|
|
117
124
|
|
|
118
125
|
this.outputTexture = this.renderTarget.texture
|
|
126
|
+
this.mesh.geometry.indirect = this.indirectBuffer
|
|
119
127
|
}
|
|
120
128
|
|
|
121
129
|
override customCacheKey(): number {
|
|
@@ -151,7 +159,7 @@ export class LensGlareNode extends FilterNode {
|
|
|
151
159
|
const { width: inputWidth, height: inputHeight } = inputNode.value
|
|
152
160
|
this.setSize(inputWidth, inputHeight) // Compute node is initialized here.
|
|
153
161
|
|
|
154
|
-
const { computeNode,
|
|
162
|
+
const { computeNode, indirectBuffer, renderTarget } = this
|
|
155
163
|
invariant(computeNode != null)
|
|
156
164
|
|
|
157
165
|
this.inputTexelSize.value.set(1 / inputWidth, 1 / inputHeight)
|
|
@@ -165,24 +173,12 @@ export class LensGlareNode extends FilterNode {
|
|
|
165
173
|
const { width: outputWidth, height: outputHeight } = renderTarget
|
|
166
174
|
this.outputTexelSize.value.set(1 / outputWidth, 1 / outputHeight)
|
|
167
175
|
|
|
168
|
-
// Reset the
|
|
169
|
-
|
|
170
|
-
|
|
176
|
+
// Reset instanceCount in the indirect buffer:
|
|
177
|
+
indirectBuffer.array[1] = 0
|
|
178
|
+
indirectBuffer.needsUpdate = true
|
|
171
179
|
|
|
172
180
|
void renderer.compute(computeNode)
|
|
173
181
|
|
|
174
|
-
renderer
|
|
175
|
-
.getArrayBufferAsync(counterBuffer)
|
|
176
|
-
.then(arrayBuffer => {
|
|
177
|
-
// TODO: This is indeed a couple of frames behind, thus the number of
|
|
178
|
-
// computed instances above and the number of instances to be drawn by
|
|
179
|
-
// the mesh differ.
|
|
180
|
-
this.mesh.count = new Uint32Array(arrayBuffer)[0]
|
|
181
|
-
})
|
|
182
|
-
.catch((error: unknown) => {
|
|
183
|
-
console.error(error)
|
|
184
|
-
})
|
|
185
|
-
|
|
186
182
|
this.rendererState = resetRendererState(renderer, this.rendererState)
|
|
187
183
|
|
|
188
184
|
renderer.setRenderTarget(renderTarget)
|
|
@@ -195,16 +191,16 @@ export class LensGlareNode extends FilterNode {
|
|
|
195
191
|
const {
|
|
196
192
|
spikePairCount,
|
|
197
193
|
inputNode,
|
|
198
|
-
|
|
194
|
+
indirectBuffer,
|
|
199
195
|
instanceBuffer,
|
|
200
196
|
outputTexelSize
|
|
201
197
|
} = this
|
|
202
198
|
invariant(inputNode != null)
|
|
203
199
|
|
|
204
|
-
const
|
|
205
|
-
|
|
200
|
+
const indirectStorage = storage(
|
|
201
|
+
indirectBuffer,
|
|
206
202
|
'uint',
|
|
207
|
-
|
|
203
|
+
indirectBuffer.count
|
|
208
204
|
).toAtomic()
|
|
209
205
|
|
|
210
206
|
this.computeNode = Fn(() => {
|
|
@@ -218,7 +214,11 @@ export class LensGlareNode extends FilterNode {
|
|
|
218
214
|
const inputLuminance = inputColor.a // Alpha channel stores luminance
|
|
219
215
|
|
|
220
216
|
If(inputLuminance.greaterThan(0.1), () => {
|
|
221
|
-
|
|
217
|
+
// The first element is instanceCount in the drawIndexedIndirect buffer.
|
|
218
|
+
const countBefore = atomicAdd(
|
|
219
|
+
indirectStorage.element(1),
|
|
220
|
+
spikePairCount
|
|
221
|
+
)
|
|
222
222
|
for (let i = 0; i < spikePairCount; ++i) {
|
|
223
223
|
const instance = instanceBuffer.element(countBefore.add(i))
|
|
224
224
|
instance.get('color').assign(inputColor.rgb)
|
|
@@ -38,8 +38,9 @@ export class LensHaloNode extends TempNode {
|
|
|
38
38
|
|
|
39
39
|
constructor(inputNode?: TextureNode | null) {
|
|
40
40
|
super('vec3')
|
|
41
|
-
this.inputNode = inputNode
|
|
42
41
|
this.updateBeforeType = NodeUpdateType.FRAME
|
|
42
|
+
|
|
43
|
+
this.inputNode = inputNode
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
override updateBefore({ renderer }: NodeFrame): void {
|
|
@@ -31,7 +31,16 @@ export class OutputTexture3DNode extends Texture3DNode {
|
|
|
31
31
|
|
|
32
32
|
override clone(): this {
|
|
33
33
|
// @ts-expect-error Ignore
|
|
34
|
-
|
|
34
|
+
const copy = new this.constructor(this.owner, this.value)
|
|
35
|
+
copy.uvNode = this.uvNode
|
|
36
|
+
copy.levelNode = this.levelNode
|
|
37
|
+
copy.biasNode = this.biasNode
|
|
38
|
+
copy.sampler = this.sampler
|
|
39
|
+
copy.depthNode = this.depthNode
|
|
40
|
+
copy.compareNode = this.compareNode
|
|
41
|
+
copy.gradNode = this.gradNode
|
|
42
|
+
copy.offsetNode = this.offsetNode
|
|
43
|
+
return copy
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
|
|
@@ -31,7 +31,16 @@ export class OutputTextureNode extends TextureNode {
|
|
|
31
31
|
|
|
32
32
|
override clone(): this {
|
|
33
33
|
// @ts-expect-error Ignore
|
|
34
|
-
|
|
34
|
+
const copy = new this.constructor(this.owner, this.value)
|
|
35
|
+
copy.uvNode = this.uvNode
|
|
36
|
+
copy.levelNode = this.levelNode
|
|
37
|
+
copy.biasNode = this.biasNode
|
|
38
|
+
copy.sampler = this.sampler
|
|
39
|
+
copy.depthNode = this.depthNode
|
|
40
|
+
copy.compareNode = this.compareNode
|
|
41
|
+
copy.gradNode = this.gradNode
|
|
42
|
+
copy.offsetNode = this.offsetNode
|
|
43
|
+
return copy
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { hashString } from 'three/src/nodes/core/NodeUtils.js'
|
|
2
|
+
import { Fn, frameId, nodeImmutable, screenCoordinate, vec3 } from 'three/tsl'
|
|
3
|
+
import {
|
|
4
|
+
Data3DTexture,
|
|
5
|
+
NearestFilter,
|
|
6
|
+
RedFormat,
|
|
7
|
+
RepeatWrapping,
|
|
8
|
+
Texture3DNode,
|
|
9
|
+
type NodeBuilder
|
|
10
|
+
} from 'three/webgpu'
|
|
11
|
+
|
|
12
|
+
import { DEFAULT_STBN_URL } from '../constants'
|
|
13
|
+
import { STBNLoader } from '../STBNLoader'
|
|
14
|
+
|
|
15
|
+
const emptyTexture3D = /*#__PURE__*/ (() => {
|
|
16
|
+
const texture = new Data3DTexture(new Uint8Array(1))
|
|
17
|
+
texture.format = RedFormat
|
|
18
|
+
// BUG: TextureNode doesn't update these when the texture is swapped.
|
|
19
|
+
texture.minFilter = NearestFilter
|
|
20
|
+
texture.magFilter = NearestFilter
|
|
21
|
+
texture.wrapS = RepeatWrapping
|
|
22
|
+
texture.wrapT = RepeatWrapping
|
|
23
|
+
texture.wrapR = RepeatWrapping
|
|
24
|
+
texture.needsUpdate = true
|
|
25
|
+
return texture
|
|
26
|
+
})()
|
|
27
|
+
|
|
28
|
+
export class STBNTextureNode extends Texture3DNode {
|
|
29
|
+
url = DEFAULT_STBN_URL
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
super(emptyTexture3D)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override customCacheKey(): number {
|
|
36
|
+
return hashString(this.url)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override setup(builder: NodeBuilder): unknown {
|
|
40
|
+
new STBNLoader()
|
|
41
|
+
.loadAsync(this.url)
|
|
42
|
+
.then(texture => {
|
|
43
|
+
this.value = texture
|
|
44
|
+
})
|
|
45
|
+
.catch((error: unknown) => {
|
|
46
|
+
console.error(error)
|
|
47
|
+
})
|
|
48
|
+
return super.setup(builder)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override clone(): this {
|
|
52
|
+
// @ts-expect-error Ignore
|
|
53
|
+
const copy = new this.constructor()
|
|
54
|
+
copy.uvNode = this.uvNode
|
|
55
|
+
copy.levelNode = this.levelNode
|
|
56
|
+
copy.biasNode = this.biasNode
|
|
57
|
+
copy.sampler = this.sampler
|
|
58
|
+
copy.depthNode = this.depthNode
|
|
59
|
+
copy.compareNode = this.compareNode
|
|
60
|
+
copy.gradNode = this.gradNode
|
|
61
|
+
copy.offsetNode = this.offsetNode
|
|
62
|
+
return copy
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const stbnTexture = /*#__PURE__*/ nodeImmutable(STBNTextureNode)
|
|
67
|
+
|
|
68
|
+
export const stbn = /*#__PURE__*/ Fn(() => {
|
|
69
|
+
return stbnTexture
|
|
70
|
+
.sample(vec3(screenCoordinate.xy, frameId.mod(64)).div(vec3(128, 128, 64)))
|
|
71
|
+
.r.toConst('stbn')
|
|
72
|
+
}).once()()
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
15
15
|
* License for the specific language governing permissions and limitations under
|
|
16
16
|
* the License.
|
|
17
|
+
*
|
|
18
|
+
* Modified from the original source code.
|
|
17
19
|
*/
|
|
18
20
|
|
|
19
21
|
import {
|
|
@@ -38,7 +40,6 @@ import {
|
|
|
38
40
|
ivec2,
|
|
39
41
|
min,
|
|
40
42
|
mix,
|
|
41
|
-
textureSize,
|
|
42
43
|
textureStore,
|
|
43
44
|
uniform,
|
|
44
45
|
vec2,
|
|
@@ -56,7 +57,6 @@ import {
|
|
|
56
57
|
type NodeFrame,
|
|
57
58
|
type TextureNode
|
|
58
59
|
} from 'three/webgpu'
|
|
59
|
-
import invariant from 'tiny-invariant'
|
|
60
60
|
|
|
61
61
|
import { cameraFar, cameraNear } from './accessors'
|
|
62
62
|
import type { Node } from './node'
|
|
@@ -107,14 +107,12 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
107
107
|
shadowContrast = uniform(4)
|
|
108
108
|
shadowIntensity = uniform(1)
|
|
109
109
|
bilinearThreshold = uniform(0.02)
|
|
110
|
-
nearDepth = uniform(0)
|
|
111
|
-
farDepth = uniform(1)
|
|
112
110
|
|
|
113
111
|
// xy: Screen coordinate
|
|
114
112
|
// z: Normalized Z
|
|
115
113
|
// w: Direction sign
|
|
116
|
-
private readonly lightCoordinate = uniform(
|
|
117
|
-
private readonly dispatchOffset = uniform(
|
|
114
|
+
private readonly lightCoordinate = uniform('vec4')
|
|
115
|
+
private readonly dispatchOffset = uniform('ivec2')
|
|
118
116
|
private readonly dispatchIndex = uniform(0)
|
|
119
117
|
|
|
120
118
|
private readonly dispatches: readonly Dispatch[] = Array.from(
|
|
@@ -124,7 +122,7 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
124
122
|
)
|
|
125
123
|
private dispatchCount = 0
|
|
126
124
|
|
|
127
|
-
private computeNode
|
|
125
|
+
private readonly computeNode: ComputeNode
|
|
128
126
|
|
|
129
127
|
constructor(
|
|
130
128
|
depthNode: TextureNode,
|
|
@@ -132,6 +130,8 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
132
130
|
mainLight: DirectionalLight
|
|
133
131
|
) {
|
|
134
132
|
super('float')
|
|
133
|
+
this.updateBeforeType = NodeUpdateType.FRAME
|
|
134
|
+
|
|
135
135
|
this.depthNode = depthNode
|
|
136
136
|
this.camera = camera
|
|
137
137
|
this.mainLight = mainLight
|
|
@@ -141,12 +141,11 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
141
141
|
texture.minFilter = LinearFilter
|
|
142
142
|
texture.magFilter = LinearFilter
|
|
143
143
|
texture.generateMipmaps = false
|
|
144
|
-
texture.name = '
|
|
144
|
+
texture.name = 'ScreenSpaceShadow'
|
|
145
145
|
|
|
146
146
|
this.outputTexture = texture
|
|
147
147
|
this.textureNode = outputTexture(this, texture)
|
|
148
|
-
|
|
149
|
-
this.updateBeforeType = NodeUpdateType.FRAME
|
|
148
|
+
this.computeNode = this.createComputeNode()
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
override customCacheKey(): number {
|
|
@@ -198,7 +197,6 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
198
197
|
|
|
199
198
|
this.updateDispatchList(lightProjection, size)
|
|
200
199
|
|
|
201
|
-
invariant(this.computeNode != null)
|
|
202
200
|
for (let index = 0; index < this.dispatchCount; ++index) {
|
|
203
201
|
const dispatch = this.dispatches[index]
|
|
204
202
|
this.dispatchOffset.value.set(dispatch.offset.x, dispatch.offset.y)
|
|
@@ -341,7 +339,7 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
341
339
|
}
|
|
342
340
|
|
|
343
341
|
// See bend_sss_gpu.h
|
|
344
|
-
private
|
|
342
|
+
private createComputeNode(): ComputeNode {
|
|
345
343
|
const {
|
|
346
344
|
depthNode,
|
|
347
345
|
camera,
|
|
@@ -353,8 +351,6 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
353
351
|
shadowContrast,
|
|
354
352
|
shadowIntensity,
|
|
355
353
|
bilinearThreshold,
|
|
356
|
-
farDepth,
|
|
357
|
-
nearDepth,
|
|
358
354
|
lightCoordinate,
|
|
359
355
|
dispatchOffset
|
|
360
356
|
} = this
|
|
@@ -442,27 +438,30 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
442
438
|
return { pixelXY, pixelDistance, xyDelta, xAxisMajor }
|
|
443
439
|
}
|
|
444
440
|
|
|
445
|
-
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
441
|
+
return Fn(builder => {
|
|
442
|
+
const [nearDepth, farDepth] = builder.renderer.reversedDepthBuffer
|
|
443
|
+
? [float(1), float(0)]
|
|
444
|
+
: [float(0), float(1)]
|
|
445
|
+
|
|
446
|
+
const loadDepth = (coord: Node<'ivec2'>): Node<'float'> => {
|
|
447
|
+
let depth: Node = depthNode.load(coord)
|
|
448
|
+
if (builder.renderer.logarithmicDepthBuffer) {
|
|
449
|
+
depth = logarithmicToPerspectiveDepth(
|
|
450
450
|
depth,
|
|
451
451
|
cameraNear(camera),
|
|
452
452
|
cameraFar(camera)
|
|
453
453
|
)
|
|
454
|
-
|
|
454
|
+
}
|
|
455
|
+
depth = depth.toConst()
|
|
456
|
+
|
|
457
|
+
// Emulate a point sampler in bend_sss_gpu.h, with Wrap Mode set to
|
|
458
|
+
// Clamp-To-Border-Color, and Border Color set to farDepth.
|
|
459
|
+
return and(
|
|
460
|
+
coord.greaterThanEqual(0).all(),
|
|
461
|
+
coord.lessThan(depthNode.size()).all()
|
|
462
|
+
).select(depth, farDepth)
|
|
455
463
|
}
|
|
456
464
|
|
|
457
|
-
// Emulate a point sampler in bend_sss_gpu.h, with Wrap Mode set to
|
|
458
|
-
// Clamp-To-Border-Color, and Border Color set to farDepth.
|
|
459
|
-
return and(
|
|
460
|
-
coord.greaterThanEqual(0).all(),
|
|
461
|
-
coord.lessThan(textureSize(depthNode)).all()
|
|
462
|
-
).select(depth, farDepth)
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
this.computeNode = Fn(() => {
|
|
466
465
|
const { pixelXY, xyDelta, pixelDistance, xAxisMajor } =
|
|
467
466
|
getWorkgroupExtents()
|
|
468
467
|
|
|
@@ -656,7 +655,7 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
656
655
|
shadowValue.mul(shadowContrast).add(contrastOffset).saturate()
|
|
657
656
|
)
|
|
658
657
|
|
|
659
|
-
const result = float().toVar()
|
|
658
|
+
const result = float(0).toVar()
|
|
660
659
|
|
|
661
660
|
// Take the average of 4 samples, this is useful to reduce aliasing noise
|
|
662
661
|
// in the source depth, especially with long shadows.
|
|
@@ -669,14 +668,10 @@ export class ScreenSpaceShadowNode extends TempNode {
|
|
|
669
668
|
// Asking the GPU to write scattered single-byte pixels isn't great,
|
|
670
669
|
// But thankfully the latency is hidden by all the work we're doing...
|
|
671
670
|
textureStore(outputTexture, writeXY, mix(1, result, shadowIntensity))
|
|
672
|
-
})().
|
|
673
|
-
0, // Determine this later
|
|
674
|
-
[GROUP_SIZE, 1, 1]
|
|
675
|
-
)
|
|
671
|
+
})().computeKernel([GROUP_SIZE, 1, 1])
|
|
676
672
|
}
|
|
677
673
|
|
|
678
674
|
override setup(builder: NodeBuilder): unknown {
|
|
679
|
-
this.setupCompute(builder)
|
|
680
675
|
return this.textureNode
|
|
681
676
|
}
|
|
682
677
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { RenderTarget } from 'three'
|
|
2
2
|
import { uniform } from 'three/tsl'
|
|
3
3
|
import {
|
|
4
4
|
NodeMaterial,
|
|
@@ -24,14 +24,17 @@ export abstract class SeparableFilterNode extends FilterNode {
|
|
|
24
24
|
private readonly mesh = new QuadMesh(this.material)
|
|
25
25
|
private rendererState?: RendererUtils.RendererState
|
|
26
26
|
|
|
27
|
-
protected readonly inputTexelSize = uniform(
|
|
28
|
-
protected readonly direction = uniform(
|
|
27
|
+
protected readonly inputTexelSize = uniform('vec2')
|
|
28
|
+
protected readonly direction = uniform('vec2')
|
|
29
29
|
|
|
30
30
|
constructor(inputNode?: TextureNode | null) {
|
|
31
31
|
super(inputNode)
|
|
32
|
+
const typeName = (this.constructor as typeof Node).type.replace(/Node$/, '')
|
|
33
|
+
this.material.name = typeName
|
|
34
|
+
this.mesh.name = typeName
|
|
32
35
|
|
|
33
|
-
this.horizontalRT = this.createRenderTarget('
|
|
34
|
-
this.verticalRT = this.createRenderTarget('
|
|
36
|
+
this.horizontalRT = this.createRenderTarget('horizontal')
|
|
37
|
+
this.verticalRT = this.createRenderTarget('vertical')
|
|
35
38
|
this.outputTexture = this.verticalRT.texture
|
|
36
39
|
}
|
|
37
40
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { RenderTarget } from 'three'
|
|
2
2
|
import { uniform } from 'three/tsl'
|
|
3
3
|
import {
|
|
4
4
|
NodeMaterial,
|
|
@@ -21,10 +21,13 @@ export abstract class SingleFilterNode extends FilterNode {
|
|
|
21
21
|
private readonly mesh = new QuadMesh(this.material)
|
|
22
22
|
private rendererState?: RendererUtils.RendererState
|
|
23
23
|
|
|
24
|
-
protected readonly inputTexelSize = uniform(
|
|
24
|
+
protected readonly inputTexelSize = uniform('vec2')
|
|
25
25
|
|
|
26
26
|
constructor(inputNode?: TextureNode | null) {
|
|
27
27
|
super(inputNode)
|
|
28
|
+
const typeName = (this.constructor as typeof Node).type.replace(/Node$/, '')
|
|
29
|
+
this.material.name = typeName
|
|
30
|
+
this.mesh.name = typeName
|
|
28
31
|
|
|
29
32
|
this.renderTarget = this.createRenderTarget()
|
|
30
33
|
this.outputTexture = this.renderTarget.texture
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/class-methods-use-this */
|
|
2
|
+
|
|
3
|
+
import { vec3 } from 'three/tsl'
|
|
4
|
+
import { StorageTextureNode, type Node, type NodeBuilder } from 'three/webgpu'
|
|
5
|
+
|
|
6
|
+
// WORKAROUND: StorageTextureNode on Storage3DTexture breaks UV.
|
|
7
|
+
// TODO: File a PR in the upstream.
|
|
8
|
+
export class StorageTexture3DNode extends StorageTextureNode {
|
|
9
|
+
static override get type(): string {
|
|
10
|
+
return 'StorageTexture3DNode'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override getDefaultUV(): Node {
|
|
14
|
+
return vec3(0.5, 0.5, 0.5)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setUpdateMatrix(_value: boolean): void {}
|
|
18
|
+
|
|
19
|
+
generateUV(builder: NodeBuilder, uvNode: Node): string {
|
|
20
|
+
return uvNode.build(builder, this.sampler ? 'vec3' : 'ivec3') as string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
generateOffset(builder: NodeBuilder, offsetNode: Node): string {
|
|
24
|
+
return offsetNode.build(builder, 'ivec3') as string
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const storageTexture3D = (
|
|
29
|
+
...args: ConstructorParameters<typeof StorageTexture3DNode>
|
|
30
|
+
): StorageTexture3DNode => new StorageTexture3DNode(...args)
|