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.

159 lines (158 loc) 8.08 kB
import { FrameGraphTask } from "../../frameGraphTask.js"; import { FrameGraphDepthOfFieldMergeTask } from "./depthOfFieldMergeTask.js"; import { FrameGraphCircleOfConfusionTask } from "./circleOfConfusionTask.js"; import { FrameGraphDepthOfFieldBlurTask } from "./depthOfFieldBlurTask.js"; import { ThinDepthOfFieldEffect } from "../../../PostProcesses/thinDepthOfFieldEffect.js"; /** * Task which applies a depth of field effect. */ export class FrameGraphDepthOfFieldTask extends FrameGraphTask { /** * The name of the task. */ get name() { return this._name; } set name(name) { this._name = name; if (this._circleOfConfusion) { this._circleOfConfusion.name = `${name} Circle of Confusion`; } if (this._blurX) { for (let i = 0; i < this._blurX.length; i++) { this._blurX[i].name = `${name} Blur X${i}`; this._blurY[i].name = `${name} Blur Y${i}`; } } if (this._merge) { this._merge.name = `${name} Merge`; } } /** * Constructs a depth of field task. * @param name The name of the task. * @param frameGraph The frame graph this task belongs to. * @param blurLevel The blur level of the depth of field effect (default: ThinDepthOfFieldEffectBlurLevel.Low). * @param hdr Whether the depth of field effect is HDR. */ constructor(name, frameGraph, blurLevel = 0 /* ThinDepthOfFieldEffectBlurLevel.Low */, hdr = false) { super(name, frameGraph); /** * The sampling mode to use for the source texture. */ this.sourceSamplingMode = 2; /** * The sampling mode to use for the depth texture. */ this.depthSamplingMode = 2; this._blurX = []; this._blurY = []; this._engine = frameGraph.engine; this.hdr = hdr; this._defaultPipelineTextureType = 0; if (hdr) { const caps = frameGraph.engine.getCaps(); if (caps.textureHalfFloatRender) { this._defaultPipelineTextureType = 2; } else if (caps.textureFloatRender) { this._defaultPipelineTextureType = 1; } } this.depthOfField = new ThinDepthOfFieldEffect(name, frameGraph.engine, blurLevel, true); this._circleOfConfusion = new FrameGraphCircleOfConfusionTask(`${name} Circle of Confusion`, this._frameGraph, this.depthOfField._circleOfConfusion); const blurCount = this.depthOfField._depthOfFieldBlurX.length; for (let i = 0; i < blurCount; i++) { this._blurX.push(new FrameGraphDepthOfFieldBlurTask(`${name} Blur X${i}`, this._frameGraph, this.depthOfField._depthOfFieldBlurX[i][0])); this._blurY.push(new FrameGraphDepthOfFieldBlurTask(`${name} Blur Y${i}`, this._frameGraph, this.depthOfField._depthOfFieldBlurY[i][0])); } this._merge = new FrameGraphDepthOfFieldMergeTask(`${name} Merge`, this._frameGraph, this.depthOfField._dofMerge); this.onTexturesAllocatedObservable.add((context) => { this._circleOfConfusion.onTexturesAllocatedObservable.notifyObservers(context); for (let i = 0; i < blurCount; i++) { this._blurX[i].onTexturesAllocatedObservable.notifyObservers(context); this._blurY[i].onTexturesAllocatedObservable.notifyObservers(context); } this._merge.onTexturesAllocatedObservable.notifyObservers(context); }); this.outputTexture = this._frameGraph.textureManager.createDanglingHandle(); } isReady() { return this.depthOfField.isReady(); } record() { if (this.sourceTexture === undefined || this.depthTexture === undefined || this.camera === undefined) { throw new Error("FrameGraphDepthOfFieldTask: sourceTexture, depthTexture and camera are required"); } const sourceTextureDescription = this._frameGraph.textureManager.getTextureDescription(this.sourceTexture); const textureSize = { width: sourceTextureDescription.size.width, height: sourceTextureDescription.size.height, }; const circleOfConfusionTextureFormat = this._engine.isWebGPU || this._engine.version > 1 ? 6 : 5; const textureCreationOptions = { size: textureSize, options: { createMipMaps: false, types: [this._defaultPipelineTextureType], formats: [circleOfConfusionTextureFormat], samples: 1, useSRGBBuffers: [false], labels: [""], }, sizeIsPercentage: false, }; const circleOfConfusionTextureHandle = this._frameGraph.textureManager.createRenderTargetTexture(this._circleOfConfusion.name, textureCreationOptions); this._circleOfConfusion.sourceTexture = this.sourceTexture; // texture not used by the CoC shader this._circleOfConfusion.depthTexture = this.depthTexture; this._circleOfConfusion.depthSamplingMode = this.depthSamplingMode; this._circleOfConfusion.camera = this.camera; this._circleOfConfusion.targetTexture = circleOfConfusionTextureHandle; this._circleOfConfusion.record(true); textureCreationOptions.options.formats = [5]; const blurSteps = []; for (let i = 0; i < this._blurX.length; i++) { const ratio = this.depthOfField._depthOfFieldBlurX[i][1]; textureSize.width = Math.floor(sourceTextureDescription.size.width * ratio) || 1; textureSize.height = Math.floor(sourceTextureDescription.size.height * ratio) || 1; textureCreationOptions.options.labels[0] = "step " + (i + 1); const blurYTextureHandle = this._frameGraph.textureManager.createRenderTargetTexture(this._blurY[i].name, textureCreationOptions); this._blurY[i].sourceTexture = i === 0 ? this.sourceTexture : this._blurX[i - 1].outputTexture; this._blurY[i].sourceSamplingMode = 2; this._blurY[i].circleOfConfusionTexture = circleOfConfusionTextureHandle; this._blurY[i].targetTexture = blurYTextureHandle; this._blurY[i].record(true); const blurXTextureHandle = this._frameGraph.textureManager.createRenderTargetTexture(this._blurX[i].name, textureCreationOptions); this._blurX[i].sourceTexture = this._blurY[i].outputTexture; this._blurX[i].sourceSamplingMode = 2; this._blurX[i].circleOfConfusionTexture = circleOfConfusionTextureHandle; this._blurX[i].targetTexture = blurXTextureHandle; this._blurX[i].record(true); blurSteps.push(blurXTextureHandle); } const sourceTextureCreationOptions = this._frameGraph.textureManager.getTextureCreationOptions(this.sourceTexture); this._frameGraph.textureManager.resolveDanglingHandle(this.outputTexture, this.targetTexture, this._merge.name, sourceTextureCreationOptions); this._merge.sourceTexture = this.sourceTexture; this._merge.sourceSamplingMode = this.sourceSamplingMode; this._merge.circleOfConfusionTexture = circleOfConfusionTextureHandle; this._merge.blurSteps = blurSteps; this._merge.targetTexture = this.outputTexture; this._merge.record(true); const passDisabled = this._frameGraph.addRenderPass(this.name + "_disabled", true); passDisabled.addDependencies(this.sourceTexture); passDisabled.setRenderTarget(this.outputTexture); passDisabled.setExecuteFunc((context) => { context.copyTexture(this.sourceTexture); }); } dispose() { this._circleOfConfusion.dispose(); for (let i = 0; i < this._blurX.length; i++) { this._blurX[i].dispose(); this._blurY[i].dispose(); } this._merge.dispose(); super.dispose(); } } //# sourceMappingURL=depthOfFieldTask.js.map