@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
|
@@ -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)
|
|
@@ -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
|
|
109
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
|
138
|
-
const neighbor = inputNode.load(coord.add(
|
|
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 =
|
|
144
|
-
const mean = moment1.div(N)
|
|
145
|
-
const variance = sqrt(moment2.div(N).sub(mean.pow2()).max(0))
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
const currentDepthStruct = /*#__PURE__*/ struct({
|
|
168
|
+
closestCoord: 'ivec2',
|
|
169
|
+
closestDepth: 'float'
|
|
168
170
|
})
|
|
169
171
|
|
|
170
|
-
const
|
|
171
|
-
(depthNode: TextureNode, inputCoord: Node<'ivec2'>) => {
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
for (const
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
|
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('
|
|
240
|
-
private historyRT = this.createRenderTarget('
|
|
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
|
|
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.
|
|
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
|
|
293
|
-
texture.name = name != null ? `${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
|
-
|
|
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
|
-
|
|
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.
|
|
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(
|
|
425
|
-
.
|
|
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
|
-
:
|
|
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
|
|
440
|
-
const
|
|
441
|
-
const
|
|
441
|
+
const currentDepth = getCurrentDepth(this.depthNode, coord).toConst()
|
|
442
|
+
const closestCoord = currentDepth.get('closestCoord')
|
|
443
|
+
const closestDepth = currentDepth.get('closestDepth')
|
|
442
444
|
|
|
443
|
-
const
|
|
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
|
-
.
|
|
448
|
+
.toConst()
|
|
447
449
|
|
|
448
450
|
// Discards texels with velocity greater than the threshold:
|
|
449
|
-
const velocityConfidence =
|
|
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(
|
|
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
|
|
463
|
+
closestDepth,
|
|
462
464
|
cameraNear(this.camera),
|
|
463
465
|
cameraFar(this.camera)
|
|
464
466
|
)
|
|
465
|
-
: closestDepth
|
|
467
|
+
: closestDepth
|
|
466
468
|
|
|
467
469
|
const depthConfidence = step(
|
|
468
|
-
expectedDepth.add(
|
|
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.
|
|
482
|
+
const depthWeight = closestDepth.notEqual(1).toFloat()
|
|
481
483
|
|
|
482
|
-
const outputColor =
|
|
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
|
-
|
|
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.
|
|
503
|
-
subpixelCorrection
|
|
500
|
+
0.4,
|
|
501
|
+
subpixelCorrection(velocityUVW.xy, textureSize(this.inputNode))
|
|
504
502
|
).saturate()
|
|
505
503
|
|
|
506
|
-
outputColor.assign(mix(clippedColor,
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
|
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
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
+
// )
|