UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

136 lines (135 loc) 7.61 kB
import { Vector4 } from "../../../../Maths/math.vector.pure.js"; import { ThinCustomPostProcess } from "../../../../PostProcesses/thinCustomPostProcess.js"; import { FrameGraphTask } from "../../../frameGraphTask.js"; /** * Task used to temporally accumulate IBL shadows. * @internal */ export class FrameGraphIblShadowsAccumulationTask extends FrameGraphTask { get remanence() { return this._remanence; } set remanence(value) { this._remanence = Math.max(0, Math.min(value, 1)); } constructor(name, frameGraph) { super(name, frameGraph); this._remanence = 0.75; this.reset = true; this.isMoving = false; this.voxelGridSize = 1; this._accumulationParams = new Vector4(0, 0, 0, 0); this.postProcess = new ThinCustomPostProcess(name, frameGraph.engine, { fragmentShader: "iblShadowAccumulation", uniforms: ["accumulationParameters"], samplers: ["spatialBlurSampler", "oldAccumulationSampler", "prevPositionSampler", "motionSampler", "positionSampler"], shaderLanguage: frameGraph.engine.isWebGPU ? 1 /* ShaderLanguage.WGSL */ : 0 /* ShaderLanguage.GLSL */, }); this._postProcessDrawWrapper = this.postProcess.drawWrapper; this.outputTexture = this._frameGraph.textureManager.createDanglingHandle(); } getClassName() { return "FrameGraphIblShadowsAccumulationTask"; } // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax initAsync() { if (this._frameGraph.engine.isWebGPU) { return import("../../../../ShadersWGSL/iblShadowAccumulation.fragment.js"); } return import("../../../../Shaders/iblShadowAccumulation.fragment.js"); } isReady() { return this.postProcess.isReady(); } record() { if (this.sourceTexture === undefined || this.velocityTexture === undefined || this.positionTexture === undefined) { throw new Error(`FrameGraphIblShadowsAccumulationTask ${this.name}: sourceTexture, velocityTexture and positionTexture are required`); } const textureManager = this._frameGraph.textureManager; const outputSize = textureManager.getTextureAbsoluteDimensions(this.sourceTexture); const positionSize = textureManager.getTextureAbsoluteDimensions(this.positionTexture); const sharedTextureOptions = { createMipMaps: false, samples: 1, formats: [5], useSRGBBuffers: [false], creationFlags: [0], }; const outputCreationOptions = { size: outputSize, sizeIsPercentage: false, isHistoryTexture: false, options: { ...sharedTextureOptions, types: [2], labels: [`${this.name} Output`] }, }; const previousAccumulationCreationOptions = { size: outputSize, sizeIsPercentage: false, isHistoryTexture: false, options: { ...sharedTextureOptions, types: [2], labels: [`${this.name} Previous Accumulation`] }, }; const previousPositionCreationOptions = { size: positionSize, sizeIsPercentage: false, isHistoryTexture: false, options: { ...sharedTextureOptions, types: [2], labels: [`${this.name} Previous Position`] }, }; textureManager.resolveDanglingHandle(this.outputTexture, undefined, `${this.name} Output`, outputCreationOptions); this._previousAccumulationTexture = textureManager.createRenderTargetTexture(`${this.name} Previous Accumulation`, previousAccumulationCreationOptions, this._previousAccumulationTexture); this._previousPositionTexture = textureManager.createRenderTargetTexture(`${this.name} Previous Position`, previousPositionCreationOptions, this._previousPositionTexture); // Pass 1: Accumulate into outputTexture, sampling last frame's accumulation and position. const pass = this._frameGraph.addRenderPass(this.name); pass.addDependencies(this.sourceTexture); pass.addDependencies(this.velocityTexture); pass.addDependencies(this.positionTexture); pass.addDependencies(this._previousAccumulationTexture); pass.addDependencies(this._previousPositionTexture); pass.setRenderTarget(this.outputTexture); pass.setExecuteFunc((context) => { context.setTextureSamplingMode(this.sourceTexture, 1); context.setTextureSamplingMode(this.velocityTexture, 1); context.setTextureSamplingMode(this.positionTexture, 1); const remanence = this.isMoving ? this.remanence : 0.99; this._accumulationParams.set(remanence, this.reset ? 1.0 : 0.0, this.voxelizationTask?.voxelGridSize ?? this.voxelGridSize, 0.0); context.applyFullScreenEffect(this._postProcessDrawWrapper, () => { const effect = this._postProcessDrawWrapper.effect; context.bindTextureHandle(effect, "spatialBlurSampler", this.sourceTexture); context.bindTextureHandle(effect, "oldAccumulationSampler", this._previousAccumulationTexture); context.bindTextureHandle(effect, "prevPositionSampler", this._previousPositionTexture); context.bindTextureHandle(effect, "motionSampler", this.velocityTexture); context.bindTextureHandle(effect, "positionSampler", this.positionTexture); effect.setVector4("accumulationParameters", this._accumulationParams); this.postProcess.bind(); }, undefined, false, false, true); this.reset = false; this.isMoving = false; }); // Pass 2: Copy the current frame's world-position into previousPositionTexture so the // next frame's accumulation pass can use it as "previous frame positions". const copyPositionToPreviousPass = this._frameGraph.addRenderPass(`${this.name} CopyPositionToPrevious`); copyPositionToPreviousPass.addDependencies(this.positionTexture); copyPositionToPreviousPass.setRenderTarget(this._previousPositionTexture); copyPositionToPreviousPass.setExecuteFunc((context) => { context.copyTexture(this.positionTexture); }); // Pass 3: Copy the current frame's accumulation result into previousAccumulationTexture // so the next frame's accumulation pass can use it as oldAccumulationSampler. const copyAccumulationToPreviousPass = this._frameGraph.addRenderPass(`${this.name} CopyAccumulationToPrevious`); copyAccumulationToPreviousPass.addDependencies(this.outputTexture); copyAccumulationToPreviousPass.setRenderTarget(this._previousAccumulationTexture); copyAccumulationToPreviousPass.setExecuteFunc((context) => { context.copyTexture(this.outputTexture); }); // Pass 4 (marker): empty execute, render target = outputTexture. // Ensures _checkTask sees outputTexture as the task's last enabled-pass output, // matching the disabled path. No render pass encoder is opened because the // execute function never calls _applyRenderTarget. const outputMarkerPass = this._frameGraph.addRenderPass(`${this.name} Output`); outputMarkerPass.setRenderTarget(this.outputTexture); outputMarkerPass.setExecuteFunc((_context) => { }); } dispose() { this.postProcess.dispose(); super.dispose(); } } //# sourceMappingURL=iblShadowsAccumulationTask.js.map