@zephyr3d/scene 0.9.17 → 0.9.19

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 (68) hide show
  1. package/dist/animation/joint_dynamics/collision.js +8 -6
  2. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  3. package/dist/animation/morphtargetgrouptrack.js +11 -3
  4. package/dist/animation/morphtargetgrouptrack.js.map +1 -1
  5. package/dist/app/scriptregistry.js +124 -6
  6. package/dist/app/scriptregistry.js.map +1 -1
  7. package/dist/index.d.ts +270 -7
  8. package/dist/index.js +2 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +11 -5
  11. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  12. package/dist/material/mtoon.js +20 -2
  13. package/dist/material/mtoon.js.map +1 -1
  14. package/dist/material/shader/helper.js +21 -8
  15. package/dist/material/shader/helper.js.map +1 -1
  16. package/dist/material/skin.js +4 -6
  17. package/dist/material/skin.js.map +1 -1
  18. package/dist/material/water.js +1 -1
  19. package/dist/material/water.js.map +1 -1
  20. package/dist/posteffect/bloom.js +177 -29
  21. package/dist/posteffect/bloom.js.map +1 -1
  22. package/dist/posteffect/compositor.js +111 -204
  23. package/dist/posteffect/compositor.js.map +1 -1
  24. package/dist/posteffect/motionblur.js +3 -0
  25. package/dist/posteffect/motionblur.js.map +1 -1
  26. package/dist/posteffect/posteffect.js +79 -0
  27. package/dist/posteffect/posteffect.js.map +1 -1
  28. package/dist/posteffect/skinsss.js +10 -10
  29. package/dist/posteffect/skinsss.js.map +1 -1
  30. package/dist/posteffect/ssr.js +247 -16
  31. package/dist/posteffect/ssr.js.map +1 -1
  32. package/dist/posteffect/taa.js +121 -19
  33. package/dist/posteffect/taa.js.map +1 -1
  34. package/dist/posteffect/tonemap.js +6 -6
  35. package/dist/posteffect/tonemap.js.map +1 -1
  36. package/dist/render/abuffer_oit.js +2 -1
  37. package/dist/render/abuffer_oit.js.map +1 -1
  38. package/dist/render/envlight.js +6 -3
  39. package/dist/render/envlight.js.map +1 -1
  40. package/dist/render/hzb.js +11 -4
  41. package/dist/render/hzb.js.map +1 -1
  42. package/dist/render/lightpass.js +7 -15
  43. package/dist/render/lightpass.js.map +1 -1
  44. package/dist/render/renderer.js +4 -3
  45. package/dist/render/renderer.js.map +1 -1
  46. package/dist/render/rendergraph/blackboard.js +78 -0
  47. package/dist/render/rendergraph/blackboard.js.map +1 -0
  48. package/dist/render/rendergraph/executor.js +41 -11
  49. package/dist/render/rendergraph/executor.js.map +1 -1
  50. package/dist/render/rendergraph/forward_plus_builder.js +495 -201
  51. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  52. package/dist/render/rendergraph/rendergraph.js +29 -0
  53. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  54. package/dist/render/rendergraph/types.js.map +1 -1
  55. package/dist/scene/light.js +146 -146
  56. package/dist/scene/light.js.map +1 -1
  57. package/dist/shaders/ssr.js +52 -21
  58. package/dist/shaders/ssr.js.map +1 -1
  59. package/dist/shadow/shadowmapper.js +95 -95
  60. package/dist/shadow/shadowmapper.js.map +1 -1
  61. package/dist/utility/misc.js +10 -1
  62. package/dist/utility/misc.js.map +1 -1
  63. package/dist/utility/serialization/manager.js +2 -1
  64. package/dist/utility/serialization/manager.js.map +1 -1
  65. package/dist/utility/serialization/scene/animation.js +36 -2
  66. package/dist/utility/serialization/scene/animation.js.map +1 -1
  67. package/dist/utility/serialization/scene/light.js.map +1 -1
  68. package/package.json +2 -2
@@ -1,7 +1,4 @@
1
- import { linearToGamma } from '../shaders/misc.js';
2
1
  import { PostEffectLayer } from './posteffect.js';
3
- import { MaterialVaryingFlags } from '../values.js';
4
- import { fetchSampler } from '../utility/misc.js';
5
2
  import { DRef } from '@zephyr3d/base';
6
3
 
7
4
  /**
@@ -9,14 +6,6 @@ import { DRef } from '@zephyr3d/base';
9
6
  * @public
10
7
  */ class Compositor {
11
8
  /** @internal */ _postEffects;
12
- /** @internal */ _finalFramebuffer;
13
- /** @internal */ _prevInputTexture;
14
- /** @internal */ _prevFrameBuffer;
15
- /** @internal */ _textureFormat;
16
- /** @internal */ static _blitProgram = null;
17
- /** @internal */ static _blitBindgroup = null;
18
- /** @internal */ static _blitRenderStates = null;
19
- /** @internal */ static _blitVertexLayout = null;
20
9
  /**
21
10
  * Creates an instance of Compositor
22
11
  */ constructor(){
@@ -24,20 +13,120 @@ import { DRef } from '@zephyr3d/base';
24
13
  this._postEffects[PostEffectLayer.opaque] = [];
25
14
  this._postEffects[PostEffectLayer.transparent] = [];
26
15
  this._postEffects[PostEffectLayer.end] = [];
27
- this._finalFramebuffer = null;
28
- this._prevInputTexture = null;
29
- this._prevFrameBuffer = null;
30
- this._textureFormat = 'rgba16f';
31
16
  }
32
- /** @internal */ requireLinearDepth(ctx) {
33
- for (const list of this._postEffects){
34
- for (const postEffect of list){
35
- if (postEffect.get().requireLinearDepthTexture(ctx)) {
36
- return true;
17
+ /** @internal */ layerHasEnabledEffect(layer) {
18
+ return this._postEffects[layer].some((ref)=>!!ref.get()?.enabled);
19
+ }
20
+ /** @internal */ getIntermediateFormat(ctx) {
21
+ return ctx.camera.HDR && ctx.device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer ? 'rgba16f' : 'rgba8unorm';
22
+ }
23
+ /**
24
+ * Build the enabled effects of a layer as render graph passes.
25
+ *
26
+ * Effects are chained through graph texture handles: each effect's setup()
27
+ * declares its passes reading the previous output. Where each effect output
28
+ * lands (intermediate texture or the final target) is decided here through
29
+ * the {@link PostEffectSetupContext.createOutput} implementation, so effect
30
+ * code never handles final-target selection.
31
+ *
32
+ * @param options - Build inputs.
33
+ * @returns The chain output handle and whether the final target was written directly.
34
+ */ buildLayer(options) {
35
+ const { graph, ctx, layer, blackboard, input } = options;
36
+ const effects = this._postEffects[layer].map((ref)=>ref.get()).filter((effect)=>!!effect && effect.enabled);
37
+ if (effects.length === 0) {
38
+ return {
39
+ color: input,
40
+ wroteFinal: false
41
+ };
42
+ }
43
+ const colorFormat = this.getIntermediateFormat(ctx);
44
+ const finalOutput = options.finalOutput ?? null;
45
+ const history = options.history ?? null;
46
+ const dependencies = options.dependencies ?? [];
47
+ const historyReads = options.historyReads ?? [];
48
+ const sceneDepthAttachment = options.sceneDepthAttachment ?? null;
49
+ const inputResidesInFinalTarget = !!options.inputResidesInFinalTarget;
50
+ const width = ctx.renderWidth;
51
+ const height = ctx.renderHeight;
52
+ let chain = input;
53
+ let wroteFinal = false;
54
+ for(let i = 0; i < effects.length; i++){
55
+ const effect = effects[i];
56
+ const isLast = i === effects.length - 1;
57
+ // An effect that samples the final target's texture must not render into
58
+ // it in the same pass (feedback loop); force an intermediate output.
59
+ const inputIsFinalTarget = inputResidesInFinalTarget && chain === input;
60
+ const label = `PostEffect:${effect.constructor.name}`;
61
+ const setupContext = {
62
+ graph,
63
+ ctx,
64
+ blackboard,
65
+ input: chain,
66
+ colorFormat,
67
+ width,
68
+ height,
69
+ history,
70
+ sceneDepthAttachment,
71
+ dependencies,
72
+ historyReads,
73
+ createOutput (builder, opts) {
74
+ const needDepthAttachment = !!opts?.needDepthAttachment;
75
+ // Direct write to the final target is only allowed for the last effect
76
+ // of the chain, only when the effect does not depth-test against
77
+ // scene depth (the final target does not carry the scene depth
78
+ // buffer), and only when the effect does not sample the final
79
+ // target's own texture as its input.
80
+ if (isLast && finalOutput && !needDepthAttachment && !inputIsFinalTarget) {
81
+ wroteFinal = true;
82
+ const color = builder.write(finalOutput.handle);
83
+ if (finalOutput.isScreen) {
84
+ // Device default framebuffer: not a graph resource; the effect
85
+ // must gamma-correct since the screen is sRGB.
86
+ return {
87
+ color,
88
+ framebuffer: null,
89
+ srgbOutput: true
90
+ };
91
+ }
92
+ const framebuffer = builder.createFramebuffer({
93
+ label: `${label}:finalFB`,
94
+ width,
95
+ height,
96
+ colorAttachments: color,
97
+ depthAttachment: null
98
+ });
99
+ return {
100
+ color,
101
+ framebuffer,
102
+ srgbOutput: false
103
+ };
104
+ }
105
+ const color = builder.createTexture({
106
+ format: colorFormat,
107
+ label: `${label}:out`
108
+ });
109
+ const framebuffer = builder.createFramebuffer({
110
+ label: `${label}:outFB`,
111
+ width,
112
+ height,
113
+ colorAttachments: color,
114
+ depthAttachment: needDepthAttachment ? sceneDepthAttachment : null,
115
+ ignoreDepthStencil: !needDepthAttachment
116
+ });
117
+ return {
118
+ color,
119
+ framebuffer,
120
+ srgbOutput: false
121
+ };
37
122
  }
38
- }
123
+ };
124
+ chain = effect.setup(setupContext);
39
125
  }
40
- return false;
126
+ return {
127
+ color: chain,
128
+ wroteFinal
129
+ };
41
130
  }
42
131
  /**
43
132
  * Adds a posteffect
@@ -79,188 +168,6 @@ import { DRef } from '@zephyr3d/base';
79
168
  list.splice(0, list.length);
80
169
  }
81
170
  }
82
- /** @internal */ begin(ctx) {
83
- const device = ctx.device;
84
- this._textureFormat = ctx.camera.HDR && device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer ? 'rgba16f' : 'rgba8unorm';
85
- this._finalFramebuffer = device.getFramebuffer();
86
- if (this._postEffects.every((list)=>list.length === 0)) {
87
- return;
88
- }
89
- const depth = this._finalFramebuffer?.getDepthAttachment();
90
- const w = depth ? depth.width : device.getDrawingBufferWidth();
91
- const h = depth ? depth.height : device.getDrawingBufferHeight();
92
- const attachments = [
93
- this._textureFormat
94
- ];
95
- if (ctx.materialFlags & MaterialVaryingFlags.SSR_STORE_ROUGHNESS) {
96
- attachments.push(ctx.SSRRoughnessTexture, ctx.SSRNormalTexture);
97
- } else if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_NORMAL) {
98
- attachments.push(ctx.SSRNormalTexture);
99
- }
100
- if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_PROFILE) {
101
- attachments.push(ctx.SSSProfileTexture, ctx.SSSParamTexture);
102
- }
103
- if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_DIFFUSE) {
104
- attachments.push(ctx.SSSDiffuseTexture);
105
- }
106
- if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_TRANSMISSION) {
107
- attachments.push(ctx.SSSTransmissionTexture);
108
- }
109
- if (ctx.materialFlags & MaterialVaryingFlags.SKIN_SSS_STORE) {
110
- attachments.push(ctx.SkinSSSTexture);
111
- }
112
- const tmpFramebuffer = device.pool.fetchTemporalFramebuffer(true, w, h, attachments.length === 1 ? attachments[0] : attachments, depth ?? ctx.depthFormat);
113
- device.setFramebuffer(tmpFramebuffer);
114
- }
115
- /** @internal */ drawPostEffects(ctx, layer, sceneDepthTexture) {
116
- const postEffects = this._postEffects[layer];
117
- if (postEffects.length > 0) {
118
- const device = ctx.device;
119
- const inputFramebuffer = device.getFramebuffer();
120
- const inputTexture = inputFramebuffer.getColorAttachments()[0];
121
- let tmpTexture = null;
122
- for(let i = 0; i < postEffects.length; i++){
123
- const postEffect = postEffects[i].get();
124
- if (!postEffect.enabled) {
125
- continue;
126
- }
127
- if (this._prevFrameBuffer) {
128
- device.pool.releaseFrameBuffer(this._prevFrameBuffer);
129
- this._prevFrameBuffer = null;
130
- }
131
- const isLast = this.isLastPostEffect(layer, i);
132
- const finalEffect = isLast && (!postEffect.requireDepthAttachment(ctx) || !!this._finalFramebuffer);
133
- let singleColorFramebuffer = null;
134
- if (finalEffect) {
135
- singleColorFramebuffer = this.createSingleColorFramebuffer(device, this._finalFramebuffer, postEffect.requireDepthAttachment(ctx));
136
- device.setFramebuffer(singleColorFramebuffer ?? this._finalFramebuffer);
137
- } else {
138
- this._prevFrameBuffer = device.pool.fetchTemporalFramebuffer(false, inputFramebuffer.getWidth(), inputFramebuffer.getHeight(), this._textureFormat, inputFramebuffer.getDepthAttachment() ?? null);
139
- device.setFramebuffer(this._prevFrameBuffer);
140
- }
141
- const inputColorTexture = tmpTexture ?? inputTexture;
142
- try {
143
- postEffect.apply(ctx, inputColorTexture, sceneDepthTexture, !device.getFramebuffer());
144
- } finally{
145
- if (singleColorFramebuffer) {
146
- device.setFramebuffer(this._finalFramebuffer);
147
- device.pool.releaseFrameBuffer(singleColorFramebuffer);
148
- }
149
- }
150
- if (this._prevInputTexture) {
151
- device.pool.releaseTexture(this._prevInputTexture);
152
- this._prevInputTexture = null;
153
- }
154
- if (this._prevFrameBuffer) {
155
- tmpTexture = this._prevFrameBuffer.getColorAttachments()[0];
156
- device.pool.retainTexture(tmpTexture);
157
- this._prevInputTexture = tmpTexture;
158
- }
159
- }
160
- }
161
- }
162
- /** @internal */ end(ctx) {
163
- const device = ctx.device;
164
- if (device.getFramebuffer() !== this._finalFramebuffer) {
165
- const srcTex = device.getFramebuffer().getColorAttachments()[0];
166
- const singleColorFramebuffer = this.createSingleColorFramebuffer(device, this._finalFramebuffer, false);
167
- device.setFramebuffer(singleColorFramebuffer ?? this._finalFramebuffer);
168
- device.setViewport(null);
169
- device.setScissor(null);
170
- try {
171
- Compositor._blit(device, srcTex, !this._finalFramebuffer);
172
- } finally{
173
- if (singleColorFramebuffer) {
174
- device.setFramebuffer(this._finalFramebuffer);
175
- device.pool.releaseFrameBuffer(singleColorFramebuffer);
176
- }
177
- }
178
- }
179
- if (this._prevInputTexture) {
180
- device.pool.releaseTexture(this._prevInputTexture);
181
- this._prevInputTexture = null;
182
- }
183
- if (this._prevFrameBuffer) {
184
- device.pool.releaseFrameBuffer(this._prevFrameBuffer);
185
- this._prevFrameBuffer = null;
186
- }
187
- }
188
- /** @internal */ isLastPostEffect(layer, index) {
189
- for(let i = layer; i < this._postEffects.length; i++){
190
- const start = i === layer ? index + 1 : 0;
191
- for(let j = start; j < this._postEffects[i].length; j++){
192
- if (this._postEffects[i][j].get().enabled) {
193
- return false;
194
- }
195
- }
196
- }
197
- return true;
198
- }
199
- /** @internal */ createSingleColorFramebuffer(device, framebuffer, withDepth) {
200
- const colorAttachment = framebuffer?.getColorAttachments()[0] ?? null;
201
- if (!framebuffer || framebuffer.getColorAttachments().length <= 1 || !colorAttachment) {
202
- return null;
203
- }
204
- return device.pool.fetchTemporalFramebuffer(false, 0, 0, colorAttachment, withDepth ? framebuffer.getDepthAttachment() : null, false);
205
- }
206
- /** @internal */ static _blit(device, srcTex, srgbOutput) {
207
- if (!this._blitProgram) {
208
- this._blitProgram = device.buildRenderProgram({
209
- vertex (pb) {
210
- this.$inputs.pos = pb.vec2().attrib('position');
211
- this.$outputs.uv = pb.vec2();
212
- this.flip = pb.int().uniform(0);
213
- pb.main(function() {
214
- this.$builtins.position = pb.vec4(this.$inputs.pos, 0, 1);
215
- this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));
216
- this.$if(pb.notEqual(this.flip, 0), function() {
217
- this.$builtins.position.y = pb.neg(this.$builtins.position.y);
218
- });
219
- });
220
- },
221
- fragment (pb) {
222
- this.srcTex = pb.tex2D().sampleType('unfilterable-float').uniform(0);
223
- this.srgbOutput = pb.int().uniform(0);
224
- this.$outputs.outColor = pb.vec4();
225
- pb.main(function() {
226
- this.$outputs.outColor = pb.textureSample(this.srcTex, this.$inputs.uv);
227
- this.$if(pb.notEqual(this.srgbOutput, 0), function() {
228
- this.$outputs.outColor = pb.vec4(linearToGamma(this, this.$outputs.outColor.rgb), 1);
229
- });
230
- });
231
- }
232
- });
233
- this._blitProgram.name = '@Compositor_blit';
234
- this._blitBindgroup = device.createBindGroup(this._blitProgram.bindGroupLayouts[0]);
235
- this._blitVertexLayout = device.createVertexLayout({
236
- vertexBuffers: [
237
- {
238
- buffer: device.createVertexBuffer('position_f32x2', new Float32Array([
239
- -1,
240
- -1,
241
- 1,
242
- -1,
243
- -1,
244
- 1,
245
- 1,
246
- 1
247
- ]))
248
- }
249
- ]
250
- });
251
- this._blitRenderStates = device.createRenderStateSet();
252
- this._blitRenderStates.useRasterizerState().setCullMode('none');
253
- this._blitRenderStates.useDepthState().enableTest(false).enableWrite(false);
254
- }
255
- this._blitBindgroup.setTexture('srcTex', srcTex, fetchSampler('clamp_nearest_nomip'));
256
- this._blitBindgroup.setValue('srgbOutput', srgbOutput ? 1 : 0);
257
- this._blitBindgroup.setValue('flip', device.type === 'webgpu' && !!device.getFramebuffer() ? 1 : 0);
258
- device.setRenderStates(this._blitRenderStates);
259
- device.setProgram(this._blitProgram);
260
- device.setBindGroup(0, this._blitBindgroup);
261
- device.setVertexLayout(this._blitVertexLayout);
262
- device.draw('triangle-strip', 0, 4);
263
- }
264
171
  }
265
172
 
266
173
  export { Compositor };
@@ -1 +1 @@
1
- {"version":3,"file":"compositor.js","sources":["../../src/posteffect/compositor.ts"],"sourcesContent":["import { linearToGamma } from '../shaders/misc';\r\nimport type { DrawContext } from '../render';\r\nimport type {\r\n AbstractDevice,\r\n BindGroup,\r\n FrameBuffer,\r\n GPUProgram,\r\n RenderStateSet,\r\n Texture2D,\r\n TextureFormat,\r\n VertexLayout\r\n} from '@zephyr3d/device';\r\nimport type { AbstractPostEffect } from './posteffect';\r\nimport { PostEffectLayer } from './posteffect';\r\nimport { MaterialVaryingFlags } from '../values';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport type { Nullable } from '@zephyr3d/base';\r\nimport { DRef } from '@zephyr3d/base';\r\n\r\n/**\r\n * Posteffect rendering context\r\n * @public\r\n */\r\nexport interface CompositorContext {\r\n pingpongFramebuffers: FrameBuffer[];\r\n finalFramebuffer: FrameBuffer;\r\n writeIndex: number;\r\n}\r\n/**\r\n * Post processing compositor\r\n * @public\r\n */\r\nexport class Compositor {\r\n /** @internal */\r\n protected _postEffects: DRef<AbstractPostEffect>[][];\r\n /** @internal */\r\n private _finalFramebuffer: Nullable<FrameBuffer>;\r\n /** @internal */\r\n private _prevInputTexture: Nullable<Texture2D>;\r\n /** @internal */\r\n private _prevFrameBuffer: Nullable<FrameBuffer>;\r\n /** @internal */\r\n private _textureFormat: TextureFormat;\r\n /** @internal */\r\n private static _blitProgram: Nullable<GPUProgram> = null;\r\n /** @internal */\r\n private static _blitBindgroup: Nullable<BindGroup> = null;\r\n /** @internal */\r\n private static _blitRenderStates: Nullable<RenderStateSet> = null;\r\n /** @internal */\r\n private static _blitVertexLayout: Nullable<VertexLayout> = null;\r\n /**\r\n * Creates an instance of Compositor\r\n */\r\n constructor() {\r\n this._postEffects = [];\r\n this._postEffects[PostEffectLayer.opaque] = [];\r\n this._postEffects[PostEffectLayer.transparent] = [];\r\n this._postEffects[PostEffectLayer.end] = [];\r\n this._finalFramebuffer = null;\r\n this._prevInputTexture = null;\r\n this._prevFrameBuffer = null;\r\n this._textureFormat = 'rgba16f';\r\n }\r\n /** @internal */\r\n requireLinearDepth(ctx: DrawContext) {\r\n for (const list of this._postEffects) {\r\n for (const postEffect of list) {\r\n if (postEffect.get()!.requireLinearDepthTexture(ctx)) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n /**\r\n * Adds a posteffect\r\n *\r\n * @param postEffect - The post effect to add\r\n * @param opaque - true if the post effect should be applied after the opaque pass and before the transparent pass, otherwise the post effect should be applied after the transparent pass\r\n */\r\n appendPostEffect(postEffect: AbstractPostEffect) {\r\n if (postEffect) {\r\n for (const list of this._postEffects) {\r\n if (list.findIndex((val) => val.get() === postEffect) >= 0) {\r\n console.error(`Posteffect cannot be added to same compositor multiple times`);\r\n return;\r\n }\r\n }\r\n this._postEffects[postEffect.layer].push(new DRef(postEffect));\r\n }\r\n }\r\n /**\r\n * Removes a posteffect that was previously added\r\n *\r\n * @param postEffect - The posteffect to be remove.\r\n */\r\n removePostEffect(postEffect: AbstractPostEffect) {\r\n for (const list of this._postEffects) {\r\n const index = list.findIndex((val) => val.get() === postEffect);\r\n if (index >= 0) {\r\n list[index].dispose();\r\n list.splice(index, 1);\r\n return;\r\n }\r\n }\r\n }\r\n /**\r\n * Removes all post effects\r\n */\r\n clear() {\r\n for (const list of this._postEffects) {\r\n for (const p of list) {\r\n p.dispose();\r\n }\r\n list.splice(0, list.length);\r\n }\r\n }\r\n /** @internal */\r\n begin(ctx: DrawContext) {\r\n const device = ctx.device;\r\n this._textureFormat =\r\n ctx.camera.HDR && device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer\r\n ? 'rgba16f'\r\n : 'rgba8unorm';\r\n this._finalFramebuffer = device.getFramebuffer();\r\n if (this._postEffects.every((list) => list.length === 0)) {\r\n return;\r\n }\r\n const depth = this._finalFramebuffer?.getDepthAttachment() as Texture2D;\r\n const w = depth ? depth.width : device.getDrawingBufferWidth();\r\n const h = depth ? depth.height : device.getDrawingBufferHeight();\r\n const attachments: any[] = [this._textureFormat];\r\n if (ctx.materialFlags & MaterialVaryingFlags.SSR_STORE_ROUGHNESS) {\r\n attachments.push(ctx.SSRRoughnessTexture!, ctx.SSRNormalTexture!);\r\n } else if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_NORMAL) {\r\n attachments.push(ctx.SSRNormalTexture!);\r\n }\r\n if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_PROFILE) {\r\n attachments.push(ctx.SSSProfileTexture!, ctx.SSSParamTexture!);\r\n }\r\n if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_DIFFUSE) {\r\n attachments.push(ctx.SSSDiffuseTexture!);\r\n }\r\n if (ctx.materialFlags & MaterialVaryingFlags.SSS_STORE_TRANSMISSION) {\r\n attachments.push(ctx.SSSTransmissionTexture!);\r\n }\r\n if (ctx.materialFlags & MaterialVaryingFlags.SKIN_SSS_STORE) {\r\n attachments.push(ctx.SkinSSSTexture!);\r\n }\r\n const tmpFramebuffer = device.pool.fetchTemporalFramebuffer(\r\n true,\r\n w,\r\n h,\r\n attachments.length === 1 ? attachments[0] : attachments,\r\n depth ?? ctx.depthFormat\r\n );\r\n device.setFramebuffer(tmpFramebuffer);\r\n }\r\n /** @internal */\r\n drawPostEffects(ctx: DrawContext, layer: PostEffectLayer, sceneDepthTexture: Texture2D) {\r\n const postEffects = this._postEffects[layer];\r\n if (postEffects.length > 0) {\r\n const device = ctx.device;\r\n const inputFramebuffer = device.getFramebuffer()!;\r\n const inputTexture = inputFramebuffer!.getColorAttachments()[0] as Texture2D;\r\n let tmpTexture: Nullable<Texture2D> = null;\r\n for (let i = 0; i < postEffects.length; i++) {\r\n const postEffect = postEffects[i].get()!;\r\n if (!postEffect.enabled) {\r\n continue;\r\n }\r\n if (this._prevFrameBuffer) {\r\n device.pool.releaseFrameBuffer(this._prevFrameBuffer);\r\n this._prevFrameBuffer = null;\r\n }\r\n const isLast = this.isLastPostEffect(layer, i);\r\n const finalEffect = isLast && (!postEffect.requireDepthAttachment(ctx) || !!this._finalFramebuffer);\r\n let singleColorFramebuffer: Nullable<FrameBuffer> = null;\r\n if (finalEffect) {\r\n singleColorFramebuffer = this.createSingleColorFramebuffer(\r\n device,\r\n this._finalFramebuffer,\r\n postEffect.requireDepthAttachment(ctx)\r\n );\r\n device.setFramebuffer(singleColorFramebuffer ?? this._finalFramebuffer);\r\n } else {\r\n this._prevFrameBuffer = device.pool.fetchTemporalFramebuffer(\r\n false,\r\n inputFramebuffer.getWidth(),\r\n inputFramebuffer.getHeight(),\r\n this._textureFormat,\r\n inputFramebuffer.getDepthAttachment() ?? null\r\n );\r\n device.setFramebuffer(this._prevFrameBuffer);\r\n }\r\n const inputColorTexture = tmpTexture ?? inputTexture;\r\n try {\r\n postEffect.apply(ctx, inputColorTexture, sceneDepthTexture, !device.getFramebuffer());\r\n } finally {\r\n if (singleColorFramebuffer) {\r\n device.setFramebuffer(this._finalFramebuffer);\r\n device.pool.releaseFrameBuffer(singleColorFramebuffer);\r\n }\r\n }\r\n if (this._prevInputTexture) {\r\n device.pool.releaseTexture(this._prevInputTexture);\r\n this._prevInputTexture = null;\r\n }\r\n if (this._prevFrameBuffer) {\r\n tmpTexture = this._prevFrameBuffer.getColorAttachments()[0] as Texture2D;\r\n device.pool.retainTexture(tmpTexture);\r\n this._prevInputTexture = tmpTexture;\r\n }\r\n }\r\n }\r\n }\r\n /** @internal */\r\n end(ctx: DrawContext) {\r\n const device = ctx.device;\r\n if (device.getFramebuffer() !== this._finalFramebuffer) {\r\n const srcTex = device.getFramebuffer()!.getColorAttachments()[0] as Texture2D;\r\n const singleColorFramebuffer = this.createSingleColorFramebuffer(device, this._finalFramebuffer, false);\r\n device.setFramebuffer(singleColorFramebuffer ?? this._finalFramebuffer);\r\n device.setViewport(null);\r\n device.setScissor(null);\r\n try {\r\n Compositor._blit(device, srcTex, !this._finalFramebuffer);\r\n } finally {\r\n if (singleColorFramebuffer) {\r\n device.setFramebuffer(this._finalFramebuffer);\r\n device.pool.releaseFrameBuffer(singleColorFramebuffer);\r\n }\r\n }\r\n }\r\n if (this._prevInputTexture) {\r\n device.pool.releaseTexture(this._prevInputTexture);\r\n this._prevInputTexture = null;\r\n }\r\n if (this._prevFrameBuffer) {\r\n device.pool.releaseFrameBuffer(this._prevFrameBuffer);\r\n this._prevFrameBuffer = null;\r\n }\r\n }\r\n /** @internal */\r\n private isLastPostEffect(layer: PostEffectLayer, index: number) {\r\n for (let i = layer; i < this._postEffects.length; i++) {\r\n const start = i === layer ? index + 1 : 0;\r\n for (let j = start; j < this._postEffects[i].length; j++) {\r\n if (this._postEffects[i][j].get()!.enabled) {\r\n return false;\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n /** @internal */\r\n private createSingleColorFramebuffer(\r\n device: AbstractDevice,\r\n framebuffer: Nullable<FrameBuffer>,\r\n withDepth: boolean\r\n ) {\r\n const colorAttachment = framebuffer?.getColorAttachments()[0] ?? null;\r\n if (!framebuffer || framebuffer.getColorAttachments().length <= 1 || !colorAttachment) {\r\n return null;\r\n }\r\n return device.pool.fetchTemporalFramebuffer(\r\n false,\r\n 0,\r\n 0,\r\n colorAttachment,\r\n withDepth ? framebuffer.getDepthAttachment() : null,\r\n false\r\n );\r\n }\r\n /** @internal */\r\n static _blit(device: AbstractDevice, srcTex: Texture2D, srgbOutput: boolean) {\r\n if (!this._blitProgram) {\r\n this._blitProgram = device.buildRenderProgram({\r\n vertex(pb) {\r\n this.$inputs.pos = pb.vec2().attrib('position');\r\n this.$outputs.uv = pb.vec2();\r\n this.flip = pb.int().uniform(0);\r\n pb.main(function () {\r\n this.$builtins.position = pb.vec4(this.$inputs.pos, 0, 1);\r\n this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));\r\n this.$if(pb.notEqual(this.flip, 0), function () {\r\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\r\n });\r\n });\r\n },\r\n fragment(pb) {\r\n this.srcTex = pb.tex2D().sampleType('unfilterable-float').uniform(0);\r\n this.srgbOutput = pb.int().uniform(0);\r\n this.$outputs.outColor = pb.vec4();\r\n pb.main(function () {\r\n this.$outputs.outColor = pb.textureSample(this.srcTex, this.$inputs.uv);\r\n this.$if(pb.notEqual(this.srgbOutput, 0), function () {\r\n this.$outputs.outColor = pb.vec4(linearToGamma(this, this.$outputs.outColor.rgb), 1);\r\n });\r\n });\r\n }\r\n })!;\r\n this._blitProgram.name = '@Compositor_blit';\r\n this._blitBindgroup = device.createBindGroup(this._blitProgram.bindGroupLayouts[0]);\r\n this._blitVertexLayout = device.createVertexLayout({\r\n vertexBuffers: [\r\n {\r\n buffer: device.createVertexBuffer(\r\n 'position_f32x2',\r\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1])\r\n )!\r\n }\r\n ]\r\n });\r\n this._blitRenderStates = device.createRenderStateSet();\r\n this._blitRenderStates.useRasterizerState().setCullMode('none');\r\n this._blitRenderStates.useDepthState().enableTest(false).enableWrite(false);\r\n }\r\n this._blitBindgroup!.setTexture('srcTex', srcTex, fetchSampler('clamp_nearest_nomip'));\r\n this._blitBindgroup!.setValue('srgbOutput', srgbOutput ? 1 : 0);\r\n this._blitBindgroup!.setValue('flip', device.type === 'webgpu' && !!device.getFramebuffer() ? 1 : 0);\r\n device.setRenderStates(this._blitRenderStates);\r\n device.setProgram(this._blitProgram);\r\n device.setBindGroup(0, this._blitBindgroup!);\r\n device.setVertexLayout(this._blitVertexLayout);\r\n device.draw('triangle-strip', 0, 4);\r\n }\r\n}\r\n"],"names":["Compositor","_blitProgram","_blitBindgroup","_blitRenderStates","_blitVertexLayout","_postEffects","PostEffectLayer","opaque","transparent","end","_finalFramebuffer","_prevInputTexture","_prevFrameBuffer","_textureFormat","requireLinearDepth","ctx","list","postEffect","get","requireLinearDepthTexture","appendPostEffect","findIndex","val","console","error","layer","push","DRef","removePostEffect","index","dispose","splice","clear","p","length","begin","device","camera","HDR","getDeviceCaps","textureCaps","supportHalfFloatColorBuffer","getFramebuffer","every","depth","getDepthAttachment","w","width","getDrawingBufferWidth","h","height","getDrawingBufferHeight","attachments","materialFlags","MaterialVaryingFlags","SSR_STORE_ROUGHNESS","SSRRoughnessTexture","SSRNormalTexture","SSS_STORE_NORMAL","SSS_STORE_PROFILE","SSSProfileTexture","SSSParamTexture","SSS_STORE_DIFFUSE","SSSDiffuseTexture","SSS_STORE_TRANSMISSION","SSSTransmissionTexture","SKIN_SSS_STORE","SkinSSSTexture","tmpFramebuffer","pool","fetchTemporalFramebuffer","depthFormat","setFramebuffer","drawPostEffects","sceneDepthTexture","postEffects","inputFramebuffer","inputTexture","getColorAttachments","tmpTexture","i","enabled","releaseFrameBuffer","isLast","isLastPostEffect","finalEffect","requireDepthAttachment","singleColorFramebuffer","createSingleColorFramebuffer","getWidth","getHeight","inputColorTexture","apply","releaseTexture","retainTexture","srcTex","setViewport","setScissor","_blit","start","j","framebuffer","withDepth","colorAttachment","srgbOutput","buildRenderProgram","vertex","pb","$inputs","pos","vec2","attrib","$outputs","uv","flip","int","uniform","main","$builtins","position","vec4","add","mul","xy","$if","notEqual","y","neg","fragment","tex2D","sampleType","outColor","textureSample","linearToGamma","rgb","name","createBindGroup","bindGroupLayouts","createVertexLayout","vertexBuffers","buffer","createVertexBuffer","Float32Array","createRenderStateSet","useRasterizerState","setCullMode","useDepthState","enableTest","enableWrite","setTexture","fetchSampler","setValue","type","setRenderStates","setProgram","setBindGroup","setVertexLayout","draw"],"mappings":";;;;;;AA4BA;;;AAGC,IACM,MAAMA,UAAAA,CAAAA;qBAEX,YAAqD;qBAErD,iBAAiD;qBAEjD,iBAA+C;qBAE/C,gBAAgD;qBAEhD,cAAsC;qBAEtC,OAAeC,YAAAA,GAAqC,IAAK;qBAEzD,OAAeC,cAAAA,GAAsC,IAAK;qBAE1D,OAAeC,iBAAAA,GAA8C,IAAK;qBAElE,OAAeC,iBAAAA,GAA4C,IAAK;AAChE;;AAEC,MACD,WAAc,EAAA;QACZ,IAAI,CAACC,YAAY,GAAG,EAAE;AACtB,QAAA,IAAI,CAACA,YAAY,CAACC,gBAAgBC,MAAM,CAAC,GAAG,EAAE;AAC9C,QAAA,IAAI,CAACF,YAAY,CAACC,gBAAgBE,WAAW,CAAC,GAAG,EAAE;AACnD,QAAA,IAAI,CAACH,YAAY,CAACC,gBAAgBG,GAAG,CAAC,GAAG,EAAE;QAC3C,IAAI,CAACC,iBAAiB,GAAG,IAAA;QACzB,IAAI,CAACC,iBAAiB,GAAG,IAAA;QACzB,IAAI,CAACC,gBAAgB,GAAG,IAAA;QACxB,IAAI,CAACC,cAAc,GAAG,SAAA;AACxB;qBAEAC,kBAAmBC,CAAAA,GAAgB,EAAE;AACnC,QAAA,KAAK,MAAMC,IAAAA,IAAQ,IAAI,CAACX,YAAY,CAAE;YACpC,KAAK,MAAMY,cAAcD,IAAM,CAAA;AAC7B,gBAAA,IAAIC,UAAWC,CAAAA,GAAG,EAAIC,CAAAA,yBAAyB,CAACJ,GAAM,CAAA,EAAA;oBACpD,OAAO,IAAA;AACT;AACF;AACF;QACA,OAAO,KAAA;AACT;AACA;;;;;MAMAK,gBAAAA,CAAiBH,UAA8B,EAAE;AAC/C,QAAA,IAAIA,UAAY,EAAA;AACd,YAAA,KAAK,MAAMD,IAAAA,IAAQ,IAAI,CAACX,YAAY,CAAE;gBACpC,IAAIW,IAAAA,CAAKK,SAAS,CAAC,CAACC,MAAQA,GAAIJ,CAAAA,GAAG,EAAOD,KAAAA,UAAAA,CAAAA,IAAe,CAAG,EAAA;AAC1DM,oBAAAA,OAAAA,CAAQC,KAAK,CAAC,CAAC,4DAA4D,CAAC,CAAA;AAC5E,oBAAA;AACF;AACF;YACA,IAAI,CAACnB,YAAY,CAACY,UAAWQ,CAAAA,KAAK,CAAC,CAACC,IAAI,CAAC,IAAIC,IAAKV,CAAAA,UAAAA,CAAAA,CAAAA;AACpD;AACF;AACA;;;;MAKAW,gBAAAA,CAAiBX,UAA8B,EAAE;AAC/C,QAAA,KAAK,MAAMD,IAAAA,IAAQ,IAAI,CAACX,YAAY,CAAE;YACpC,MAAMwB,KAAAA,GAAQb,KAAKK,SAAS,CAAC,CAACC,GAAQA,GAAAA,GAAAA,CAAIJ,GAAG,EAAOD,KAAAA,UAAAA,CAAAA;AACpD,YAAA,IAAIY,SAAS,CAAG,EAAA;gBACdb,IAAI,CAACa,KAAM,CAAA,CAACC,OAAO,EAAA;gBACnBd,IAAKe,CAAAA,MAAM,CAACF,KAAO,EAAA,CAAA,CAAA;AACnB,gBAAA;AACF;AACF;AACF;AACA;;AAEC,MACDG,KAAQ,GAAA;AACN,QAAA,KAAK,MAAMhB,IAAAA,IAAQ,IAAI,CAACX,YAAY,CAAE;YACpC,KAAK,MAAM4B,KAAKjB,IAAM,CAAA;AACpBiB,gBAAAA,CAAAA,CAAEH,OAAO,EAAA;AACX;AACAd,YAAAA,IAAAA,CAAKe,MAAM,CAAC,CAAGf,EAAAA,IAAAA,CAAKkB,MAAM,CAAA;AAC5B;AACF;qBAEAC,KAAMpB,CAAAA,GAAgB,EAAE;QACtB,MAAMqB,MAAAA,GAASrB,IAAIqB,MAAM;AACzB,QAAA,IAAI,CAACvB,cAAc,GACjBE,GAAAA,CAAIsB,MAAM,CAACC,GAAG,IAAIF,MAAAA,CAAOG,aAAa,EAAGC,CAAAA,WAAW,CAACC,2BAA2B,GAC5E,SACA,GAAA,YAAA;AACN,QAAA,IAAI,CAAC/B,iBAAiB,GAAG0B,MAAAA,CAAOM,cAAc,EAAA;QAC9C,IAAI,IAAI,CAACrC,YAAY,CAACsC,KAAK,CAAC,CAAC3B,IAASA,GAAAA,IAAAA,CAAKkB,MAAM,KAAK,CAAI,CAAA,EAAA;AACxD,YAAA;AACF;AACA,QAAA,MAAMU,KAAQ,GAAA,IAAI,CAAClC,iBAAiB,EAAEmC,kBAAAA,EAAAA;AACtC,QAAA,MAAMC,IAAIF,KAAQA,GAAAA,KAAAA,CAAMG,KAAK,GAAGX,OAAOY,qBAAqB,EAAA;AAC5D,QAAA,MAAMC,IAAIL,KAAQA,GAAAA,KAAAA,CAAMM,MAAM,GAAGd,OAAOe,sBAAsB,EAAA;AAC9D,QAAA,MAAMC,WAAqB,GAAA;AAAC,YAAA,IAAI,CAACvC;AAAe,SAAA;AAChD,QAAA,IAAIE,GAAIsC,CAAAA,aAAa,GAAGC,oBAAAA,CAAqBC,mBAAmB,EAAE;AAChEH,YAAAA,WAAAA,CAAY1B,IAAI,CAACX,GAAAA,CAAIyC,mBAAmB,EAAGzC,IAAI0C,gBAAgB,CAAA;AACjE,SAAA,MAAO,IAAI1C,GAAIsC,CAAAA,aAAa,GAAGC,oBAAAA,CAAqBI,gBAAgB,EAAE;YACpEN,WAAY1B,CAAAA,IAAI,CAACX,GAAAA,CAAI0C,gBAAgB,CAAA;AACvC;AACA,QAAA,IAAI1C,GAAIsC,CAAAA,aAAa,GAAGC,oBAAAA,CAAqBK,iBAAiB,EAAE;AAC9DP,YAAAA,WAAAA,CAAY1B,IAAI,CAACX,GAAAA,CAAI6C,iBAAiB,EAAG7C,IAAI8C,eAAe,CAAA;AAC9D;AACA,QAAA,IAAI9C,GAAIsC,CAAAA,aAAa,GAAGC,oBAAAA,CAAqBQ,iBAAiB,EAAE;YAC9DV,WAAY1B,CAAAA,IAAI,CAACX,GAAAA,CAAIgD,iBAAiB,CAAA;AACxC;AACA,QAAA,IAAIhD,GAAIsC,CAAAA,aAAa,GAAGC,oBAAAA,CAAqBU,sBAAsB,EAAE;YACnEZ,WAAY1B,CAAAA,IAAI,CAACX,GAAAA,CAAIkD,sBAAsB,CAAA;AAC7C;AACA,QAAA,IAAIlD,GAAIsC,CAAAA,aAAa,GAAGC,oBAAAA,CAAqBY,cAAc,EAAE;YAC3Dd,WAAY1B,CAAAA,IAAI,CAACX,GAAAA,CAAIoD,cAAc,CAAA;AACrC;QACA,MAAMC,cAAAA,GAAiBhC,OAAOiC,IAAI,CAACC,wBAAwB,CACzD,IAAA,EACAxB,GACAG,CACAG,EAAAA,WAAAA,CAAYlB,MAAM,KAAK,CAAA,GAAIkB,WAAW,CAAC,CAAA,CAAE,GAAGA,WAC5CR,EAAAA,KAAAA,IAAS7B,IAAIwD,WAAW,CAAA;AAE1BnC,QAAAA,MAAAA,CAAOoC,cAAc,CAACJ,cAAAA,CAAAA;AACxB;AACA,qBACAK,eAAgB1D,CAAAA,GAAgB,EAAEU,KAAsB,EAAEiD,iBAA4B,EAAE;AACtF,QAAA,MAAMC,WAAc,GAAA,IAAI,CAACtE,YAAY,CAACoB,KAAM,CAAA;QAC5C,IAAIkD,WAAAA,CAAYzC,MAAM,GAAG,CAAG,EAAA;YAC1B,MAAME,MAAAA,GAASrB,IAAIqB,MAAM;YACzB,MAAMwC,gBAAAA,GAAmBxC,OAAOM,cAAc,EAAA;AAC9C,YAAA,MAAMmC,YAAeD,GAAAA,gBAAAA,CAAkBE,mBAAmB,EAAE,CAAC,CAAE,CAAA;AAC/D,YAAA,IAAIC,UAAkC,GAAA,IAAA;AACtC,YAAA,IAAK,IAAIC,CAAI,GAAA,CAAA,EAAGA,IAAIL,WAAYzC,CAAAA,MAAM,EAAE8C,CAAK,EAAA,CAAA;AAC3C,gBAAA,MAAM/D,UAAa0D,GAAAA,WAAW,CAACK,CAAAA,CAAE,CAAC9D,GAAG,EAAA;gBACrC,IAAI,CAACD,UAAWgE,CAAAA,OAAO,EAAE;AACvB,oBAAA;AACF;gBACA,IAAI,IAAI,CAACrE,gBAAgB,EAAE;AACzBwB,oBAAAA,MAAAA,CAAOiC,IAAI,CAACa,kBAAkB,CAAC,IAAI,CAACtE,gBAAgB,CAAA;oBACpD,IAAI,CAACA,gBAAgB,GAAG,IAAA;AAC1B;AACA,gBAAA,MAAMuE,MAAS,GAAA,IAAI,CAACC,gBAAgB,CAAC3D,KAAOuD,EAAAA,CAAAA,CAAAA;AAC5C,gBAAA,MAAMK,WAAcF,GAAAA,MAAAA,KAAW,CAAClE,UAAWqE,CAAAA,sBAAsB,CAACvE,GAAAA,CAAAA,IAAQ,CAAC,CAAC,IAAI,CAACL,iBAAiB,CAAD;AACjG,gBAAA,IAAI6E,sBAAgD,GAAA,IAAA;AACpD,gBAAA,IAAIF,WAAa,EAAA;oBACfE,sBAAyB,GAAA,IAAI,CAACC,4BAA4B,CACxDpD,MAAAA,EACA,IAAI,CAAC1B,iBAAiB,EACtBO,UAAWqE,CAAAA,sBAAsB,CAACvE,GAAAA,CAAAA,CAAAA;AAEpCqB,oBAAAA,MAAAA,CAAOoC,cAAc,CAACe,sBAA0B,IAAA,IAAI,CAAC7E,iBAAiB,CAAA;iBACjE,MAAA;oBACL,IAAI,CAACE,gBAAgB,GAAGwB,MAAAA,CAAOiC,IAAI,CAACC,wBAAwB,CAC1D,KACAM,EAAAA,gBAAAA,CAAiBa,QAAQ,EACzBb,EAAAA,gBAAAA,CAAiBc,SAAS,EAC1B,EAAA,IAAI,CAAC7E,cAAc,EACnB+D,gBAAiB/B,CAAAA,kBAAkB,EAAM,IAAA,IAAA,CAAA;AAE3CT,oBAAAA,MAAAA,CAAOoC,cAAc,CAAC,IAAI,CAAC5D,gBAAgB,CAAA;AAC7C;AACA,gBAAA,MAAM+E,oBAAoBZ,UAAcF,IAAAA,YAAAA;gBACxC,IAAI;AACF5D,oBAAAA,UAAAA,CAAW2E,KAAK,CAAC7E,GAAAA,EAAK4E,mBAAmBjB,iBAAmB,EAAA,CAACtC,OAAOM,cAAc,EAAA,CAAA;iBAC1E,QAAA;AACR,oBAAA,IAAI6C,sBAAwB,EAAA;AAC1BnD,wBAAAA,MAAAA,CAAOoC,cAAc,CAAC,IAAI,CAAC9D,iBAAiB,CAAA;wBAC5C0B,MAAOiC,CAAAA,IAAI,CAACa,kBAAkB,CAACK,sBAAAA,CAAAA;AACjC;AACF;gBACA,IAAI,IAAI,CAAC5E,iBAAiB,EAAE;AAC1ByB,oBAAAA,MAAAA,CAAOiC,IAAI,CAACwB,cAAc,CAAC,IAAI,CAAClF,iBAAiB,CAAA;oBACjD,IAAI,CAACA,iBAAiB,GAAG,IAAA;AAC3B;gBACA,IAAI,IAAI,CAACC,gBAAgB,EAAE;AACzBmE,oBAAAA,UAAAA,GAAa,IAAI,CAACnE,gBAAgB,CAACkE,mBAAmB,EAAE,CAAC,CAAE,CAAA;oBAC3D1C,MAAOiC,CAAAA,IAAI,CAACyB,aAAa,CAACf,UAAAA,CAAAA;oBAC1B,IAAI,CAACpE,iBAAiB,GAAGoE,UAAAA;AAC3B;AACF;AACF;AACF;qBAEAtE,GAAIM,CAAAA,GAAgB,EAAE;QACpB,MAAMqB,MAAAA,GAASrB,IAAIqB,MAAM;AACzB,QAAA,IAAIA,OAAOM,cAAc,EAAA,KAAO,IAAI,CAAChC,iBAAiB,EAAE;AACtD,YAAA,MAAMqF,SAAS3D,MAAOM,CAAAA,cAAc,GAAIoC,mBAAmB,EAAE,CAAC,CAAE,CAAA;YAChE,MAAMS,sBAAAA,GAAyB,IAAI,CAACC,4BAA4B,CAACpD,MAAQ,EAAA,IAAI,CAAC1B,iBAAiB,EAAE,KAAA,CAAA;AACjG0B,YAAAA,MAAAA,CAAOoC,cAAc,CAACe,sBAA0B,IAAA,IAAI,CAAC7E,iBAAiB,CAAA;AACtE0B,YAAAA,MAAAA,CAAO4D,WAAW,CAAC,IAAA,CAAA;AACnB5D,YAAAA,MAAAA,CAAO6D,UAAU,CAAC,IAAA,CAAA;YAClB,IAAI;AACFjG,gBAAAA,UAAAA,CAAWkG,KAAK,CAAC9D,MAAAA,EAAQ2D,QAAQ,CAAC,IAAI,CAACrF,iBAAiB,CAAA;aAChD,QAAA;AACR,gBAAA,IAAI6E,sBAAwB,EAAA;AAC1BnD,oBAAAA,MAAAA,CAAOoC,cAAc,CAAC,IAAI,CAAC9D,iBAAiB,CAAA;oBAC5C0B,MAAOiC,CAAAA,IAAI,CAACa,kBAAkB,CAACK,sBAAAA,CAAAA;AACjC;AACF;AACF;QACA,IAAI,IAAI,CAAC5E,iBAAiB,EAAE;AAC1ByB,YAAAA,MAAAA,CAAOiC,IAAI,CAACwB,cAAc,CAAC,IAAI,CAAClF,iBAAiB,CAAA;YACjD,IAAI,CAACA,iBAAiB,GAAG,IAAA;AAC3B;QACA,IAAI,IAAI,CAACC,gBAAgB,EAAE;AACzBwB,YAAAA,MAAAA,CAAOiC,IAAI,CAACa,kBAAkB,CAAC,IAAI,CAACtE,gBAAgB,CAAA;YACpD,IAAI,CAACA,gBAAgB,GAAG,IAAA;AAC1B;AACF;AACA,qBACA,gBAAQwE,CAAiB3D,KAAsB,EAAEI,KAAa,EAAE;QAC9D,IAAK,IAAImD,CAAIvD,GAAAA,KAAAA,EAAOuD,CAAI,GAAA,IAAI,CAAC3E,YAAY,CAAC6B,MAAM,EAAE8C,CAAK,EAAA,CAAA;AACrD,YAAA,MAAMmB,KAAQnB,GAAAA,CAAAA,KAAMvD,KAAQI,GAAAA,KAAAA,GAAQ,CAAI,GAAA,CAAA;AACxC,YAAA,IAAK,IAAIuE,CAAAA,GAAID,KAAOC,EAAAA,CAAAA,GAAI,IAAI,CAAC/F,YAAY,CAAC2E,CAAE,CAAA,CAAC9C,MAAM,EAAEkE,CAAK,EAAA,CAAA;gBACxD,IAAI,IAAI,CAAC/F,YAAY,CAAC2E,CAAAA,CAAE,CAACoB,CAAAA,CAAE,CAAClF,GAAG,EAAI+D,CAAAA,OAAO,EAAE;oBAC1C,OAAO,KAAA;AACT;AACF;AACF;QACA,OAAO,IAAA;AACT;qBAEA,4BACE7C,CAAAA,MAAsB,EACtBiE,WAAkC,EAClCC,SAAkB,EAClB;AACA,QAAA,MAAMC,eAAkBF,GAAAA,WAAAA,EAAavB,mBAAqB,EAAA,CAAC,EAAE,IAAI,IAAA;QACjE,IAAI,CAACuB,eAAeA,WAAYvB,CAAAA,mBAAmB,GAAG5C,MAAM,IAAI,CAAK,IAAA,CAACqE,eAAiB,EAAA;YACrF,OAAO,IAAA;AACT;AACA,QAAA,OAAOnE,MAAOiC,CAAAA,IAAI,CAACC,wBAAwB,CACzC,KAAA,EACA,CACA,EAAA,CAAA,EACAiC,eACAD,EAAAA,SAAAA,GAAYD,WAAYxD,CAAAA,kBAAkB,KAAK,IAC/C,EAAA,KAAA,CAAA;AAEJ;qBAEA,OAAOqD,KAAM9D,CAAAA,MAAsB,EAAE2D,MAAiB,EAAES,UAAmB,EAAE;AAC3E,QAAA,IAAI,CAAC,IAAI,CAACvG,YAAY,EAAE;AACtB,YAAA,IAAI,CAACA,YAAY,GAAGmC,MAAAA,CAAOqE,kBAAkB,CAAC;AAC5CC,gBAAAA,MAAAA,CAAAA,CAAOC,EAAE,EAAA;oBACP,IAAI,CAACC,OAAO,CAACC,GAAG,GAAGF,EAAGG,CAAAA,IAAI,EAAGC,CAAAA,MAAM,CAAC,UAAA,CAAA;AACpC,oBAAA,IAAI,CAACC,QAAQ,CAACC,EAAE,GAAGN,GAAGG,IAAI,EAAA;AAC1B,oBAAA,IAAI,CAACI,IAAI,GAAGP,GAAGQ,GAAG,EAAA,CAAGC,OAAO,CAAC,CAAA,CAAA;AAC7BT,oBAAAA,EAAAA,CAAGU,IAAI,CAAC,WAAA;AACN,wBAAA,IAAI,CAACC,SAAS,CAACC,QAAQ,GAAGZ,EAAGa,CAAAA,IAAI,CAAC,IAAI,CAACZ,OAAO,CAACC,GAAG,EAAE,CAAG,EAAA,CAAA,CAAA;wBACvD,IAAI,CAACG,QAAQ,CAACC,EAAE,GAAGN,EAAGc,CAAAA,GAAG,CAACd,EAAAA,CAAGe,GAAG,CAAC,IAAI,CAACd,OAAO,CAACC,GAAG,CAACc,EAAE,EAAE,GAAA,CAAA,EAAMhB,EAAGG,CAAAA,IAAI,CAAC,GAAA,CAAA,CAAA;wBACpE,IAAI,CAACc,GAAG,CAACjB,EAAGkB,CAAAA,QAAQ,CAAC,IAAI,CAACX,IAAI,EAAE,CAAI,CAAA,EAAA,WAAA;AAClC,4BAAA,IAAI,CAACI,SAAS,CAACC,QAAQ,CAACO,CAAC,GAAGnB,EAAAA,CAAGoB,GAAG,CAAC,IAAI,CAACT,SAAS,CAACC,QAAQ,CAACO,CAAC,CAAA;AAC9D,yBAAA,CAAA;AACF,qBAAA,CAAA;AACF,iBAAA;AACAE,gBAAAA,QAAAA,CAAAA,CAASrB,EAAE,EAAA;oBACT,IAAI,CAACZ,MAAM,GAAGY,EAAGsB,CAAAA,KAAK,GAAGC,UAAU,CAAC,oBAAsBd,CAAAA,CAAAA,OAAO,CAAC,CAAA,CAAA;AAClE,oBAAA,IAAI,CAACZ,UAAU,GAAGG,GAAGQ,GAAG,EAAA,CAAGC,OAAO,CAAC,CAAA,CAAA;AACnC,oBAAA,IAAI,CAACJ,QAAQ,CAACmB,QAAQ,GAAGxB,GAAGa,IAAI,EAAA;AAChCb,oBAAAA,EAAAA,CAAGU,IAAI,CAAC,WAAA;AACN,wBAAA,IAAI,CAACL,QAAQ,CAACmB,QAAQ,GAAGxB,GAAGyB,aAAa,CAAC,IAAI,CAACrC,MAAM,EAAE,IAAI,CAACa,OAAO,CAACK,EAAE,CAAA;wBACtE,IAAI,CAACW,GAAG,CAACjB,EAAGkB,CAAAA,QAAQ,CAAC,IAAI,CAACrB,UAAU,EAAE,CAAI,CAAA,EAAA,WAAA;AACxC,4BAAA,IAAI,CAACQ,QAAQ,CAACmB,QAAQ,GAAGxB,EAAAA,CAAGa,IAAI,CAACa,aAAAA,CAAc,IAAI,EAAE,IAAI,CAACrB,QAAQ,CAACmB,QAAQ,CAACG,GAAG,CAAG,EAAA,CAAA,CAAA;AACpF,yBAAA,CAAA;AACF,qBAAA,CAAA;AACF;AACF,aAAA,CAAA;AACA,YAAA,IAAI,CAACrI,YAAY,CAACsI,IAAI,GAAG,kBAAA;AACzB,YAAA,IAAI,CAACrI,cAAc,GAAGkC,MAAAA,CAAOoG,eAAe,CAAC,IAAI,CAACvI,YAAY,CAACwI,gBAAgB,CAAC,CAAE,CAAA,CAAA;AAClF,YAAA,IAAI,CAACrI,iBAAiB,GAAGgC,MAAAA,CAAOsG,kBAAkB,CAAC;gBACjDC,aAAe,EAAA;AACb,oBAAA;AACEC,wBAAAA,MAAAA,EAAQxG,MAAOyG,CAAAA,kBAAkB,CAC/B,gBAAA,EACA,IAAIC,YAAa,CAAA;4BAAC,EAAC;4BAAG,EAAC;AAAG,4BAAA,CAAA;4BAAG,EAAC;4BAAG,EAAC;AAAG,4BAAA,CAAA;AAAG,4BAAA,CAAA;AAAG,4BAAA;AAAE,yBAAA,CAAA;AAEjD;AACD;AACH,aAAA,CAAA;AACA,YAAA,IAAI,CAAC3I,iBAAiB,GAAGiC,MAAAA,CAAO2G,oBAAoB,EAAA;AACpD,YAAA,IAAI,CAAC5I,iBAAiB,CAAC6I,kBAAkB,EAAA,CAAGC,WAAW,CAAC,MAAA,CAAA;YACxD,IAAI,CAAC9I,iBAAiB,CAAC+I,aAAa,GAAGC,UAAU,CAAC,KAAOC,CAAAA,CAAAA,WAAW,CAAC,KAAA,CAAA;AACvE;AACA,QAAA,IAAI,CAAClJ,cAAc,CAAEmJ,UAAU,CAAC,QAAA,EAAUtD,QAAQuD,YAAa,CAAA,qBAAA,CAAA,CAAA;AAC/D,QAAA,IAAI,CAACpJ,cAAc,CAAEqJ,QAAQ,CAAC,YAAA,EAAc/C,aAAa,CAAI,GAAA,CAAA,CAAA;AAC7D,QAAA,IAAI,CAACtG,cAAc,CAAEqJ,QAAQ,CAAC,MAAQnH,EAAAA,MAAAA,CAAOoH,IAAI,KAAK,YAAY,CAAC,CAACpH,MAAOM,CAAAA,cAAc,KAAK,CAAI,GAAA,CAAA,CAAA;AAClGN,QAAAA,MAAAA,CAAOqH,eAAe,CAAC,IAAI,CAACtJ,iBAAiB,CAAA;AAC7CiC,QAAAA,MAAAA,CAAOsH,UAAU,CAAC,IAAI,CAACzJ,YAAY,CAAA;AACnCmC,QAAAA,MAAAA,CAAOuH,YAAY,CAAC,CAAG,EAAA,IAAI,CAACzJ,cAAc,CAAA;AAC1CkC,QAAAA,MAAAA,CAAOwH,eAAe,CAAC,IAAI,CAACxJ,iBAAiB,CAAA;QAC7CgC,MAAOyH,CAAAA,IAAI,CAAC,gBAAA,EAAkB,CAAG,EAAA,CAAA,CAAA;AACnC;AACF;;;;"}
1
+ {"version":3,"file":"compositor.js","sources":["../../src/posteffect/compositor.ts"],"sourcesContent":["import type { DrawContext } from '../render';\r\nimport type { Texture2D, TextureFormat } from '@zephyr3d/device';\r\nimport type { AbstractPostEffect, PostEffectHistoryRead, PostEffectSetupContext } from './posteffect';\r\nimport { PostEffectLayer } from './posteffect';\r\nimport type { Nullable } from '@zephyr3d/base';\r\nimport { DRef } from '@zephyr3d/base';\r\nimport type { RenderGraph } from '../render/rendergraph/rendergraph';\r\nimport type { RGHandle } from '../render/rendergraph/types';\r\nimport type { RGBlackboard } from '../render/rendergraph/blackboard';\r\nimport type { HistoryResourceManager } from '../render/rendergraph/history_resource_manager';\r\n\r\n/**\r\n * Options for building a post effect layer as render graph passes.\r\n * @public\r\n */\r\nexport interface CompositorBuildLayerOptions {\r\n /** The render graph being built. */\r\n graph: RenderGraph;\r\n /** Frame draw context. */\r\n ctx: DrawContext;\r\n /** The layer to build. */\r\n layer: PostEffectLayer;\r\n /** Named frame resources. */\r\n blackboard: RGBlackboard;\r\n /** Chain input color handle. */\r\n input: RGHandle;\r\n /**\r\n * Direct final target for the last effect of the chain, or null to always\r\n * end the chain in an intermediate texture. Pass the imported backbuffer\r\n * handle together with isScreen=false when rendering into a framebuffer,\r\n * or isScreen=true when the final target is the device default framebuffer.\r\n */\r\n finalOutput?: Nullable<{ handle: RGHandle; isScreen: boolean }>;\r\n /**\r\n * True when the chain input physically resides in the final target (final\r\n * framebuffer used as scene intermediate). An effect whose input is the\r\n * final target must never direct-write it — sampling and rendering the same\r\n * texture in one pass is a feedback loop.\r\n */\r\n inputResidesInFinalTarget?: boolean;\r\n /**\r\n * Depth attachment for intermediate effect outputs that request one:\r\n * either a graph texture handle or a backend depth texture.\r\n */\r\n sceneDepthAttachment?: unknown;\r\n /** Ordering/lifetime dependencies declared by every effect pass. */\r\n dependencies?: RGHandle[];\r\n /** History bindings kept in a read scope while effects execute. */\r\n historyReads?: PostEffectHistoryRead[];\r\n /** Cross-frame history resource manager. */\r\n history?: Nullable<HistoryResourceManager<Texture2D>>;\r\n}\r\n\r\n/**\r\n * Result of {@link Compositor.buildLayer}.\r\n * @public\r\n */\r\nexport interface CompositorBuildLayerResult {\r\n /** Chain output color handle. Equals the input when no effect is enabled. */\r\n color: RGHandle;\r\n /** True when the last effect wrote the final target directly. */\r\n wroteFinal: boolean;\r\n}\r\n\r\n/**\r\n * Post processing compositor\r\n * @public\r\n */\r\nexport class Compositor {\r\n /** @internal */\r\n protected _postEffects: DRef<AbstractPostEffect>[][];\r\n /**\r\n * Creates an instance of Compositor\r\n */\r\n constructor() {\r\n this._postEffects = [];\r\n this._postEffects[PostEffectLayer.opaque] = [];\r\n this._postEffects[PostEffectLayer.transparent] = [];\r\n this._postEffects[PostEffectLayer.end] = [];\r\n }\r\n /** @internal */\r\n layerHasEnabledEffect(layer: PostEffectLayer): boolean {\r\n return this._postEffects[layer].some((ref) => !!ref.get()?.enabled);\r\n }\r\n /** @internal */\r\n private getIntermediateFormat(ctx: DrawContext): TextureFormat {\r\n return ctx.camera.HDR && ctx.device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer\r\n ? 'rgba16f'\r\n : 'rgba8unorm';\r\n }\r\n /**\r\n * Build the enabled effects of a layer as render graph passes.\r\n *\r\n * Effects are chained through graph texture handles: each effect's setup()\r\n * declares its passes reading the previous output. Where each effect output\r\n * lands (intermediate texture or the final target) is decided here through\r\n * the {@link PostEffectSetupContext.createOutput} implementation, so effect\r\n * code never handles final-target selection.\r\n *\r\n * @param options - Build inputs.\r\n * @returns The chain output handle and whether the final target was written directly.\r\n */\r\n buildLayer(options: CompositorBuildLayerOptions): CompositorBuildLayerResult {\r\n const { graph, ctx, layer, blackboard, input } = options;\r\n const effects = this._postEffects[layer]\r\n .map((ref) => ref.get())\r\n .filter((effect): effect is AbstractPostEffect => !!effect && effect.enabled);\r\n if (effects.length === 0) {\r\n return { color: input, wroteFinal: false };\r\n }\r\n const colorFormat = this.getIntermediateFormat(ctx);\r\n const finalOutput = options.finalOutput ?? null;\r\n const history = options.history ?? null;\r\n const dependencies = options.dependencies ?? [];\r\n const historyReads = options.historyReads ?? [];\r\n const sceneDepthAttachment = options.sceneDepthAttachment ?? null;\r\n const inputResidesInFinalTarget = !!options.inputResidesInFinalTarget;\r\n const width = ctx.renderWidth;\r\n const height = ctx.renderHeight;\r\n let chain = input;\r\n let wroteFinal = false;\r\n for (let i = 0; i < effects.length; i++) {\r\n const effect = effects[i];\r\n const isLast = i === effects.length - 1;\r\n // An effect that samples the final target's texture must not render into\r\n // it in the same pass (feedback loop); force an intermediate output.\r\n const inputIsFinalTarget = inputResidesInFinalTarget && chain === input;\r\n const label = `PostEffect:${effect.constructor.name}`;\r\n const setupContext: PostEffectSetupContext = {\r\n graph,\r\n ctx,\r\n blackboard,\r\n input: chain,\r\n colorFormat,\r\n width,\r\n height,\r\n history,\r\n sceneDepthAttachment,\r\n dependencies,\r\n historyReads,\r\n createOutput(builder, opts) {\r\n const needDepthAttachment = !!opts?.needDepthAttachment;\r\n // Direct write to the final target is only allowed for the last effect\r\n // of the chain, only when the effect does not depth-test against\r\n // scene depth (the final target does not carry the scene depth\r\n // buffer), and only when the effect does not sample the final\r\n // target's own texture as its input.\r\n if (isLast && finalOutput && !needDepthAttachment && !inputIsFinalTarget) {\r\n wroteFinal = true;\r\n const color = builder.write(finalOutput.handle);\r\n if (finalOutput.isScreen) {\r\n // Device default framebuffer: not a graph resource; the effect\r\n // must gamma-correct since the screen is sRGB.\r\n return { color, framebuffer: null, srgbOutput: true };\r\n }\r\n const framebuffer = builder.createFramebuffer({\r\n label: `${label}:finalFB`,\r\n width,\r\n height,\r\n colorAttachments: color,\r\n depthAttachment: null\r\n });\r\n return { color, framebuffer, srgbOutput: false };\r\n }\r\n const color = builder.createTexture({ format: colorFormat, label: `${label}:out` });\r\n const framebuffer = builder.createFramebuffer({\r\n label: `${label}:outFB`,\r\n width,\r\n height,\r\n colorAttachments: color,\r\n depthAttachment: needDepthAttachment ? sceneDepthAttachment : null,\r\n ignoreDepthStencil: !needDepthAttachment\r\n });\r\n return { color, framebuffer, srgbOutput: false };\r\n }\r\n };\r\n chain = effect.setup(setupContext);\r\n }\r\n return { color: chain, wroteFinal };\r\n }\r\n /**\r\n * Adds a posteffect\r\n *\r\n * @param postEffect - The post effect to add\r\n * @param opaque - true if the post effect should be applied after the opaque pass and before the transparent pass, otherwise the post effect should be applied after the transparent pass\r\n */\r\n appendPostEffect(postEffect: AbstractPostEffect) {\r\n if (postEffect) {\r\n for (const list of this._postEffects) {\r\n if (list.findIndex((val) => val.get() === postEffect) >= 0) {\r\n console.error(`Posteffect cannot be added to same compositor multiple times`);\r\n return;\r\n }\r\n }\r\n this._postEffects[postEffect.layer].push(new DRef(postEffect));\r\n }\r\n }\r\n /**\r\n * Removes a posteffect that was previously added\r\n *\r\n * @param postEffect - The posteffect to be remove.\r\n */\r\n removePostEffect(postEffect: AbstractPostEffect) {\r\n for (const list of this._postEffects) {\r\n const index = list.findIndex((val) => val.get() === postEffect);\r\n if (index >= 0) {\r\n list[index].dispose();\r\n list.splice(index, 1);\r\n return;\r\n }\r\n }\r\n }\r\n /**\r\n * Removes all post effects\r\n */\r\n clear() {\r\n for (const list of this._postEffects) {\r\n for (const p of list) {\r\n p.dispose();\r\n }\r\n list.splice(0, list.length);\r\n }\r\n }\r\n}\r\n"],"names":["Compositor","_postEffects","PostEffectLayer","opaque","transparent","end","layerHasEnabledEffect","layer","some","ref","get","enabled","getIntermediateFormat","ctx","camera","HDR","device","getDeviceCaps","textureCaps","supportHalfFloatColorBuffer","buildLayer","options","graph","blackboard","input","effects","map","filter","effect","length","color","wroteFinal","colorFormat","finalOutput","history","dependencies","historyReads","sceneDepthAttachment","inputResidesInFinalTarget","width","renderWidth","height","renderHeight","chain","i","isLast","inputIsFinalTarget","label","name","setupContext","createOutput","builder","opts","needDepthAttachment","write","handle","isScreen","framebuffer","srgbOutput","createFramebuffer","colorAttachments","depthAttachment","createTexture","format","ignoreDepthStencil","setup","appendPostEffect","postEffect","list","findIndex","val","console","error","push","DRef","removePostEffect","index","dispose","splice","clear","p"],"mappings":"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"}
@@ -31,6 +31,9 @@ import { Vector2 } from '@zephyr3d/base';
31
31
  /** {@inheritDoc AbstractPostEffect.requireDepthAttachment} */ requireDepthAttachment() {
32
32
  return false;
33
33
  }
34
+ /** {@inheritDoc AbstractPostEffect.requireMotionVectorTexture} */ requireMotionVectorTexture() {
35
+ return true;
36
+ }
34
37
  /** {@inheritDoc AbstractPostEffect.apply} */ apply(ctx, inputColorTexture, sceneDepthTexture, srgbOutput) {
35
38
  const device = ctx.device;
36
39
  this._prepare(device);
@@ -1 +1 @@
1
- {"version":3,"file":"motionblur.js","sources":["../../src/posteffect/motionblur.ts"],"sourcesContent":["import { AbstractPostEffect, PostEffectLayer } from './posteffect';\r\nimport { linearToGamma } from '../shaders/misc';\r\nimport type { AbstractDevice, BindGroup, GPUProgram, Texture2D } from '@zephyr3d/device';\r\nimport type { DrawContext } from '../render';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport type { Nullable } from '@zephyr3d/base';\r\nimport { Vector2 } from '@zephyr3d/base';\r\n\r\n/**\r\n * The motion blur post effect\r\n * @public\r\n */\r\nexport class MotionBlur extends AbstractPostEffect {\r\n private static _programMotionBlur: Nullable<GPUProgram> = null;\r\n private static _bindgroupMotionBlur: Nullable<BindGroup> = null;\r\n /** @internal */\r\n private _intensity: number;\r\n /** @internal */\r\n private _aspect: Vector2;\r\n /**\r\n * Creates an instance of tonemap post effect\r\n */\r\n constructor() {\r\n super();\r\n this._intensity = 1;\r\n this._aspect = new Vector2();\r\n this._layer = PostEffectLayer.transparent;\r\n }\r\n /** Motion blur strength */\r\n get strength() {\r\n return this._intensity;\r\n }\r\n set strength(val: number) {\r\n this._intensity = val;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.requireLinearDepthTexture} */\r\n requireLinearDepthTexture() {\r\n return false;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.requireDepthAttachment} */\r\n requireDepthAttachment() {\r\n return false;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.apply} */\r\n apply(ctx: DrawContext, inputColorTexture: Texture2D, sceneDepthTexture: Texture2D, srgbOutput: boolean) {\r\n const device = ctx.device;\r\n this._prepare(device);\r\n this._aspect.setXY(inputColorTexture.width / inputColorTexture.height, 1);\r\n MotionBlur._bindgroupMotionBlur!.setTexture(\r\n 'inputTexture',\r\n inputColorTexture,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n MotionBlur._bindgroupMotionBlur!.setTexture(\r\n 'motionVectorTexture',\r\n ctx.motionVectorTexture!,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n MotionBlur._bindgroupMotionBlur!.setValue('flip', this.needFlip(device) ? 1 : 0);\r\n MotionBlur._bindgroupMotionBlur!.setValue('srgbOut', srgbOutput ? 1 : 0);\r\n MotionBlur._bindgroupMotionBlur!.setValue('frameDeltaTime', device.frameInfo.elapsedFrame);\r\n MotionBlur._bindgroupMotionBlur!.setValue('intensity', this._intensity);\r\n MotionBlur._bindgroupMotionBlur!.setValue('aspect', this._aspect);\r\n device.setProgram(MotionBlur._programMotionBlur);\r\n device.setBindGroup(0, MotionBlur._bindgroupMotionBlur!);\r\n this.drawFullscreenQuad();\r\n }\r\n /** @internal */\r\n private _prepare(device: AbstractDevice) {\r\n if (!MotionBlur._programMotionBlur) {\r\n MotionBlur._programMotionBlur = device.buildRenderProgram({\r\n vertex(pb) {\r\n this.flip = pb.int().uniform(0);\r\n this.$inputs.pos = pb.vec2().attrib('position');\r\n this.$outputs.uv = pb.vec2();\r\n pb.main(function () {\r\n this.$builtins.position = pb.vec4(this.$inputs.pos, 0, 1);\r\n this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));\r\n this.$if(pb.notEqual(this.flip, 0), function () {\r\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\r\n });\r\n });\r\n },\r\n fragment(pb) {\r\n this.srgbOut = pb.int().uniform(0);\r\n this.frameDeltaTime = pb.float().uniform(0);\r\n this.inputTexture = pb.tex2D().uniform(0);\r\n this.motionVectorTexture = pb.tex2D().uniform(0);\r\n this.intensity = pb.float().uniform(0);\r\n this.aspect = pb.vec2().uniform(0);\r\n this.$outputs.outColor = pb.vec4();\r\n pb.main(function () {\r\n this.$l.color = pb.vec3();\r\n this.$l.velocity = pb.textureSampleLevel(this.motionVectorTexture, this.$inputs.uv, 0).xy;\r\n this.velocity = pb.div(pb.mul(this.velocity, 0.5), this.aspect);\r\n this.$l.sourceSample = pb.textureSampleLevel(this.inputTexture, this.$inputs.uv, 0);\r\n this.$l.color = this.sourceSample.rgb;\r\n this.$if(pb.greaterThan(pb.dot(this.velocity, this.velocity), 1e-7), function () {\r\n this.velocity = pb.mul(this.velocity, this.intensity, this.frameDeltaTime);\r\n this.$l.uv0 = pb.clamp(pb.sub(this.$inputs.uv, this.velocity), pb.vec2(0), pb.vec2(1));\r\n this.$l.uv1 = pb.clamp(pb.add(this.$inputs.uv, this.velocity), pb.vec2(0), pb.vec2(1));\r\n const NUM_SAMPLES = 17;\r\n this.$for(pb.float('i'), 0, NUM_SAMPLES, function () {\r\n this.$l.t = pb.div(this.i, NUM_SAMPLES - 1);\r\n this.color = pb.add(\r\n this.color,\r\n pb.textureSampleLevel(this.inputTexture, pb.mix(this.uv0, this.uv1, this.t), 0).rgb\r\n );\r\n });\r\n this.color = pb.mul(this.color, 1 / NUM_SAMPLES);\r\n });\r\n //this.color = pb.vec3(this.velocity, 0);\r\n this.$if(pb.notEqual(this.srgbOut, 0), function () {\r\n this.color = linearToGamma(this, this.color);\r\n });\r\n this.$outputs.outColor = pb.vec4(this.color, this.sourceSample.a);\r\n });\r\n }\r\n })!;\r\n MotionBlur._programMotionBlur.name = '@MotionBlur';\r\n MotionBlur._bindgroupMotionBlur = device.createBindGroup(\r\n MotionBlur._programMotionBlur.bindGroupLayouts[0]\r\n );\r\n console.log(MotionBlur._programMotionBlur.getShaderSource('fragment'));\r\n }\r\n }\r\n}\r\n"],"names":["MotionBlur","AbstractPostEffect","_programMotionBlur","_bindgroupMotionBlur","_intensity","_aspect","Vector2","_layer","PostEffectLayer","transparent","strength","val","requireLinearDepthTexture","requireDepthAttachment","apply","ctx","inputColorTexture","sceneDepthTexture","srgbOutput","device","_prepare","setXY","width","height","setTexture","fetchSampler","motionVectorTexture","setValue","needFlip","frameInfo","elapsedFrame","setProgram","setBindGroup","drawFullscreenQuad","buildRenderProgram","vertex","pb","flip","int","uniform","$inputs","pos","vec2","attrib","$outputs","uv","main","$builtins","position","vec4","add","mul","xy","$if","notEqual","y","neg","fragment","srgbOut","frameDeltaTime","float","inputTexture","tex2D","intensity","aspect","outColor","$l","color","vec3","velocity","textureSampleLevel","div","sourceSample","rgb","greaterThan","dot","uv0","clamp","sub","uv1","NUM_SAMPLES","$for","t","i","mix","linearToGamma","a","name","createBindGroup","bindGroupLayouts","console","log","getShaderSource"],"mappings":"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"}
1
+ {"version":3,"file":"motionblur.js","sources":["../../src/posteffect/motionblur.ts"],"sourcesContent":["import { AbstractPostEffect, PostEffectLayer } from './posteffect';\r\nimport { linearToGamma } from '../shaders/misc';\r\nimport type { AbstractDevice, BindGroup, GPUProgram, Texture2D } from '@zephyr3d/device';\r\nimport type { DrawContext } from '../render';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport type { Nullable } from '@zephyr3d/base';\r\nimport { Vector2 } from '@zephyr3d/base';\r\n\r\n/**\r\n * The motion blur post effect\r\n * @public\r\n */\r\nexport class MotionBlur extends AbstractPostEffect {\r\n private static _programMotionBlur: Nullable<GPUProgram> = null;\r\n private static _bindgroupMotionBlur: Nullable<BindGroup> = null;\r\n /** @internal */\r\n private _intensity: number;\r\n /** @internal */\r\n private _aspect: Vector2;\r\n /**\r\n * Creates an instance of tonemap post effect\r\n */\r\n constructor() {\r\n super();\r\n this._intensity = 1;\r\n this._aspect = new Vector2();\r\n this._layer = PostEffectLayer.transparent;\r\n }\r\n /** Motion blur strength */\r\n get strength() {\r\n return this._intensity;\r\n }\r\n set strength(val: number) {\r\n this._intensity = val;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.requireLinearDepthTexture} */\r\n requireLinearDepthTexture() {\r\n return false;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.requireDepthAttachment} */\r\n requireDepthAttachment() {\r\n return false;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.requireMotionVectorTexture} */\r\n requireMotionVectorTexture() {\r\n return true;\r\n }\r\n /** {@inheritDoc AbstractPostEffect.apply} */\r\n apply(ctx: DrawContext, inputColorTexture: Texture2D, sceneDepthTexture: Texture2D, srgbOutput: boolean) {\r\n const device = ctx.device;\r\n this._prepare(device);\r\n this._aspect.setXY(inputColorTexture.width / inputColorTexture.height, 1);\r\n MotionBlur._bindgroupMotionBlur!.setTexture(\r\n 'inputTexture',\r\n inputColorTexture,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n MotionBlur._bindgroupMotionBlur!.setTexture(\r\n 'motionVectorTexture',\r\n ctx.motionVectorTexture!,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n MotionBlur._bindgroupMotionBlur!.setValue('flip', this.needFlip(device) ? 1 : 0);\r\n MotionBlur._bindgroupMotionBlur!.setValue('srgbOut', srgbOutput ? 1 : 0);\r\n MotionBlur._bindgroupMotionBlur!.setValue('frameDeltaTime', device.frameInfo.elapsedFrame);\r\n MotionBlur._bindgroupMotionBlur!.setValue('intensity', this._intensity);\r\n MotionBlur._bindgroupMotionBlur!.setValue('aspect', this._aspect);\r\n device.setProgram(MotionBlur._programMotionBlur);\r\n device.setBindGroup(0, MotionBlur._bindgroupMotionBlur!);\r\n this.drawFullscreenQuad();\r\n }\r\n /** @internal */\r\n private _prepare(device: AbstractDevice) {\r\n if (!MotionBlur._programMotionBlur) {\r\n MotionBlur._programMotionBlur = device.buildRenderProgram({\r\n vertex(pb) {\r\n this.flip = pb.int().uniform(0);\r\n this.$inputs.pos = pb.vec2().attrib('position');\r\n this.$outputs.uv = pb.vec2();\r\n pb.main(function () {\r\n this.$builtins.position = pb.vec4(this.$inputs.pos, 0, 1);\r\n this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));\r\n this.$if(pb.notEqual(this.flip, 0), function () {\r\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\r\n });\r\n });\r\n },\r\n fragment(pb) {\r\n this.srgbOut = pb.int().uniform(0);\r\n this.frameDeltaTime = pb.float().uniform(0);\r\n this.inputTexture = pb.tex2D().uniform(0);\r\n this.motionVectorTexture = pb.tex2D().uniform(0);\r\n this.intensity = pb.float().uniform(0);\r\n this.aspect = pb.vec2().uniform(0);\r\n this.$outputs.outColor = pb.vec4();\r\n pb.main(function () {\r\n this.$l.color = pb.vec3();\r\n this.$l.velocity = pb.textureSampleLevel(this.motionVectorTexture, this.$inputs.uv, 0).xy;\r\n this.velocity = pb.div(pb.mul(this.velocity, 0.5), this.aspect);\r\n this.$l.sourceSample = pb.textureSampleLevel(this.inputTexture, this.$inputs.uv, 0);\r\n this.$l.color = this.sourceSample.rgb;\r\n this.$if(pb.greaterThan(pb.dot(this.velocity, this.velocity), 1e-7), function () {\r\n this.velocity = pb.mul(this.velocity, this.intensity, this.frameDeltaTime);\r\n this.$l.uv0 = pb.clamp(pb.sub(this.$inputs.uv, this.velocity), pb.vec2(0), pb.vec2(1));\r\n this.$l.uv1 = pb.clamp(pb.add(this.$inputs.uv, this.velocity), pb.vec2(0), pb.vec2(1));\r\n const NUM_SAMPLES = 17;\r\n this.$for(pb.float('i'), 0, NUM_SAMPLES, function () {\r\n this.$l.t = pb.div(this.i, NUM_SAMPLES - 1);\r\n this.color = pb.add(\r\n this.color,\r\n pb.textureSampleLevel(this.inputTexture, pb.mix(this.uv0, this.uv1, this.t), 0).rgb\r\n );\r\n });\r\n this.color = pb.mul(this.color, 1 / NUM_SAMPLES);\r\n });\r\n //this.color = pb.vec3(this.velocity, 0);\r\n this.$if(pb.notEqual(this.srgbOut, 0), function () {\r\n this.color = linearToGamma(this, this.color);\r\n });\r\n this.$outputs.outColor = pb.vec4(this.color, this.sourceSample.a);\r\n });\r\n }\r\n })!;\r\n MotionBlur._programMotionBlur.name = '@MotionBlur';\r\n MotionBlur._bindgroupMotionBlur = device.createBindGroup(\r\n MotionBlur._programMotionBlur.bindGroupLayouts[0]\r\n );\r\n console.log(MotionBlur._programMotionBlur.getShaderSource('fragment'));\r\n }\r\n }\r\n}\r\n"],"names":["MotionBlur","AbstractPostEffect","_programMotionBlur","_bindgroupMotionBlur","_intensity","_aspect","Vector2","_layer","PostEffectLayer","transparent","strength","val","requireLinearDepthTexture","requireDepthAttachment","requireMotionVectorTexture","apply","ctx","inputColorTexture","sceneDepthTexture","srgbOutput","device","_prepare","setXY","width","height","setTexture","fetchSampler","motionVectorTexture","setValue","needFlip","frameInfo","elapsedFrame","setProgram","setBindGroup","drawFullscreenQuad","buildRenderProgram","vertex","pb","flip","int","uniform","$inputs","pos","vec2","attrib","$outputs","uv","main","$builtins","position","vec4","add","mul","xy","$if","notEqual","y","neg","fragment","srgbOut","frameDeltaTime","float","inputTexture","tex2D","intensity","aspect","outColor","$l","color","vec3","velocity","textureSampleLevel","div","sourceSample","rgb","greaterThan","dot","uv0","clamp","sub","uv1","NUM_SAMPLES","$for","t","i","mix","linearToGamma","a","name","createBindGroup","bindGroupLayouts","console","log","getShaderSource"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { drawFullscreenQuad } from '../render/fullscreenquad.js';
2
2
  import { copyTexture, fetchSampler } from '../utility/misc.js';
3
3
  import { Disposable } from '@zephyr3d/base';
4
+ import { FrameResources } from '../render/rendergraph/blackboard.js';
4
5
 
5
6
  /**
6
7
  * Rendering layer of post processing effects
@@ -56,6 +57,12 @@ import { Disposable } from '@zephyr3d/base';
56
57
  return false;
57
58
  }
58
59
  /**
60
+ * Checks whether this post effect requires the motion vector texture
61
+ * @returns true if the motion vector texture is required.
62
+ */ requireMotionVectorTexture(_ctx) {
63
+ return false;
64
+ }
65
+ /**
59
66
  * Apply the post effect
60
67
  * @param camera - Camera used the render the scene
61
68
  * @param inputColorTexture - The previous scene color texture
@@ -68,6 +75,78 @@ import { Disposable } from '@zephyr3d/base';
68
75
  this.passThrough(ctx, inputColorTexture, srgbOutput);
69
76
  }
70
77
  /**
78
+ * Declare this effect's passes on the render graph.
79
+ *
80
+ * The default implementation wraps {@link AbstractPostEffect.apply} into a
81
+ * single graph pass, so effects only overriding apply() work unchanged.
82
+ * Multi-pass effects override this method to declare each internal step as
83
+ * its own pass, calling {@link PostEffectSetupContext.createOutput} inside
84
+ * the final pass.
85
+ *
86
+ * @param s - Build-time setup context.
87
+ * @returns The effect's output color handle.
88
+ */ setup(s) {
89
+ return this._setupFromApply(s);
90
+ }
91
+ /**
92
+ * Wraps the legacy apply() entry into a single graph pass.
93
+ * @internal
94
+ */ _setupFromApply(s) {
95
+ const passName = `PostEffect:${this.constructor.name}`;
96
+ return s.graph.addPass(passName, (builder)=>{
97
+ builder.read(s.input);
98
+ for (const dep of s.dependencies){
99
+ builder.read(dep);
100
+ }
101
+ for (const binding of s.historyReads){
102
+ builder.read(binding.handle);
103
+ }
104
+ // Declare reads according to the effect's declared requirements so the
105
+ // executor keeps exactly the textures this effect samples alive. Effects
106
+ // reaching frame textures through DrawContext fields must declare them
107
+ // via requireLinearDepthTexture / requireMotionVectorTexture.
108
+ const linearDepthHandle = this.requireLinearDepthTexture(s.ctx) ? s.blackboard.get(FrameResources.LinearDepth) : null;
109
+ if (linearDepthHandle) {
110
+ builder.read(linearDepthHandle);
111
+ }
112
+ const motionVectorHandle = this.requireMotionVectorTexture(s.ctx) ? s.blackboard.get(FrameResources.MotionVector) : null;
113
+ if (motionVectorHandle) {
114
+ builder.read(motionVectorHandle);
115
+ }
116
+ const output = s.createOutput(builder, {
117
+ needDepthAttachment: this.requireDepthAttachment(s.ctx)
118
+ });
119
+ builder.setExecute((rg)=>{
120
+ const device = s.ctx.device;
121
+ const inputTexture = rg.getTexture(s.input);
122
+ const linearDepthTexture = linearDepthHandle ? rg.getTexture(linearDepthHandle) : s.ctx.linearDepthTexture;
123
+ const applyEffect = ()=>{
124
+ device.pushDeviceStates();
125
+ try {
126
+ device.setFramebuffer(output.framebuffer ? rg.getFramebuffer(output.framebuffer) : null);
127
+ this.apply(s.ctx, inputTexture, linearDepthTexture, output.srgbOutput);
128
+ } finally{
129
+ device.popDeviceStates();
130
+ }
131
+ };
132
+ if (s.history && s.historyReads.length > 0) {
133
+ s.history.beginReadScope(s.historyReads.map((binding)=>({
134
+ name: binding.name,
135
+ texture: rg.getTexture(binding.handle)
136
+ })));
137
+ try {
138
+ applyEffect();
139
+ } finally{
140
+ s.history.endReadScope();
141
+ }
142
+ } else {
143
+ applyEffect();
144
+ }
145
+ });
146
+ return output.color;
147
+ });
148
+ }
149
+ /**
71
150
  *
72
151
  * @param ctx - Draw context
73
152
  * @param inputColorTexture - Input color texture