123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- import { PrePassRenderTarget } from "../Materials/Textures/prePassRenderTarget.js";
- import { _WarnImport } from "../Misc/devTools.js";
- import { Color4 } from "../Maths/math.color.js";
- import { Material } from "../Materials/material.js";
- import { GeometryBufferRenderer } from "../Rendering/geometryBufferRenderer.js";
- /**
- * Renders a pre pass of the scene
- * This means every mesh in the scene will be rendered to a render target texture
- * And then this texture will be composited to the rendering canvas with post processes
- * It is necessary for effects like subsurface scattering or deferred shading
- */
- export class PrePassRenderer {
- /**
- * Indicates if the prepass renderer is generating normals in world space or camera space (default: camera space)
- */
- get generateNormalsInWorldSpace() {
- return this._generateNormalsInWorldSpace;
- }
- set generateNormalsInWorldSpace(value) {
- if (this._generateNormalsInWorldSpace === value) {
- return;
- }
- this._generateNormalsInWorldSpace = value;
- this._markAllMaterialsAsPrePassDirty();
- }
- /**
- * Returns the index of a texture in the multi render target texture array.
- * @param type Texture type
- * @returns The index
- */
- getIndex(type) {
- return this._textureIndices[type];
- }
- /**
- * How many samples are used for MSAA of the scene render target
- */
- get samples() {
- return this.defaultRT.samples;
- }
- set samples(n) {
- this.defaultRT.samples = n;
- }
- /**
- * If set to true (default: false), the depth texture will be cleared with the depth value corresponding to the far plane (1 in normal mode, 0 in reverse depth buffer mode)
- * If set to false, the depth texture is always cleared with 0.
- */
- get useSpecificClearForDepthTexture() {
- return this._useSpecificClearForDepthTexture;
- }
- set useSpecificClearForDepthTexture(value) {
- if (this._useSpecificClearForDepthTexture === value) {
- return;
- }
- this._useSpecificClearForDepthTexture = value;
- this._isDirty = true;
- }
- /**
- * @returns the prepass render target for the rendering pass.
- * If we are currently rendering a render target, it returns the PrePassRenderTarget
- * associated with that render target. Otherwise, it returns the scene default PrePassRenderTarget
- */
- getRenderTarget() {
- return this._currentTarget;
- }
- /**
- * @internal
- * Managed by the scene component
- * @param prePassRenderTarget
- */
- _setRenderTarget(prePassRenderTarget) {
- if (prePassRenderTarget) {
- this._currentTarget = prePassRenderTarget;
- }
- else {
- this._currentTarget = this.defaultRT;
- this._engine.currentRenderPassId = this._scene.activeCamera?.renderPassId ?? this._currentTarget.renderPassId;
- }
- }
- /**
- * Returns true if the currently rendered prePassRenderTarget is the one
- * associated with the scene.
- */
- get currentRTisSceneRT() {
- return this._currentTarget === this.defaultRT;
- }
- _refreshGeometryBufferRendererLink() {
- if (!this.doNotUseGeometryRendererFallback) {
- this._geometryBuffer = this._scene.enableGeometryBufferRenderer();
- if (!this._geometryBuffer) {
- // Not supported
- this.doNotUseGeometryRendererFallback = true;
- return;
- }
- this._geometryBuffer._linkPrePassRenderer(this);
- }
- else {
- if (this._geometryBuffer) {
- this._geometryBuffer._unlinkPrePassRenderer();
- }
- this._geometryBuffer = null;
- this._scene.disableGeometryBufferRenderer();
- }
- }
- /**
- * Indicates if the prepass is enabled
- */
- get enabled() {
- return this._enabled;
- }
- /**
- * Instantiates a prepass renderer
- * @param scene The scene
- */
- constructor(scene) {
- /**
- * To save performance, we can excluded skinned meshes from the prepass
- */
- this.excludedSkinnedMesh = [];
- /**
- * Force material to be excluded from the prepass
- * Can be useful when `useGeometryBufferFallback` is set to `true`
- * and you don't want a material to show in the effect.
- */
- this.excludedMaterials = [];
- /**
- * Number of textures in the multi render target texture where the scene is directly rendered
- */
- this.mrtCount = 0;
- this._mrtTypes = [];
- this._mrtFormats = [];
- this._mrtLayout = [];
- this._mrtNames = [];
- this._textureIndices = [];
- this._generateNormalsInWorldSpace = false;
- this._useSpecificClearForDepthTexture = false;
- this._isDirty = true;
- /**
- * Configuration for prepass effects
- */
- this._effectConfigurations = [];
- /**
- * Prevents the PrePassRenderer from using the GeometryBufferRenderer as a fallback
- */
- this.doNotUseGeometryRendererFallback = true;
- /**
- * All the render targets generated by prepass
- */
- this.renderTargets = [];
- this._clearColor = new Color4(0, 0, 0, 0);
- this._clearDepthColor = new Color4(1e8, 0, 0, 1); // "infinity" value - depth in the depth texture is view.z, not a 0..1 value!
- this._enabled = false;
- this._needsCompositionForThisPass = false;
- /**
- * Set to true to disable gamma transform in PrePass.
- * Can be useful in case you already proceed to gamma transform on a material level
- * and your post processes don't need to be in linear color space.
- */
- this.disableGammaTransform = false;
- this._scene = scene;
- this._engine = scene.getEngine();
- let type = 0;
- if (this._engine._caps.textureFloat && this._engine._caps.textureFloatLinearFiltering) {
- type = 1;
- }
- else if (this._engine._caps.textureHalfFloat && this._engine._caps.textureHalfFloatLinearFiltering) {
- type = 2;
- }
- for (let i = 0; i < PrePassRenderer.TextureFormats.length; ++i) {
- const format = PrePassRenderer.TextureFormats[i].format;
- if (PrePassRenderer.TextureFormats[i].type === 1) {
- PrePassRenderer.TextureFormats[5].type = type;
- if ((format === 6 || format === 7 || format === 5) &&
- !this._engine._caps.supportFloatTexturesResolve) {
- // We don't know in advance if the texture will be used as a resolve target, so we revert to half_float if the extension to resolve full float textures is not supported
- PrePassRenderer.TextureFormats[5].type = 2;
- }
- }
- }
- PrePassRenderer._SceneComponentInitialization(this._scene);
- this.defaultRT = this._createRenderTarget("sceneprePassRT", null);
- this._currentTarget = this.defaultRT;
- }
- /**
- * Creates a new PrePassRenderTarget
- * This should be the only way to instantiate a `PrePassRenderTarget`
- * @param name Name of the `PrePassRenderTarget`
- * @param renderTargetTexture RenderTarget the `PrePassRenderTarget` will be attached to.
- * Can be `null` if the created `PrePassRenderTarget` is attached to the scene (default framebuffer).
- * @internal
- */
- _createRenderTarget(name, renderTargetTexture) {
- const rt = new PrePassRenderTarget(name, renderTargetTexture, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene, {
- generateMipMaps: false,
- generateStencilBuffer: this._engine.isStencilEnable,
- defaultType: 0,
- types: [],
- drawOnlyOnFirstAttachmentByDefault: true,
- });
- this.renderTargets.push(rt);
- if (this._enabled) {
- // The pre-pass renderer is already enabled, so make sure we create the render target with the correct number of textures
- this._update();
- }
- return rt;
- }
- /**
- * Indicates if rendering a prepass is supported
- */
- get isSupported() {
- return this._scene.getEngine().getCaps().drawBuffersExtension;
- }
- /**
- * Sets the proper output textures to draw in the engine.
- * @param effect The effect that is drawn. It can be or not be compatible with drawing to several output textures.
- * @param subMesh Submesh on which the effect is applied
- */
- bindAttachmentsForEffect(effect, subMesh) {
- const material = subMesh.getMaterial();
- const isPrePassCapable = material && material.isPrePassCapable;
- const excluded = material && this.excludedMaterials.indexOf(material) !== -1;
- if (this.enabled && this._currentTarget.enabled) {
- if (effect._multiTarget && isPrePassCapable && !excluded) {
- this._engine.bindAttachments(this._multiRenderAttachments);
- }
- else {
- if (this._engine._currentRenderTarget) {
- this._engine.bindAttachments(this._defaultAttachments);
- }
- else {
- this._engine.restoreSingleAttachment();
- }
- if (this._geometryBuffer && this.currentRTisSceneRT && !excluded) {
- this._geometryBuffer.renderList.push(subMesh.getRenderingMesh());
- }
- }
- }
- }
- _reinitializeAttachments() {
- const multiRenderLayout = [];
- const clearLayout = [false];
- const clearDepthLayout = [false];
- const defaultLayout = [true];
- for (let i = 0; i < this.mrtCount; i++) {
- multiRenderLayout.push(true);
- if (i > 0) {
- if (this._useSpecificClearForDepthTexture && this._mrtLayout[i] === 5) {
- clearLayout.push(false);
- clearDepthLayout.push(true);
- }
- else {
- clearLayout.push(true);
- clearDepthLayout.push(false);
- }
- defaultLayout.push(false);
- }
- }
- this._multiRenderAttachments = this._engine.buildTextureLayout(multiRenderLayout);
- this._clearAttachments = this._engine.buildTextureLayout(clearLayout);
- this._clearDepthAttachments = this._engine.buildTextureLayout(clearDepthLayout);
- this._defaultAttachments = this._engine.buildTextureLayout(defaultLayout);
- }
- _resetLayout() {
- for (let i = 0; i < PrePassRenderer.TextureFormats.length; i++) {
- this._textureIndices[PrePassRenderer.TextureFormats[i].purpose] = -1;
- }
- this._textureIndices[4] = 0;
- this._mrtLayout = [4];
- this._mrtTypes = [PrePassRenderer.TextureFormats[4].type];
- this._mrtFormats = [PrePassRenderer.TextureFormats[4].format];
- this._mrtNames = [PrePassRenderer.TextureFormats[4].name];
- this.mrtCount = 1;
- }
- _updateGeometryBufferLayout() {
- this._refreshGeometryBufferRendererLink();
- if (this._geometryBuffer) {
- this._geometryBuffer._resetLayout();
- const texturesActivated = [];
- for (let i = 0; i < this._mrtLayout.length; i++) {
- texturesActivated.push(false);
- }
- this._geometryBuffer._linkInternalTexture(this.defaultRT.getInternalTexture());
- const matches = [
- {
- prePassConstant: 5,
- geometryBufferConstant: GeometryBufferRenderer.DEPTH_TEXTURE_TYPE,
- },
- {
- prePassConstant: 6,
- geometryBufferConstant: GeometryBufferRenderer.NORMAL_TEXTURE_TYPE,
- },
- {
- prePassConstant: 1,
- geometryBufferConstant: GeometryBufferRenderer.POSITION_TEXTURE_TYPE,
- },
- {
- prePassConstant: 3,
- geometryBufferConstant: GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE,
- },
- {
- prePassConstant: 2,
- geometryBufferConstant: GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE,
- },
- ];
- // replace textures in the geometryBuffer RT
- for (let i = 0; i < matches.length; i++) {
- const index = this._mrtLayout.indexOf(matches[i].prePassConstant);
- if (index !== -1) {
- this._geometryBuffer._forceTextureType(matches[i].geometryBufferConstant, index);
- texturesActivated[index] = true;
- }
- }
- this._geometryBuffer._setAttachments(this._engine.buildTextureLayout(texturesActivated));
- }
- }
- /**
- * Restores attachments for single texture draw.
- */
- restoreAttachments() {
- if (this.enabled && this._currentTarget.enabled && this._defaultAttachments) {
- if (this._engine._currentRenderTarget) {
- this._engine.bindAttachments(this._defaultAttachments);
- }
- else {
- this._engine.restoreSingleAttachment();
- }
- }
- }
- /**
- * @internal
- */
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- _beforeDraw(camera, faceIndex, layer) {
- // const previousEnabled = this._enabled && this._currentTarget.enabled;
- if (this._isDirty) {
- this._update();
- }
- if (!this._enabled || !this._currentTarget.enabled) {
- return;
- }
- if (this._geometryBuffer) {
- this._geometryBuffer.renderList = [];
- }
- this._setupOutputForThisPass(this._currentTarget, camera);
- }
- _prepareFrame(prePassRenderTarget, faceIndex, layer) {
- if (prePassRenderTarget.renderTargetTexture) {
- prePassRenderTarget.renderTargetTexture._prepareFrame(this._scene, faceIndex, layer, prePassRenderTarget.renderTargetTexture.useCameraPostProcesses);
- }
- else if (this._postProcessesSourceForThisPass.length) {
- this._scene.postProcessManager._prepareFrame();
- }
- else {
- this._engine.restoreDefaultFramebuffer();
- }
- }
- /**
- * Sets an intermediary texture between prepass and postprocesses. This texture
- * will be used as input for post processes
- * @param rt The render target texture to use
- * @returns true if there are postprocesses that will use this texture,
- * false if there is no postprocesses - and the function has no effect
- */
- setCustomOutput(rt) {
- const firstPP = this._postProcessesSourceForThisPass[0];
- if (!firstPP) {
- return false;
- }
- firstPP.inputTexture = rt.renderTarget;
- return true;
- }
- _renderPostProcesses(prePassRenderTarget, faceIndex) {
- const firstPP = this._postProcessesSourceForThisPass[0];
- const outputTexture = firstPP ? firstPP.inputTexture : prePassRenderTarget.renderTargetTexture ? prePassRenderTarget.renderTargetTexture.renderTarget : null;
- // Build post process chain for this prepass post draw
- let postProcessChain = this._currentTarget._beforeCompositionPostProcesses;
- if (this._needsCompositionForThisPass) {
- postProcessChain = postProcessChain.concat([this._currentTarget.imageProcessingPostProcess]);
- }
- // Activates and renders the chain
- if (postProcessChain.length) {
- this._scene.postProcessManager._prepareFrame(this._currentTarget.renderTarget?.texture, postProcessChain);
- this._scene.postProcessManager.directRender(postProcessChain, outputTexture, false, faceIndex);
- }
- }
- /**
- * @internal
- */
- _afterDraw(faceIndex, layer) {
- if (this._enabled && this._currentTarget.enabled) {
- this._prepareFrame(this._currentTarget, faceIndex, layer);
- this._renderPostProcesses(this._currentTarget, faceIndex);
- }
- }
- /**
- * Clears the current prepass render target (in the sense of settings pixels to the scene clear color value)
- * @internal
- */
- _clear() {
- if (this._enabled && this._currentTarget.enabled) {
- this._bindFrameBuffer();
- // Clearing other attachment with 0 on all other attachments
- this._engine.bindAttachments(this._clearAttachments);
- this._engine.clear(this._clearColor, true, false, false);
- if (this._useSpecificClearForDepthTexture) {
- this._engine.bindAttachments(this._clearDepthAttachments);
- this._engine.clear(this._clearDepthColor, true, false, false);
- }
- // Regular clear color with the scene clear color of the 1st attachment
- this._engine.bindAttachments(this._defaultAttachments);
- }
- }
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- _bindFrameBuffer() {
- if (this._enabled && this._currentTarget.enabled) {
- this._currentTarget._checkSize();
- const internalTexture = this._currentTarget.renderTarget;
- if (internalTexture) {
- this._engine.bindFramebuffer(internalTexture);
- }
- }
- }
- _setEnabled(enabled) {
- this._enabled = enabled;
- }
- _setRenderTargetEnabled(prePassRenderTarget, enabled) {
- prePassRenderTarget.enabled = enabled;
- if (!enabled) {
- this._unlinkInternalTexture(prePassRenderTarget);
- }
- }
- /**
- * Adds an effect configuration to the prepass render target.
- * If an effect has already been added, it won't add it twice and will return the configuration
- * already present.
- * @param cfg the effect configuration
- * @returns the effect configuration now used by the prepass
- */
- addEffectConfiguration(cfg) {
- // Do not add twice
- for (let i = 0; i < this._effectConfigurations.length; i++) {
- if (this._effectConfigurations[i].name === cfg.name) {
- return this._effectConfigurations[i];
- }
- }
- this._effectConfigurations.push(cfg);
- return cfg;
- }
- /**
- * Retrieves an effect configuration by name
- * @param name the name of the effect configuration
- * @returns the effect configuration, or null if not present
- */
- getEffectConfiguration(name) {
- for (let i = 0; i < this._effectConfigurations.length; i++) {
- if (this._effectConfigurations[i].name === name) {
- return this._effectConfigurations[i];
- }
- }
- return null;
- }
- _enable() {
- const previousMrtCount = this.mrtCount;
- for (let i = 0; i < this._effectConfigurations.length; i++) {
- if (this._effectConfigurations[i].enabled) {
- this._enableTextures(this._effectConfigurations[i].texturesRequired);
- }
- }
- for (let i = 0; i < this.renderTargets.length; i++) {
- if (this.mrtCount !== previousMrtCount || this.renderTargets[i].count !== this.mrtCount) {
- this.renderTargets[i].updateCount(this.mrtCount, { types: this._mrtTypes, formats: this._mrtFormats }, this._mrtNames.concat("prePass_DepthBuffer"));
- }
- this.renderTargets[i]._resetPostProcessChain();
- for (let j = 0; j < this._effectConfigurations.length; j++) {
- if (this._effectConfigurations[j].enabled) {
- // TODO : subsurface scattering has 1 scene-wide effect configuration
- // solution : do not stock postProcess on effectConfiguration, but in the prepassRenderTarget (hashmap configuration => postProcess)
- // And call createPostProcess whenever the post process does not exist in the RT
- if (!this._effectConfigurations[j].postProcess && this._effectConfigurations[j].createPostProcess) {
- this._effectConfigurations[j].createPostProcess();
- }
- if (this._effectConfigurations[j].postProcess) {
- this.renderTargets[i]._beforeCompositionPostProcesses.push(this._effectConfigurations[j].postProcess);
- }
- }
- }
- }
- this._reinitializeAttachments();
- this._setEnabled(true);
- this._updateGeometryBufferLayout();
- }
- _disable() {
- this._setEnabled(false);
- for (let i = 0; i < this.renderTargets.length; i++) {
- this._setRenderTargetEnabled(this.renderTargets[i], false);
- }
- this._resetLayout();
- for (let i = 0; i < this._effectConfigurations.length; i++) {
- this._effectConfigurations[i].enabled = false;
- }
- }
- _getPostProcessesSource(prePassRenderTarget, camera) {
- if (camera) {
- return camera._postProcesses;
- }
- else if (prePassRenderTarget.renderTargetTexture) {
- if (prePassRenderTarget.renderTargetTexture.useCameraPostProcesses) {
- const camera = prePassRenderTarget.renderTargetTexture.activeCamera ? prePassRenderTarget.renderTargetTexture.activeCamera : this._scene.activeCamera;
- return camera ? camera._postProcesses : [];
- }
- else if (prePassRenderTarget.renderTargetTexture.postProcesses) {
- return prePassRenderTarget.renderTargetTexture.postProcesses;
- }
- else {
- return [];
- }
- }
- else {
- return this._scene.activeCamera ? this._scene.activeCamera._postProcesses : [];
- }
- }
- _setupOutputForThisPass(prePassRenderTarget, camera) {
- // Order is : draw ===> prePassRenderTarget._postProcesses ==> ipp ==> camera._postProcesses
- const secondaryCamera = camera && this._scene.activeCameras && !!this._scene.activeCameras.length && this._scene.activeCameras.indexOf(camera) !== 0;
- this._postProcessesSourceForThisPass = this._getPostProcessesSource(prePassRenderTarget, camera);
- this._postProcessesSourceForThisPass = this._postProcessesSourceForThisPass.filter((pp) => {
- return pp != null;
- });
- this._scene.autoClear = true;
- const cameraHasImageProcessing = this._hasImageProcessing(this._postProcessesSourceForThisPass);
- this._needsCompositionForThisPass = !cameraHasImageProcessing && !this.disableGammaTransform && this._needsImageProcessing() && !secondaryCamera;
- const firstCameraPP = this._getFirstPostProcess(this._postProcessesSourceForThisPass);
- const firstPrePassPP = prePassRenderTarget._beforeCompositionPostProcesses && prePassRenderTarget._beforeCompositionPostProcesses[0];
- let firstPP = null;
- // Setting the scene-wide post process configuration
- this._scene.imageProcessingConfiguration.applyByPostProcess = this._needsCompositionForThisPass || cameraHasImageProcessing;
- // Create composition effect if needed
- if (this._needsCompositionForThisPass && !prePassRenderTarget.imageProcessingPostProcess) {
- prePassRenderTarget._createCompositionEffect();
- }
- // Setting the prePassRenderTarget as input texture of the first PP
- if (firstPrePassPP) {
- firstPP = firstPrePassPP;
- }
- else if (this._needsCompositionForThisPass) {
- firstPP = prePassRenderTarget.imageProcessingPostProcess;
- }
- else if (firstCameraPP) {
- firstPP = firstCameraPP;
- }
- this._bindFrameBuffer();
- this._linkInternalTexture(prePassRenderTarget, firstPP);
- }
- _linkInternalTexture(prePassRenderTarget, postProcess) {
- if (postProcess) {
- postProcess.autoClear = false;
- postProcess.inputTexture = prePassRenderTarget.renderTarget;
- }
- if (prePassRenderTarget._outputPostProcess !== postProcess) {
- if (prePassRenderTarget._outputPostProcess) {
- this._unlinkInternalTexture(prePassRenderTarget);
- }
- prePassRenderTarget._outputPostProcess = postProcess;
- }
- if (prePassRenderTarget._internalTextureDirty) {
- this._updateGeometryBufferLayout();
- prePassRenderTarget._internalTextureDirty = false;
- }
- }
- /**
- * @internal
- */
- _unlinkInternalTexture(prePassRenderTarget) {
- if (prePassRenderTarget._outputPostProcess) {
- prePassRenderTarget._outputPostProcess.autoClear = true;
- prePassRenderTarget._outputPostProcess.restoreDefaultInputTexture();
- prePassRenderTarget._outputPostProcess = null;
- }
- }
- _needsImageProcessing() {
- for (let i = 0; i < this._effectConfigurations.length; i++) {
- if (this._effectConfigurations[i].enabled && this._effectConfigurations[i].needsImageProcessing) {
- return true;
- }
- }
- return false;
- }
- _hasImageProcessing(postProcesses) {
- let isIPPAlreadyPresent = false;
- if (postProcesses) {
- for (let i = 0; i < postProcesses.length; i++) {
- if (postProcesses[i]?.getClassName() === "ImageProcessingPostProcess") {
- isIPPAlreadyPresent = true;
- break;
- }
- }
- }
- return isIPPAlreadyPresent;
- }
- /**
- * Internal, gets the first post proces.
- * @param postProcesses
- * @returns the first post process to be run on this camera.
- */
- _getFirstPostProcess(postProcesses) {
- for (let ppIndex = 0; ppIndex < postProcesses.length; ppIndex++) {
- if (postProcesses[ppIndex] !== null) {
- return postProcesses[ppIndex];
- }
- }
- return null;
- }
- /**
- * Marks the prepass renderer as dirty, triggering a check if the prepass is necessary for the next rendering.
- */
- markAsDirty() {
- this._isDirty = true;
- }
- /**
- * Enables a texture on the MultiRenderTarget for prepass
- * @param types
- */
- _enableTextures(types) {
- // For velocity : enable storage of previous matrices for instances
- this._scene.needsPreviousWorldMatrices = false;
- for (let i = 0; i < types.length; i++) {
- const type = types[i];
- if (this._textureIndices[type] === -1) {
- this._textureIndices[type] = this._mrtLayout.length;
- this._mrtLayout.push(type);
- this._mrtTypes.push(PrePassRenderer.TextureFormats[type].type);
- this._mrtFormats.push(PrePassRenderer.TextureFormats[type].format);
- this._mrtNames.push(PrePassRenderer.TextureFormats[type].name);
- this.mrtCount++;
- }
- if (type === 2) {
- this._scene.needsPreviousWorldMatrices = true;
- }
- }
- }
- /**
- * Makes sure that the prepass renderer is up to date if it has been dirtified.
- */
- update() {
- if (this._isDirty) {
- this._update();
- }
- }
- _update() {
- this._disable();
- let enablePrePass = false;
- this._scene.imageProcessingConfiguration.applyByPostProcess = false;
- if (this._scene._depthPeelingRenderer && this._scene.useOrderIndependentTransparency) {
- this._scene._depthPeelingRenderer.setPrePassRenderer(this);
- enablePrePass = true;
- }
- for (let i = 0; i < this._scene.materials.length; i++) {
- if (this._scene.materials[i].setPrePassRenderer(this)) {
- enablePrePass = true;
- }
- }
- if (enablePrePass) {
- this._setRenderTargetEnabled(this.defaultRT, true);
- }
- let postProcesses;
- for (let i = 0; i < this.renderTargets.length; i++) {
- if (this.renderTargets[i].renderTargetTexture) {
- postProcesses = this._getPostProcessesSource(this.renderTargets[i]);
- }
- else {
- const camera = this._scene.activeCamera;
- if (!camera) {
- continue;
- }
- postProcesses = camera._postProcesses;
- }
- if (!postProcesses) {
- continue;
- }
- postProcesses = postProcesses.filter((pp) => {
- return pp != null;
- });
- if (postProcesses) {
- for (let j = 0; j < postProcesses.length; j++) {
- if (postProcesses[j].setPrePassRenderer(this)) {
- this._setRenderTargetEnabled(this.renderTargets[i], true);
- enablePrePass = true;
- }
- }
- if (this._hasImageProcessing(postProcesses)) {
- this._scene.imageProcessingConfiguration.applyByPostProcess = true;
- }
- }
- }
- this._markAllMaterialsAsPrePassDirty();
- this._isDirty = false;
- if (enablePrePass) {
- this._enable();
- }
- }
- _markAllMaterialsAsPrePassDirty() {
- const materials = this._scene.materials;
- for (let i = 0; i < materials.length; i++) {
- materials[i].markAsDirty(Material.PrePassDirtyFlag);
- }
- }
- /**
- * Disposes the prepass renderer.
- */
- dispose() {
- for (let i = this.renderTargets.length - 1; i >= 0; i--) {
- this.renderTargets[i].dispose();
- }
- for (let i = 0; i < this._effectConfigurations.length; i++) {
- if (this._effectConfigurations[i].dispose) {
- this._effectConfigurations[i].dispose();
- }
- }
- }
- }
- /**
- * @internal
- */
- PrePassRenderer._SceneComponentInitialization = (_) => {
- throw _WarnImport("PrePassRendererSceneComponent");
- };
- /**
- * Describes the types and formats of the textures used by the pre-pass renderer
- */
- PrePassRenderer.TextureFormats = [
- {
- purpose: 0,
- type: 2,
- format: 5,
- name: "prePass_Irradiance",
- },
- {
- purpose: 1,
- type: 2,
- format: 5,
- name: "prePass_Position",
- },
- {
- purpose: 2,
- type: 0,
- format: 5,
- name: "prePass_Velocity",
- },
- {
- purpose: 3,
- type: 0,
- format: 5,
- name: "prePass_Reflectivity",
- },
- {
- purpose: 4,
- type: 2,
- format: 5,
- name: "prePass_Color",
- },
- {
- purpose: 5,
- type: 1,
- format: 6,
- name: "prePass_Depth",
- },
- {
- purpose: 6,
- type: 2,
- format: 5,
- name: "prePass_Normal",
- },
- {
- purpose: 7,
- type: 0,
- format: 5,
- name: "prePass_Albedo",
- },
- ];
- //# sourceMappingURL=prePassRenderer.js.map
|