-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathPingPongPlane.ts
103 lines (89 loc) · 3.5 KB
/
PingPongPlane.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { isRenderer, Renderer } from '../../core/renderers/utils'
import { RenderTarget } from '../../core/renderPasses/RenderTarget'
import { FullscreenPlane } from '../../core/meshes/FullscreenPlane'
import { GPUCurtains } from '../GPUCurtains'
import { RenderTexture, RenderTextureParams } from '../../core/textures/RenderTexture'
import { MeshBaseRenderParams } from '../../core/meshes/mixins/MeshBaseMixin'
/**
* Used to create a special type of {@link FullscreenPlane} that allows to use the previous frame fragment shader output as an input texture.
*
* @example
* ```javascript
* // set our main GPUCurtains instance
* const gpuCurtains = new GPUCurtains({
* container: '#canvas' // selector of our WebGPU canvas container
* })
*
* // set the GPU device
* // note this is asynchronous
* await gpuCurtains.setDevice()
*
* // create a PingPongPlane
* const shaderPass = new PingPongPlane(gpuCurtain, {
* label: 'My ping pong plane',
* shaders: {
* fragment: {
* code: pingPongCode, // assume it is a valid WGSL fragment shader
* },
* },
* })
* ```
*/
export class PingPongPlane extends FullscreenPlane {
/** {@link RenderTarget} content to use as an input */
outputTarget: RenderTarget
/**
* PingPongPlane constructor
* @param renderer - {@link Renderer} object or {@link GPUCurtains} class object used to create this {@link PingPongPlane}
* @param parameters - {@link MeshBaseRenderParams | parameters} use to create this {@link PingPongPlane}
*/
constructor(renderer: Renderer | GPUCurtains, parameters = {} as MeshBaseRenderParams) {
renderer = (renderer && (renderer as GPUCurtains).renderer) || (renderer as Renderer)
isRenderer(renderer, parameters.label ? parameters.label + ' PingPongPlane' : 'PingPongPlane')
// we will render into a separate texture
parameters.outputTarget = new RenderTarget(renderer, {
label: parameters.label ? parameters.label + ' render target' : 'Ping Pong render target',
useDepth: false,
...(parameters.targetFormat && { targetFormat: parameters.targetFormat }),
})
// no blending and depth for ping pong planes
parameters.transparent = false
parameters.depth = false
parameters.label = parameters.label ?? 'PingPongPlane ' + renderer.pingPongPlanes?.length
super(renderer, parameters)
this.type = 'PingPongPlane'
this.createRenderTexture({
label: parameters.label ? `${parameters.label} render texture` : 'PingPongPlane render texture',
name: 'renderTexture',
...(parameters.targetFormat && { format: parameters.targetFormat }),
} as RenderTextureParams)
}
/**
* Get our main {@link RenderTexture}, the one that contains our ping pong content
* @readonly
*/
get renderTexture(): RenderTexture | undefined {
return this.renderTextures.find((texture) => texture.options.name === 'renderTexture')
}
/**
* Add the {@link PingPongPlane} to the renderer and the {@link core/scenes/Scene.Scene | Scene}
*/
addToScene() {
this.renderer.pingPongPlanes.push(this)
if (this.autoRender) {
this.renderer.scene.addPingPongPlane(this)
}
}
/**
* Remove the {@link PingPongPlane} from the renderer and the {@link core/scenes/Scene.Scene | Scene}
*/
removeFromScene() {
if (this.outputTarget) {
this.outputTarget.destroy()
}
if (this.autoRender) {
this.renderer.scene.removePingPongPlane(this)
}
this.renderer.pingPongPlanes = this.renderer.pingPongPlanes.filter((pPP) => pPP.uuid !== this.uuid)
}
}