@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.
640 lines (639 loc) • 28 kB
JavaScript
import { PBRBaseMaterial } from "../../../Materials/PBR/pbrBaseMaterial.js";
import { OpenPBRMaterial } from "../../../Materials/PBR/openpbrMaterial.js";
import { StandardMaterial } from "../../../Materials/standardMaterial.js";
import { IBLShadowsPluginMaterial } from "../../../Rendering/IBLShadows/iblShadowsPluginMaterial.js";
import { FrameGraphIblShadowsAccumulationTask } from "./iblShadows/iblShadowsAccumulationTask.js";
import { FrameGraphIblShadowsSpatialBlurTask } from "./iblShadows/iblShadowsSpatialBlurTask.js";
import { FrameGraphIblShadowsTracingTask } from "./iblShadows/iblShadowsTracingTask.js";
import { FrameGraphIblShadowsVoxelizationTask } from "./iblShadows/iblShadowsVoxelizationTask.js";
import { Texture } from "../../../Materials/Textures/texture.js";
import { CubeTexture } from "../../../Materials/Textures/cubeTexture.js";
import { Tools } from "../../../Misc/tools.js";
import { Observable } from "../../../Misc/observable.js";
import { FrameGraphTask } from "../../frameGraphTask.js";
import { _RetryWithInterval } from "../../../Misc/timingTools.js";
import "../../../Rendering/iblCdfGeneratorSceneComponent.js";
/**
* Composite task that owns the individual IBL shadows frame graph tasks.
* The frame graph remains flat internally, but this task groups the pipeline
* and owns the child task implementation details.
*/
export class FrameGraphIblShadowsRendererTask extends FrameGraphTask {
/**
* Gets the class name.
* @returns The class name.
*/
getClassName() {
return "FrameGraphIblShadowsRendererTask";
}
get name() {
return this._name;
}
set name(value) {
this._name = value;
if (this._voxelizationTask) {
this._voxelizationTask.name = `${value} Voxelization`;
}
if (this._tracingTask) {
this._tracingTask.name = `${value} Tracing`;
}
if (this._spatialBlurTask) {
this._spatialBlurTask.name = `${value} Blur`;
}
if (this._accumulationTask) {
this._accumulationTask.name = `${value} Accumulation`;
}
}
/**
* Whether the task is disabled.
*/
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = value;
if (!this._disabled && this._dependenciesResolved) {
this._accumulationTask.reset = true;
}
this._applyMaterialPluginParameters();
}
// ------ Common properties ------
/** Camera used by the tracing stage. */
get camera() {
return this._tracingTask.camera;
}
/** Camera used by the tracing stage. */
set camera(value) {
this._setCamera(value);
}
/** Object list used by voxelization. */
get objectList() {
return this._voxelizationTask.objectList;
}
/** Object list used by voxelization. */
set objectList(value) {
if (this._voxelizationTask.objectList === value) {
return;
}
this._voxelizationTask.objectList = value;
this._voxelizationTask.updateSceneBounds();
this._voxelizationTask.requestVoxelizationUpdate();
this._accumulationTask.reset = true;
}
// ------ Tracing properties ------
/** Number of tracing sample directions. */
get sampleDirections() {
return this._tracingTask.sampleDirections;
}
/** Number of tracing sample directions. */
set sampleDirections(value) {
this._tracingTask.sampleDirections = value;
this.resetAccumulation();
}
/** Whether traced shadows preserve environment color. */
get coloredShadows() {
return this._tracingTask.coloredShadows;
}
/** Whether traced shadows preserve environment color. */
set coloredShadows(value) {
if (this._tracingTask.coloredShadows === value) {
return;
}
this._tracingTask.coloredShadows = value;
this._applyMaterialPluginParameters();
this.resetAccumulation();
}
/** Opacity of voxel-traced shadows. */
get voxelShadowOpacity() {
return this._tracingTask.voxelShadowOpacity;
}
/** Opacity of voxel-traced shadows. */
set voxelShadowOpacity(value) {
this._tracingTask.voxelShadowOpacity = value;
this.resetAccumulation();
}
/** Opacity of screen-space shadows. */
get ssShadowOpacity() {
return this._tracingTask.ssShadowOpacity;
}
/** Opacity of screen-space shadows. */
set ssShadowOpacity(value) {
this._tracingTask.ssShadowOpacity = value;
this.resetAccumulation();
}
/** Number of screen-space shadow samples. */
get ssShadowSampleCount() {
return this._tracingTask.ssShadowSampleCount;
}
/** Number of screen-space shadow samples. */
set ssShadowSampleCount(value) {
this._tracingTask.ssShadowSampleCount = value;
this.resetAccumulation();
}
/** Stride used by screen-space shadow sampling. */
get ssShadowStride() {
return this._tracingTask.ssShadowStride;
}
/** Stride used by screen-space shadow sampling. */
set ssShadowStride(value) {
this._tracingTask.ssShadowStride = value;
this.resetAccumulation();
}
/** Distance scale used by screen-space shadow tracing. */
get ssShadowDistanceScale() {
return this._tracingTask.ssShadowDistanceScale;
}
/** Distance scale used by screen-space shadow tracing. */
set ssShadowDistanceScale(value) {
this._tracingTask.ssShadowDistanceScale = value;
this.resetAccumulation();
}
/** Thickness scale used by screen-space shadow tracing. */
get ssShadowThicknessScale() {
return this._tracingTask.ssShadowThicknessScale;
}
/** Thickness scale used by screen-space shadow tracing. */
set ssShadowThicknessScale(value) {
this._tracingTask.ssShadowThicknessScale = value;
this.resetAccumulation();
}
/** Voxel tracing normal bias. */
get voxelNormalBias() {
return this._tracingTask.voxelNormalBias;
}
/** Voxel tracing normal bias. */
set voxelNormalBias(value) {
this._tracingTask.voxelNormalBias = value;
this.resetAccumulation();
}
/** Voxel tracing direction bias. */
get voxelDirectionBias() {
return this._tracingTask.voxelDirectionBias;
}
/** Voxel tracing direction bias. */
set voxelDirectionBias(value) {
this._tracingTask.voxelDirectionBias = value;
this.resetAccumulation();
}
/** Environment rotation in radians. */
get envRotation() {
return this._tracingTask.envRotation;
}
/** Environment rotation in radians. */
set envRotation(value) {
this._tracingTask.envRotation = value;
this.resetAccumulation();
}
// ------ Accumulation properties ------
/** Temporal shadow remanence while moving. */
get shadowRemanence() {
return this._accumulationTask.remanence;
}
/** Temporal shadow remanence while moving. */
set shadowRemanence(value) {
this._accumulationTask.remanence = value;
}
/** Final material shadow opacity. */
get shadowOpacity() {
return this._shadowOpacity;
}
/** Final material shadow opacity. */
set shadowOpacity(value) {
this._shadowOpacity = Math.max(0, Math.min(value, 1));
this._applyMaterialPluginParameters();
}
// ------ Voxelization properties ------
/** Voxelization resolution exponent. */
get resolutionExp() {
return this._voxelizationTask.resolutionExp;
}
/** Voxelization resolution exponent. */
set resolutionExp(value) {
this._voxelizationTask.resolutionExp = value;
this.resetAccumulation();
}
/** Voxelization refresh rate. */
get refreshRate() {
return this._voxelizationTask.refreshRate;
}
/** Voxelization refresh rate. */
set refreshRate(value) {
this._voxelizationTask.refreshRate = value;
}
/** Whether tri-planar voxelization is used. */
get triPlanarVoxelization() {
return this._voxelizationTask.triPlanarVoxelization;
}
/** Whether tri-planar voxelization is used. */
set triPlanarVoxelization(value) {
this._voxelizationTask.triPlanarVoxelization = value;
}
/** Current world-space voxel grid size. */
get voxelGridSize() {
return this._voxelizationTask.voxelGridSize;
}
/** True when the accumulated output texture is ready. */
get outputTextureReady() {
return !!this._getAccumulationOutputTexture()?.isReady;
}
/** Notifies when the accumulated output texture becomes ready. */
get onOutputTextureReadyObservable() {
return this._outputTextureReadyObservable;
}
// ------ Public methods ------
/** Triggers a voxelization refresh on the next eligible frame. */
updateVoxelization() {
this._voxelizationTask.requestVoxelizationUpdate();
}
/** Recomputes the voxelization scene bounds from the current object list. */
updateSceneBounds() {
this._voxelizationTask.updateSceneBounds();
}
/** Resets temporal accumulation. */
resetAccumulation() {
this._accumulationTask.reset = true;
}
/**
* Adds one or more materials that should receive IBL shadows.
* @param material The material or materials to register. If omitted, all scene materials are added.
*/
addShadowReceivingMaterial(material) {
if (!material) {
for (const sceneMaterial of this._frameGraph.scene.materials) {
this._addShadowReceivingMaterialInternal(sceneMaterial);
}
}
else if (Array.isArray(material)) {
for (const sceneMaterial of material) {
this._addShadowReceivingMaterialInternal(sceneMaterial);
}
}
else {
this._addShadowReceivingMaterialInternal(material);
}
this._applyMaterialPluginParameters();
}
/**
* Removes one or more materials from IBL shadow reception.
* @param material The material or materials to unregister.
*/
removeShadowReceivingMaterial(material) {
const materials = Array.isArray(material) ? material : [material];
for (const mat of materials) {
const index = this._materialsWithRenderPlugin.indexOf(mat);
if (index !== -1) {
this._materialsWithRenderPlugin.splice(index, 1);
}
const plugin = mat.pluginManager?.getPlugin(IBLShadowsPluginMaterial.Name);
if (plugin) {
plugin.isEnabled = false;
}
}
}
/** Clears all registered shadow-receiving materials. */
clearShadowReceivingMaterials() {
for (const mat of this._materialsWithRenderPlugin) {
const plugin = mat.pluginManager?.getPlugin(IBLShadowsPluginMaterial.Name);
if (plugin) {
plugin.isEnabled = false;
}
}
this._materialsWithRenderPlugin.length = 0;
}
/**
* Adds one or more meshes to the voxelization object list.
* @param mesh The mesh or meshes to add.
*/
addShadowCastingMesh(mesh) {
const meshes = Array.isArray(mesh) ? mesh : [mesh];
const objectMeshes = this._voxelizationTask.objectList.meshes;
for (const currentMesh of meshes) {
if (currentMesh && objectMeshes.indexOf(currentMesh) === -1) {
objectMeshes.push(currentMesh);
}
}
}
/**
* Removes one or more meshes from the voxelization object list.
* @param mesh The mesh or meshes to remove.
*/
removeShadowCastingMesh(mesh) {
const meshes = Array.isArray(mesh) ? mesh : [mesh];
const objectMeshes = this._voxelizationTask.objectList.meshes;
for (const currentMesh of meshes) {
const index = objectMeshes.indexOf(currentMesh);
if (index !== -1) {
objectMeshes.splice(index, 1);
}
}
}
/** Clears all shadow-casting meshes from the voxelization object list. */
clearShadowCastingMeshes() {
const objectMeshes = this._voxelizationTask.objectList.meshes;
objectMeshes.length = 0;
}
// eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax
initAsync() {
this._frameGraph.scene.enableIblCdfGenerator();
return new Promise((resolve, reject) => {
this._initAsyncCancel = _RetryWithInterval(() => this._tryEnableShadowsTasks(), () => {
this._initAsyncCancel = null;
resolve();
}, (err, isTimeout) => {
this._initAsyncCancel = null;
if (isTimeout) {
reject(new Error(`FrameGraphIblShadowsRendererTask "${this.name}": timed out waiting for shadow dependencies to be ready.`));
}
else {
reject(new Error(err));
}
}, 16, 10000);
});
}
isReady() {
return this._voxelizationTask.isReady() && this._tracingTask.isReady() && this._spatialBlurTask.isReady() && this._accumulationTask.isReady();
}
/**
* Records the parent task.
* Child tasks record the actual passes.
*/
record() {
if (this.depthTexture === undefined || this.normalTexture === undefined || this.positionTexture === undefined || this.velocityTexture === undefined) {
throw new Error(`FrameGraphIblShadowsRendererTask "${this.name}": depthTexture, normalTexture, positionTexture and velocityTexture are required`);
}
this._lastImportedIcdfTexture = null;
this._lastImportedEnvironmentTexture = null;
this._lastImportedBlueNoiseTexture = null;
this._tryEnableShadowsTasks();
// Set sub-task texture inputs (these are set here because handles may not be available at construction time)
this._tracingTask.depthTexture = this.depthTexture;
this._tracingTask.normalTexture = this.normalTexture;
this._spatialBlurTask.depthTexture = this.depthTexture;
this._spatialBlurTask.normalTexture = this.normalTexture;
this._accumulationTask.positionTexture = this.positionTexture;
this._accumulationTask.velocityTexture = this.velocityTexture;
this._voxelizationTask.record();
this._tracingTask.record();
this._spatialBlurTask.record();
this._accumulationTask.record();
const passDisabled = this._frameGraph.addRenderPass(this.name + "_disabled", true);
passDisabled.setRenderTarget(this.outputTexture);
passDisabled.setExecuteFunc((_context) => { });
}
/**
* Disposes the task and owned resources.
*/
dispose() {
this._initAsyncCancel?.();
this._initAsyncCancel = null;
this._disposeObservers();
this._voxelizationTask.dispose();
this._tracingTask.dispose();
this._spatialBlurTask.dispose();
this._accumulationTask.dispose();
super.dispose();
}
/**
* Creates a new IBL shadows composite task.
* @param name The task name.
* @param frameGraph The owning frame graph.
*/
constructor(name, frameGraph) {
super(name, frameGraph);
this._dependenciesResolved = false;
this._shadowOpacity = 1.0;
this._materialsWithRenderPlugin = [];
this._outputTextureReadyObservable = new Observable();
this._lastNotifiedOutputTexture = null;
this._observedEnvironmentTexture = null;
this._observedEnvironmentTextureUnsubscribe = null;
this._lastImportedIcdfTexture = null;
this._lastImportedEnvironmentTexture = null;
this._lastImportedBlueNoiseTexture = null;
this._cameraViewChangedObserver = null;
this._cdfTextureChangedObserver = null;
this._cdfGeneratedObserver = null;
this._environmentTextureChangedObserver = null;
this._beforeRenderDependencyObserver = null;
this._beforeRenderOutputReadyObserver = null;
this._blueNoiseLoadObserver = null;
this._texturesAllocatedObserver = null;
this._voxelizationCompleteObserver = null;
// ------ Framework overrides ------
this._initAsyncCancel = null;
this._onEnvironmentTextureLoaded = () => {
this._tryEnableShadowsTasks();
};
this._voxelizationTask = new FrameGraphIblShadowsVoxelizationTask(`${name} Voxelization`, frameGraph);
this._tracingTask = new FrameGraphIblShadowsTracingTask(`${name} Tracing`, frameGraph);
this._tracingTask.voxelGridTexture = this._voxelizationTask.outputVoxelGridTexture;
this._tracingTask.worldScaleMatrix = this._voxelizationTask.worldScaleMatrix;
this._tracingTask.voxelizationTask = this._voxelizationTask;
this._spatialBlurTask = new FrameGraphIblShadowsSpatialBlurTask(`${name} Blur`, frameGraph);
this._spatialBlurTask.sourceTexture = this._tracingTask.outputTexture;
this._spatialBlurTask.voxelizationTask = this._voxelizationTask;
this._accumulationTask = new FrameGraphIblShadowsAccumulationTask(`${name} Accumulation`, frameGraph);
this._accumulationTask.sourceTexture = this._spatialBlurTask.outputTexture;
this._accumulationTask.voxelizationTask = this._voxelizationTask;
this.outputTexture = this._accumulationTask.outputTexture;
this._blueNoiseTexture = new Texture(Tools.GetAssetUrl("https://assets.babylonjs.com/core/blue_noise/blue_noise_rgb.png"), frameGraph.scene, false, true, 1);
this._initialize();
}
_disposeDependencyObservers() {
this._observedEnvironmentTextureUnsubscribe?.();
this._observedEnvironmentTextureUnsubscribe = null;
this._observedEnvironmentTexture = null;
}
_disposeObservers() {
this._disposeDependencyObservers();
this._tracingTask.camera?.onViewMatrixChangedObservable.remove(this._cameraViewChangedObserver);
this._frameGraph.scene.iblCdfGenerator?.onTextureChangedObservable.remove(this._cdfTextureChangedObserver);
this._frameGraph.scene.iblCdfGenerator?.onGeneratedObservable.remove(this._cdfGeneratedObserver);
this._frameGraph.scene.onEnvironmentTextureChangedObservable.remove(this._environmentTextureChangedObserver);
this._frameGraph.scene.onBeforeRenderObservable.remove(this._beforeRenderDependencyObserver);
this._frameGraph.scene.onBeforeRenderObservable.remove(this._beforeRenderOutputReadyObserver);
this._blueNoiseTexture.onLoadObservable.remove(this._blueNoiseLoadObserver);
this.onTexturesAllocatedObservable.remove(this._texturesAllocatedObserver);
this._voxelizationTask.onVoxelizationCompleteObservable.remove(this._voxelizationCompleteObserver);
this._cameraViewChangedObserver = null;
this._cdfTextureChangedObserver = null;
this._cdfGeneratedObserver = null;
this._environmentTextureChangedObserver = null;
this._beforeRenderDependencyObserver = null;
this._beforeRenderOutputReadyObserver = null;
this._blueNoiseLoadObserver = null;
this._texturesAllocatedObserver = null;
this._voxelizationCompleteObserver = null;
this._blueNoiseTexture.dispose();
}
_setCamera(camera) {
const currentCamera = this._tracingTask.camera;
if (currentCamera === camera && this._cameraViewChangedObserver !== null) {
return;
}
if (currentCamera && this._cameraViewChangedObserver) {
currentCamera.onViewMatrixChangedObservable.remove(this._cameraViewChangedObserver);
this._cameraViewChangedObserver = null;
}
this._tracingTask.camera = camera;
this._cameraViewChangedObserver = camera.onViewMatrixChangedObservable.add(() => {
this._accumulationTask.isMoving = true;
});
this._accumulationTask.reset = true;
}
_observeEnvironmentTexture() {
const env = this._frameGraph.scene.environmentTexture;
const currentEnvironmentTexture = env instanceof Texture || env instanceof CubeTexture ? env : null;
if (currentEnvironmentTexture === this._observedEnvironmentTexture) {
return;
}
this._observedEnvironmentTextureUnsubscribe?.();
this._observedEnvironmentTextureUnsubscribe = null;
this._observedEnvironmentTexture = currentEnvironmentTexture;
if (currentEnvironmentTexture instanceof Texture) {
const observer = currentEnvironmentTexture.onLoadObservable.add(this._onEnvironmentTextureLoaded);
if (observer) {
this._observedEnvironmentTextureUnsubscribe = () => currentEnvironmentTexture.onLoadObservable.remove(observer);
}
}
else if (currentEnvironmentTexture instanceof CubeTexture) {
const observer = currentEnvironmentTexture.onLoadObservable.add(this._onEnvironmentTextureLoaded);
if (observer) {
this._observedEnvironmentTextureUnsubscribe = () => currentEnvironmentTexture.onLoadObservable.remove(observer);
}
}
}
_getEnvironmentTextureInternal() {
const currentEnvironmentTexture = this._frameGraph.scene.environmentTexture;
if (!currentEnvironmentTexture || !currentEnvironmentTexture.isReadyOrNotBlocking()) {
return null;
}
const internalTexture = currentEnvironmentTexture.getInternalTexture();
return internalTexture?.isReady ? internalTexture : null;
}
_getAccumulationOutputTexture() {
try {
return this._frameGraph.textureManager.getTextureFromHandle(this._accumulationTask.outputTexture);
}
catch {
return null;
}
}
_notifyIfOutputTextureReady() {
const outputTexture = this._getAccumulationOutputTexture();
if (!outputTexture?.isReady || this._lastNotifiedOutputTexture === outputTexture) {
return;
}
this._lastNotifiedOutputTexture = outputTexture;
this._outputTextureReadyObservable.notifyObservers(outputTexture);
}
_applyMaterialPluginParameters() {
const accumulationTexture = this._getAccumulationOutputTexture();
for (const material of this._materialsWithRenderPlugin) {
const plugin = material.pluginManager?.getPlugin(IBLShadowsPluginMaterial.Name);
if (!plugin) {
continue;
}
if (accumulationTexture && accumulationTexture.isReady) {
plugin.iblShadowsTexture = accumulationTexture;
}
plugin.shadowOpacity = this._shadowOpacity;
plugin.isColored = this._tracingTask.coloredShadows;
plugin.isEnabled = !this._disabled && this._dependenciesResolved && !!accumulationTexture;
}
}
_addShadowReceivingMaterialInternal(material) {
const isSupportedMaterial = material instanceof PBRBaseMaterial || material instanceof StandardMaterial || material instanceof OpenPBRMaterial;
if (!isSupportedMaterial || this._materialsWithRenderPlugin.indexOf(material) !== -1) {
return;
}
const plugin = material.pluginManager?.getPlugin(IBLShadowsPluginMaterial.Name);
if (!plugin) {
new IBLShadowsPluginMaterial(material);
}
this._materialsWithRenderPlugin.push(material);
}
_tryEnableShadowsTasks() {
const scene = this._frameGraph.scene;
const icdfTexture = scene.iblCdfGenerator?.getIcdfTexture().getInternalTexture();
const environmentTexture = this._getEnvironmentTextureInternal();
const blueNoiseInternalTexture = this._blueNoiseTexture.getInternalTexture();
if (!icdfTexture?.isReady || icdfTexture.width === 1 || !environmentTexture?.isReady || !blueNoiseInternalTexture?.isReady) {
if (this._dependenciesResolved) {
this._dependenciesResolved = false;
this._applyMaterialPluginParameters();
}
return false;
}
const icdfChanged = this._lastImportedIcdfTexture !== icdfTexture;
const environmentChanged = this._lastImportedEnvironmentTexture !== environmentTexture;
const blueNoiseChanged = this._lastImportedBlueNoiseTexture !== blueNoiseInternalTexture;
if (icdfChanged) {
this._tracingTask.icdfTexture = this._frameGraph.textureManager.importTexture(`ICDF Texture`, icdfTexture, this._tracingTask.icdfTexture);
this._lastImportedIcdfTexture = icdfTexture;
}
if (environmentChanged) {
this._tracingTask.environmentTexture = this._frameGraph.textureManager.importTexture(`Environment Texture`, environmentTexture, this._tracingTask.environmentTexture);
this._lastImportedEnvironmentTexture = environmentTexture;
}
if (blueNoiseChanged) {
this._tracingTask.blueNoiseTexture = this._frameGraph.textureManager.importTexture(`Blue Noise Texture`, blueNoiseInternalTexture, this._tracingTask.blueNoiseTexture);
this._lastImportedBlueNoiseTexture = blueNoiseInternalTexture;
}
if (!this._dependenciesResolved) {
this._dependenciesResolved = true;
if (!this._disabled) {
this._accumulationTask.reset = true;
}
this._disposeDependencyObservers();
}
else if (icdfChanged || environmentChanged || blueNoiseChanged) {
this._accumulationTask.reset = true;
}
this._applyMaterialPluginParameters();
return true;
}
_initialize() {
const scene = this._frameGraph.scene;
this._voxelizationCompleteObserver = this._voxelizationTask.onVoxelizationCompleteObservable.add(() => {
this._tracingTask.voxelGridTexture = this._voxelizationTask.outputVoxelGridTexture;
this._accumulationTask.reset = true;
});
this._cdfTextureChangedObserver =
scene.iblCdfGenerator?.onTextureChangedObservable.add(() => {
this._lastImportedIcdfTexture = null;
this._accumulationTask.reset = true;
}) ?? null;
this._cdfGeneratedObserver =
scene.iblCdfGenerator?.onGeneratedObservable.add(() => {
this._lastImportedIcdfTexture = null;
this._tryEnableShadowsTasks();
}) ?? null;
this._environmentTextureChangedObserver = scene.onEnvironmentTextureChangedObservable.add(() => {
this._lastImportedEnvironmentTexture = null;
this._dependenciesResolved = false;
this._observeEnvironmentTexture();
this._applyMaterialPluginParameters();
this._tryEnableShadowsTasks();
});
this._observeEnvironmentTexture();
if (scene.environmentTexture?.isReadyOrNotBlocking()) {
this._tryEnableShadowsTasks();
}
this._blueNoiseLoadObserver = this._blueNoiseTexture.onLoadObservable.add(() => {
this._tryEnableShadowsTasks();
});
this._beforeRenderDependencyObserver = scene.onBeforeRenderObservable.add(() => {
this._tryEnableShadowsTasks();
});
this._beforeRenderOutputReadyObserver = scene.onBeforeRenderObservable.add(() => {
this._notifyIfOutputTextureReady();
});
this._tryEnableShadowsTasks();
this._texturesAllocatedObserver = this.onTexturesAllocatedObservable.add(() => {
this._applyMaterialPluginParameters();
this._notifyIfOutputTextureReady();
});
}
}
//# sourceMappingURL=iblShadowsRendererTask.js.map