@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.
Files changed (71) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +1 -1
  3. package/build/index.cjs +1 -1
  4. package/build/index.cjs.map +1 -1
  5. package/build/index.js +580 -598
  6. package/build/index.js.map +1 -1
  7. package/build/r3f.cjs +1 -1
  8. package/build/r3f.js +1 -1
  9. package/build/shared2.cjs +1 -1
  10. package/build/shared2.cjs.map +1 -1
  11. package/build/shared2.js +27 -212
  12. package/build/shared2.js.map +1 -1
  13. package/build/shared3.cjs +1 -1
  14. package/build/shared3.cjs.map +1 -1
  15. package/build/shared3.js +213 -8
  16. package/build/shared3.js.map +1 -1
  17. package/build/webgpu.cjs +6 -1
  18. package/build/webgpu.cjs.map +1 -1
  19. package/build/webgpu.js +1111 -768
  20. package/build/webgpu.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/EllipsoidGeometry.ts +1 -1
  23. package/src/PointOfView.ts +12 -5
  24. package/src/STBNLoader.ts +41 -19
  25. package/src/unrollLoops.ts +1 -1
  26. package/src/webgpu/CascadedShadowMapsNode.ts +48 -0
  27. package/src/webgpu/DualMipmapFilterNode.ts +8 -4
  28. package/src/webgpu/FilterNode.ts +5 -3
  29. package/src/webgpu/FnLayout.ts +17 -16
  30. package/src/webgpu/HighpVelocityNode.ts +9 -4
  31. package/src/webgpu/LensFlareNode.ts +12 -16
  32. package/src/webgpu/LensGlareNode.ts +28 -32
  33. package/src/webgpu/LensHaloNode.ts +2 -1
  34. package/src/webgpu/OutputTexture3DNode.ts +10 -0
  35. package/src/webgpu/OutputTextureNode.ts +10 -0
  36. package/src/webgpu/STBNTextureNode.ts +58 -0
  37. package/src/webgpu/ScreenSpaceShadowNode.ts +685 -0
  38. package/src/webgpu/SeparableFilterNode.ts +8 -5
  39. package/src/webgpu/SingleFilterNode.ts +5 -2
  40. package/src/webgpu/StorageTexture3DNode.ts +30 -0
  41. package/src/webgpu/TemporalAntialiasNode.ts +178 -137
  42. package/src/webgpu/accessors.ts +75 -36
  43. package/src/webgpu/debug.ts +38 -47
  44. package/src/webgpu/events.ts +18 -0
  45. package/src/webgpu/index.ts +5 -1
  46. package/src/webgpu/math.ts +116 -15
  47. package/src/webgpu/sampling.ts +39 -5
  48. package/src/webgpu/transformations.ts +71 -44
  49. package/types/PointOfView.d.ts +1 -1
  50. package/types/STBNLoader.d.ts +3 -4
  51. package/types/webgpu/CascadedShadowMapsNode.d.ts +13 -0
  52. package/types/webgpu/DualMipmapFilterNode.d.ts +1 -2
  53. package/types/webgpu/FnLayout.d.ts +4 -4
  54. package/types/webgpu/HighpVelocityNode.d.ts +1 -0
  55. package/types/webgpu/LensFlareNode.d.ts +2 -3
  56. package/types/webgpu/LensGlareNode.d.ts +1 -1
  57. package/types/webgpu/STBNTextureNode.d.ts +9 -0
  58. package/types/webgpu/ScreenSpaceShadowNode.d.ts +33 -0
  59. package/types/webgpu/SeparableFilterNode.d.ts +2 -3
  60. package/types/webgpu/SingleFilterNode.d.ts +1 -2
  61. package/types/webgpu/StorageTexture3DNode.d.ts +9 -0
  62. package/types/webgpu/TemporalAntialiasNode.d.ts +9 -10
  63. package/types/webgpu/accessors.d.ts +9 -8
  64. package/types/webgpu/debug.d.ts +4 -3
  65. package/types/webgpu/events.d.ts +3 -0
  66. package/types/webgpu/index.d.ts +5 -1
  67. package/types/webgpu/math.d.ts +3 -0
  68. package/types/webgpu/sampling.d.ts +2 -1
  69. package/types/webgpu/transformations.d.ts +7 -10
  70. package/src/webgpu/RTTextureNode.ts +0 -130
  71. package/types/webgpu/RTTextureNode.d.ts +0 -22
@@ -1,4 +1,4 @@
1
- import { Vector2, type RenderTarget } from 'three'
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(new Vector2())
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)
@@ -11,6 +11,7 @@ import {
11
11
  import { hash } from 'three/src/nodes/core/NodeUtils.js'
12
12
  import {
13
13
  and,
14
+ convertToTexture,
14
15
  float,
15
16
  Fn,
16
17
  If,
@@ -18,9 +19,7 @@ import {
18
19
  max,
19
20
  mix,
20
21
  screenCoordinate,
21
- screenSize,
22
22
  screenUV,
23
- select,
24
23
  sqrt,
25
24
  step,
26
25
  struct,
@@ -45,19 +44,15 @@ import {
45
44
  import { cameraFar, cameraNear } from './accessors'
46
45
  import { FnLayout } from './FnLayout'
47
46
  import { FnVar } from './FnVar'
47
+ import { highpVelocity } from './HighpVelocityNode'
48
48
  import { haltonOffsets } from './internals'
49
49
  import type { Node } from './node'
50
50
  import { outputTexture } from './OutputTextureNode'
51
- import { convertToTexture } from './RTTextureNode'
52
51
  import { logarithmicToPerspectiveDepth } from './transformations'
53
52
  import { isWebGPU } from './utils'
54
53
 
55
54
  const { resetRendererState, restoreRendererState } = RendererUtils
56
55
 
57
- interface VelocityNodeImmutable {
58
- projectionMatrix?: Matrix4 | null
59
- }
60
-
61
56
  interface SupportedCamera extends Camera {
62
57
  updateProjectionMatrix(): void
63
58
  setViewOffset(
@@ -81,8 +76,15 @@ function isSupportedCamera(camera: Camera): camera is SupportedCamera {
81
76
  )
82
77
  }
83
78
 
79
+ interface RenderPipelineContext {
80
+ context: {
81
+ onBeforeRenderPipeline?: () => void
82
+ onAfterRenderPipeline?: () => void
83
+ }
84
+ }
85
+
84
86
  interface PostProcessingContext {
85
- context?: {
87
+ context: {
86
88
  onBeforePostProcessing?: () => void
87
89
  onAfterPostProcessing?: () => void
88
90
  }
@@ -99,28 +101,26 @@ const clipAABB = /*#__PURE__*/ FnLayout({
99
101
  { name: 'maxColor', type: 'vec4' }
100
102
  ]
101
103
  })(([current, history, minColor, maxColor]) => {
102
- const pClip = maxColor.rgb.add(minColor.rgb).mul(0.5)
104
+ const pClip = maxColor.rgb.add(minColor.rgb).mul(0.5).toConst()
103
105
  const eClip = maxColor.rgb.sub(minColor.rgb).mul(0.5).add(1e-7)
104
- const vClip = history.sub(vec4(pClip, current.a))
106
+ const vClip = history.sub(vec4(pClip, current.a)).toConst()
105
107
  const vUnit = vClip.xyz.div(eClip)
106
- const absUnit = vUnit.abs()
107
- const maxUnit = max(absUnit.x, absUnit.y, absUnit.z)
108
- return select(
109
- maxUnit.greaterThan(1),
110
- vec4(pClip, current.a).add(vClip.div(maxUnit)),
111
- history
112
- )
108
+ const absUnit = vUnit.abs().toConst()
109
+ const maxUnit = max(absUnit.x, absUnit.y, absUnit.z).toConst()
110
+ return maxUnit
111
+ .greaterThan(1)
112
+ .select(vec4(pClip, current.a).add(vClip.div(maxUnit)), history)
113
113
  })
114
114
 
115
115
  const varianceOffsets = [
116
- /*#__PURE__*/ ivec2(-1, -1),
117
- /*#__PURE__*/ ivec2(-1, 1),
118
- /*#__PURE__*/ ivec2(1, -1),
119
- /*#__PURE__*/ ivec2(1, 1),
120
- /*#__PURE__*/ ivec2(1, 0),
121
- /*#__PURE__*/ ivec2(0, -1),
122
- /*#__PURE__*/ ivec2(0, 1),
123
- /*#__PURE__*/ ivec2(-1, 0)
116
+ [-1, -1],
117
+ [-1, 1],
118
+ [1, -1],
119
+ [1, 1],
120
+ [1, 0],
121
+ [0, -1],
122
+ [0, 1],
123
+ [-1, 0]
124
124
  ]
125
125
 
126
126
  const varianceClipping = /*#__PURE__*/ FnVar(
@@ -134,52 +134,68 @@ const varianceClipping = /*#__PURE__*/ FnVar(
134
134
  const moment1 = current.toVar()
135
135
  const moment2 = current.pow2().toVar()
136
136
 
137
- for (const offset of varianceOffsets) {
138
- const neighbor = inputNode.load(coord.add(offset))
137
+ for (const [x, y] of varianceOffsets) {
138
+ const neighbor = inputNode.load(coord.add(ivec2(x, y))).toConst()
139
139
  moment1.addAssign(neighbor)
140
140
  moment2.addAssign(neighbor.pow2())
141
141
  }
142
142
 
143
- const N = float(varianceOffsets.length + 1)
144
- const mean = moment1.div(N)
145
- const variance = sqrt(moment2.div(N).sub(mean.pow2()).max(0)).mul(gamma)
146
- const minColor = mean.sub(variance)
147
- const maxColor = mean.add(variance)
143
+ const N = varianceOffsets.length + 1
144
+ const mean = moment1.div(N).toConst()
145
+ const variance = sqrt(moment2.div(N).sub(mean.pow2()).max(0))
146
+ .mul(gamma)
147
+ .toConst()
148
+ const minColor = mean.sub(variance).toConst()
149
+ const maxColor = mean.add(variance).toConst()
148
150
 
149
151
  return clipAABB(mean.clamp(minColor, maxColor), history, minColor, maxColor)
150
152
  }
151
153
  )
152
154
 
153
155
  const neighborOffsets = [
154
- /*#__PURE__*/ ivec2(-1, -1),
155
- /*#__PURE__*/ ivec2(-1, 0),
156
- /*#__PURE__*/ ivec2(-1, 1),
157
- /*#__PURE__*/ ivec2(0, -1),
158
- /*#__PURE__*/ ivec2(0, 0),
159
- /*#__PURE__*/ ivec2(0, 1),
160
- /*#__PURE__*/ ivec2(1, -1),
161
- /*#__PURE__*/ ivec2(1, 0),
162
- /*#__PURE__*/ ivec2(1, 1)
156
+ [-1, -1],
157
+ [-1, 0],
158
+ [-1, 1],
159
+ [0, -1],
160
+ [0, 0],
161
+ [0, 1],
162
+ [1, -1],
163
+ [1, 0],
164
+ [1, 1]
163
165
  ]
164
166
 
165
- const closestDepthStruct = /*#__PURE__*/ struct({
166
- coord: 'ivec2',
167
- depth: 'float'
167
+ const currentDepthStruct = /*#__PURE__*/ struct({
168
+ closestCoord: 'ivec2',
169
+ closestDepth: 'float'
168
170
  })
169
171
 
170
- const getClosestDepth = /*#__PURE__*/ FnVar(
171
- (depthNode: TextureNode, inputCoord: Node<'ivec2'>) => {
172
- const depth = float(1)
173
- const coord = ivec2(0)
174
- for (const offset of neighborOffsets) {
175
- const offsetCoord = inputCoord.add(offset).toVar()
176
- const neighbor = depthNode.load(offsetCoord).toVar()
177
- If(neighbor.r.lessThan(depth), () => {
178
- coord.assign(offsetCoord)
179
- depth.assign(neighbor.r)
172
+ const getCurrentDepth = /*#__PURE__*/ FnVar(
173
+ (depthNode: TextureNode, inputCoord: Node<'ivec2'>) => builder => {
174
+ const closestCoord = ivec2(0).toVar()
175
+ const closestDepth = float(1).toVar()
176
+ for (const [x, y] of neighborOffsets) {
177
+ const neighbor = inputCoord.add(ivec2(x, y)).toConst()
178
+ let depth = depthNode.load(neighbor).r
179
+ if (builder.renderer.reversedDepthBuffer) {
180
+ depth = depth.oneMinus()
181
+ }
182
+ depth = depth.toConst()
183
+
184
+ If(depth.lessThan(closestDepth), () => {
185
+ closestCoord.assign(neighbor)
186
+ closestDepth.assign(depth)
180
187
  })
181
188
  }
182
- return closestDepthStruct(coord, depth)
189
+ return currentDepthStruct(closestCoord, closestDepth)
190
+ }
191
+ )
192
+
193
+ const subpixelCorrection = /*#__PURE__#*/ FnVar(
194
+ (velocityUV: Node<'vec2'>, textureSize: Node<'ivec2'>): Node<'float'> => {
195
+ const velocityTexel = velocityUV.mul(textureSize)
196
+ const phase = velocityTexel.fract().abs()
197
+ const weight = max(phase, phase.oneMinus())
198
+ return weight.x.mul(weight.y).oneMinus().div(0.75)
183
199
  }
184
200
  )
185
201
 
@@ -219,8 +235,6 @@ export class TemporalAntialiasNode extends TempNode {
219
235
  return 'TemporalAntialiasNode'
220
236
  }
221
237
 
222
- private readonly velocityNodeImmutable: VelocityNodeImmutable
223
-
224
238
  inputNode: TextureNode
225
239
  depthNode: TextureNode
226
240
  velocityNode: TextureNode
@@ -231,19 +245,17 @@ export class TemporalAntialiasNode extends TempNode {
231
245
  velocityThreshold = uniform(0.1)
232
246
  depthError = uniform(0.001)
233
247
 
234
- // Static options:
235
248
  debugShowRejection = false
236
249
 
237
250
  private readonly textureNode: TextureNode
238
251
 
239
- private resolveRT = this.createRenderTarget('Resolve')
240
- private historyRT = this.createRenderTarget('History')
252
+ private resolveRT = this.createRenderTarget('resolve')
253
+ private historyRT = this.createRenderTarget('history')
241
254
  private previousDepthTexture?: DepthTexture
242
255
  private readonly resolveMaterial = new NodeMaterial()
243
- private readonly copyMaterial = new NodeMaterial()
244
256
  private readonly mesh = new QuadMesh()
245
257
  private rendererState?: RendererUtils.RendererState
246
- private needsSyncPostProcessing = false
258
+ private needsSyncRenderPipeline = false
247
259
  private needsClearHistory = false
248
260
 
249
261
  private readonly resolveNode = texture(this.resolveRT.texture)
@@ -253,14 +265,16 @@ export class TemporalAntialiasNode extends TempNode {
253
265
  private jitterIndex = 0
254
266
 
255
267
  constructor(
256
- velocityNodeImmutable: VelocityNodeImmutable,
257
268
  inputNode: TextureNode,
258
269
  depthNode: TextureNode,
259
270
  velocityNode: TextureNode,
260
271
  camera: Camera
261
272
  ) {
262
273
  super('vec4')
263
- this.velocityNodeImmutable = velocityNodeImmutable
274
+ this.updateBeforeType = NodeUpdateType.FRAME
275
+ this.resolveMaterial.name = 'TemporalAntialias_resolve'
276
+ this.mesh.name = 'TemporalAntialias'
277
+
264
278
  this.inputNode = inputNode
265
279
  this.depthNode = depthNode
266
280
  this.velocityNode = velocityNode
@@ -270,8 +284,6 @@ export class TemporalAntialiasNode extends TempNode {
270
284
  this.camera = camera
271
285
 
272
286
  this.textureNode = outputTexture(this, this.resolveRT.texture)
273
-
274
- this.updateBeforeType = NodeUpdateType.FRAME
275
287
  }
276
288
 
277
289
  override customCacheKey(): number {
@@ -289,8 +301,8 @@ export class TemporalAntialiasNode extends TempNode {
289
301
  texture.magFilter = LinearFilter
290
302
  texture.generateMipmaps = false
291
303
 
292
- const typeName = (this.constructor as typeof TemporalAntialiasNode).type
293
- texture.name = name != null ? `${typeName}.${name}` : typeName
304
+ const typeName = (this.constructor as typeof Node).type
305
+ texture.name = name != null ? `${typeName}_${name}` : typeName
294
306
 
295
307
  return renderTarget
296
308
  }
@@ -299,13 +311,6 @@ export class TemporalAntialiasNode extends TempNode {
299
311
  return this.textureNode
300
312
  }
301
313
 
302
- private setProjectionMatrix(value: Matrix4 | null): void {
303
- const { velocityNodeImmutable: velocity } = this
304
- if (velocity != null) {
305
- velocity.projectionMatrix = value
306
- }
307
- }
308
-
309
314
  setSize(width: number, height: number): this {
310
315
  const { resolveRT, historyRT } = this
311
316
  if (width !== historyRT.width || height !== historyRT.height) {
@@ -324,11 +329,6 @@ export class TemporalAntialiasNode extends TempNode {
324
329
  renderer.setRenderTarget(this.historyRT)
325
330
  renderer.clear()
326
331
 
327
- // Copy the current input to the history with scaling.
328
- renderer.setRenderTarget(this.historyRT)
329
- this.mesh.material = this.copyMaterial
330
- this.mesh.render(renderer)
331
-
332
332
  this.needsClearHistory = false
333
333
  }
334
334
 
@@ -337,7 +337,7 @@ export class TemporalAntialiasNode extends TempNode {
337
337
  const { camera } = this
338
338
  camera.updateProjectionMatrix()
339
339
  this.originalProjectionMatrix.copy(camera.projectionMatrix)
340
- this.setProjectionMatrix(this.originalProjectionMatrix)
340
+ highpVelocity.setProjectionMatrix(this.originalProjectionMatrix)
341
341
 
342
342
  const offset = haltonOffsets[this.jitterIndex]
343
343
  const dx = offset.x - 0.5
@@ -348,7 +348,7 @@ export class TemporalAntialiasNode extends TempNode {
348
348
  private clearViewOffset(): void {
349
349
  // Reset the projection matrix modified in setViewOffset():
350
350
  this.camera.clearViewOffset()
351
- this.setProjectionMatrix(null)
351
+ highpVelocity.setProjectionMatrix(null)
352
352
 
353
353
  // setViewOffset() can be called multiple times in a frame. Increment the
354
354
  // jitter index here.
@@ -412,7 +412,7 @@ export class TemporalAntialiasNode extends TempNode {
412
412
  this.swapBuffers()
413
413
 
414
414
  // Don't jitter the camera in subsequent render passes if any:
415
- if (this.needsSyncPostProcessing) {
415
+ if (this.needsSyncRenderPipeline) {
416
416
  this.clearViewOffset()
417
417
  }
418
418
  }
@@ -421,51 +421,53 @@ export class TemporalAntialiasNode extends TempNode {
421
421
  const getPreviousDepth = (uv: Node<'vec2'>): Node<'float'> => {
422
422
  const { previousDepthNode: depthNode } = this
423
423
  const depth = depthNode
424
- .load(ivec2(uv.mul(textureSize(depthNode)).sub(0.5)))
425
- .toVar()
424
+ .load(ivec2(uv.mul(depthNode.size()).sub(0.5)))
425
+ .toConst()
426
426
  return renderer.logarithmicDepthBuffer
427
427
  ? logarithmicToPerspectiveDepth(
428
428
  depth,
429
429
  cameraNear(this.camera),
430
430
  cameraFar(this.camera)
431
431
  )
432
- : depth
432
+ : renderer.reversedDepthBuffer
433
+ ? depth.oneMinus()
434
+ : depth
433
435
  }
434
436
 
435
437
  return Fn(() => {
436
438
  const coord = ivec2(screenCoordinate)
437
439
  const uv = screenUV
438
440
 
439
- const currentColor = this.inputNode.load(coord)
440
- const closestDepth = getClosestDepth(this.depthNode, coord)
441
- const closestCoord = closestDepth.get('coord')
441
+ const currentDepth = getCurrentDepth(this.depthNode, coord).toConst()
442
+ const closestCoord = currentDepth.get('closestCoord')
443
+ const closestDepth = currentDepth.get('closestDepth')
442
444
 
443
- const velocity = this.velocityNode
445
+ const velocityUVW = this.velocityNode
444
446
  .load(closestCoord)
445
447
  .xyz.mul(vec3(0.5, -0.5, 0.5)) // Velocity is in NDC offset
446
- .toVar()
448
+ .toConst()
447
449
 
448
450
  // Discards texels with velocity greater than the threshold:
449
- const velocityConfidence = velocity.xy
451
+ const velocityConfidence = velocityUVW.xy
450
452
  .length()
451
453
  .div(this.velocityThreshold)
452
454
  .oneMinus()
453
455
  .saturate()
454
456
 
455
- const prevUV = uv.sub(velocity.xy).toVar()
457
+ const prevUV = uv.sub(velocityUVW.xy).toConst()
456
458
  const prevDepth = getPreviousDepth(prevUV)
457
459
 
458
460
  // TODO: Add gather() in TextureNode and use it:
459
461
  const expectedDepth = renderer.logarithmicDepthBuffer
460
462
  ? logarithmicToPerspectiveDepth(
461
- closestDepth.get('depth'),
463
+ closestDepth,
462
464
  cameraNear(this.camera),
463
465
  cameraFar(this.camera)
464
466
  )
465
- : closestDepth.get('depth')
467
+ : closestDepth
466
468
 
467
469
  const depthConfidence = step(
468
- expectedDepth.add(velocity.z),
470
+ expectedDepth.add(velocityUVW.z),
469
471
  prevDepth.add(this.depthError)
470
472
  )
471
473
 
@@ -477,15 +479,15 @@ export class TemporalAntialiasNode extends TempNode {
477
479
  ).toFloat()
478
480
 
479
481
  // Don't apply TAA on the background:
480
- const depthWeight = closestDepth.get('depth').notEqual(1).toFloat()
482
+ const depthWeight = closestDepth.notEqual(1).toFloat()
481
483
 
482
- const outputColor = vec4(0).toVar()
484
+ const outputColor = this.inputNode.load(coord).toVar()
483
485
  If(uvWeight.mul(depthWeight).mul(confidence).greaterThan(0), () => {
484
486
  const historyColor = texture(this.historyNode, prevUV)
485
487
  const clippedColor = varianceClipping(
486
488
  this.inputNode,
487
489
  coord,
488
- currentColor,
490
+ outputColor,
489
491
  historyColor,
490
492
  this.varianceGamma
491
493
  )
@@ -493,19 +495,14 @@ export class TemporalAntialiasNode extends TempNode {
493
495
  // Increase the temporal alpha when the velocity is more subpixel,
494
496
  // reducing blurriness under motion.
495
497
  // Reference: https://github.com/simco50/D3D12_Research/
496
- const velocityAbsTexel = velocity.xy.abs().mul(screenSize)
497
- const subpixelCorrection = max(velocityAbsTexel.x, velocityAbsTexel.y)
498
- .fract()
499
- .mul(0.5)
500
498
  const temporalAlpha = mix(
501
499
  this.temporalAlpha,
502
- 0.8,
503
- subpixelCorrection
500
+ 0.4,
501
+ subpixelCorrection(velocityUVW.xy, textureSize(this.inputNode))
504
502
  ).saturate()
505
503
 
506
- outputColor.assign(mix(clippedColor, currentColor, temporalAlpha))
504
+ outputColor.assign(mix(clippedColor, outputColor, temporalAlpha))
507
505
  }).Else(() => {
508
- outputColor.assign(currentColor)
509
506
  if (this.debugShowRejection) {
510
507
  outputColor.assign(vec3(1, 0, 0))
511
508
  }
@@ -516,26 +513,30 @@ export class TemporalAntialiasNode extends TempNode {
516
513
  }
517
514
 
518
515
  override setup(builder: NodeBuilder): unknown {
519
- const { context } = (builder.getContext().postProcessing ??
520
- {}) as PostProcessingContext
521
- if (context != null) {
522
- const { onBeforePostProcessing } = context
523
- context.onBeforePostProcessing = () => {
524
- onBeforePostProcessing?.()
525
- const size = builder.renderer.getDrawingBufferSize(sizeScratch)
526
- this.setViewOffset(size.width, size.height)
527
- }
528
- this.needsSyncPostProcessing = true
516
+ // We have to take care of the renaming of PostProcessing to RenderPipeline
517
+ // in r183, as well as changes to property fields in the context.
518
+ const onBeforeRenderPipeline = (): void => {
519
+ const size = builder.renderer.getDrawingBufferSize(sizeScratch)
520
+ this.setViewOffset(size.width, size.height)
521
+ }
522
+ if (builder.context.renderPipeline != null) {
523
+ const { context } = builder.context
524
+ .renderPipeline as RenderPipelineContext
525
+ context.onBeforeRenderPipeline = onBeforeRenderPipeline
526
+ this.needsSyncRenderPipeline = true
527
+ }
528
+ if (builder.context.postProcessing != null) {
529
+ const { context } = builder.context
530
+ .postProcessing as PostProcessingContext
531
+ context.onBeforePostProcessing = onBeforeRenderPipeline
532
+ this.needsSyncRenderPipeline = true
529
533
  }
530
534
 
531
- const { resolveMaterial, copyMaterial } = this
535
+ const { resolveMaterial } = this
532
536
 
533
537
  resolveMaterial.fragmentNode = this.setupResolveNode(builder)
534
538
  resolveMaterial.needsUpdate = true
535
539
 
536
- copyMaterial.fragmentNode = this.inputNode
537
- copyMaterial.needsUpdate = true
538
-
539
540
  this.textureNode.uvNode = this.inputNode.uvNode
540
541
  return this.textureNode
541
542
  }
@@ -545,24 +546,64 @@ export class TemporalAntialiasNode extends TempNode {
545
546
  this.historyRT.dispose()
546
547
  this.previousDepthTexture?.dispose()
547
548
  this.resolveMaterial.dispose()
548
- this.copyMaterial.dispose()
549
549
  this.mesh.geometry.dispose()
550
550
  super.dispose()
551
551
  }
552
552
  }
553
553
 
554
- export const temporalAntialias =
555
- (velocityNodeImmutable: VelocityNodeImmutable) =>
556
- (
557
- inputNode: Node,
558
- depthNode: TextureNode,
559
- velocityNode: TextureNode,
560
- camera: Camera
561
- ): TemporalAntialiasNode =>
562
- new TemporalAntialiasNode(
563
- velocityNodeImmutable,
564
- convertToTexture(inputNode, 'TemporalAntialiasNode.Input'),
565
- depthNode,
566
- velocityNode,
567
- camera
568
- )
554
+ /**
555
+ * @deprecated Function signature has been changed. Use
556
+ * temporalAntialias(inputNode, depthNode, velocityNode, camera)
557
+ */
558
+ export function temporalAntialias(
559
+ velocityNodeImmutable: unknown
560
+ ): (
561
+ inputNode: Node,
562
+ depthNode: TextureNode,
563
+ velocityNode: TextureNode,
564
+ camera: Camera
565
+ ) => TemporalAntialiasNode
566
+
567
+ export function temporalAntialias(
568
+ inputNode: Node,
569
+ depthNode: TextureNode,
570
+ velocityNode: TextureNode,
571
+ camera: Camera
572
+ ): TemporalAntialiasNode
573
+
574
+ export function temporalAntialias(...args: any[]): any {
575
+ if (args.length === 1) {
576
+ return (
577
+ inputNode: Node,
578
+ depthNode: TextureNode,
579
+ velocityNode: TextureNode,
580
+ camera: Camera
581
+ ): TemporalAntialiasNode =>
582
+ new TemporalAntialiasNode(
583
+ convertToTexture(inputNode),
584
+ depthNode,
585
+ velocityNode,
586
+ camera
587
+ )
588
+ }
589
+ const [inputNode, depthNode, velocityNode, camera] = args
590
+ return new TemporalAntialiasNode(
591
+ convertToTexture(inputNode),
592
+ depthNode,
593
+ velocityNode,
594
+ camera
595
+ )
596
+ }
597
+
598
+ // export const temporalAntialias = (
599
+ // inputNode: Node,
600
+ // depthNode: TextureNode,
601
+ // velocityNode: TextureNode,
602
+ // camera: Camera
603
+ // ): TemporalAntialiasNode =>
604
+ // new TemporalAntialiasNode(
605
+ // convertToTexture(inputNode),
606
+ // depthNode,
607
+ // velocityNode,
608
+ // camera
609
+ // )