|
@@ -13,6 +13,7 @@ import { Material } from '../Materials/material';
|
|
import { SubMesh } from '../Meshes/subMesh';
|
|
import { SubMesh } from '../Meshes/subMesh';
|
|
import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
|
|
import { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
|
|
import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
|
|
import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
|
|
|
|
+import { GeometryBufferRenderer } from '../Rendering/geometryBufferRenderer';
|
|
|
|
|
|
/**
|
|
/**
|
|
* Renders a pre pass of the scene
|
|
* Renders a pre pass of the scene
|
|
@@ -42,13 +43,74 @@ export class PrePassRenderer {
|
|
private _engine: Engine;
|
|
private _engine: Engine;
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * Number of textures in the multi render target texture where the scene is directly rendered
|
|
|
|
+ */
|
|
|
|
+ public mrtCount: number = 0;
|
|
|
|
+
|
|
|
|
+ public _mrtFormats: number[] = [];
|
|
|
|
+ public _mrtLayout: number[];
|
|
|
|
+ public _textureIndices: number[] = [];
|
|
|
|
+
|
|
|
|
+ public _multiRenderAttachments: number[];
|
|
|
|
+ public _defaultAttachments: number[];
|
|
|
|
+ public _clearAttachments: number[];
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Returns the index of a texture in the multi render target texture array.
|
|
|
|
+ * @param type Texture type
|
|
|
|
+ * @return The index
|
|
|
|
+ */
|
|
|
|
+ public getIndex(type: number) : number {
|
|
|
|
+ return this._textureIndices[type];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static _textureFormats = [
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_IRRADIANCE_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_HALF_FLOAT,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_POSITION_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_HALF_FLOAT,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_VELOCITY_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_HALF_FLOAT,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_UNSIGNED_INT,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_COLOR_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_HALF_FLOAT,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_HALF_FLOAT,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: Constants.PREPASS_ALBEDO_TEXTURE_TYPE,
|
|
|
|
+ format: Constants.TEXTURETYPE_UNSIGNED_INT,
|
|
|
|
+ },
|
|
|
|
+ ];
|
|
|
|
+
|
|
|
|
+ private _isDirty: boolean = true;
|
|
|
|
+
|
|
|
|
+ /**
|
|
* The render target where the scene is directly rendered
|
|
* The render target where the scene is directly rendered
|
|
*/
|
|
*/
|
|
public defaultRT: PrePassRenderTarget;
|
|
public defaultRT: PrePassRenderTarget;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Returns the prepass render target for the rendering pass.
|
|
|
|
- * If we are currently rendering a render target, it returns the PrePassRenderTarget
|
|
|
|
|
|
+ * TODO : public ?
|
|
|
|
+ * Configuration for prepass effects
|
|
|
|
+ */
|
|
|
|
+ private _effectConfigurations: PrePassEffectConfiguration[] = [];
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 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
|
|
* associated with that render target. Otherwise, it returns the scene default PrePassRenderTarget
|
|
*/
|
|
*/
|
|
public getRenderTarget(): PrePassRenderTarget {
|
|
public getRenderTarget(): PrePassRenderTarget {
|
|
@@ -63,6 +125,47 @@ export class PrePassRenderer {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Returns true if the currently rendered prePassRenderTarget is the one
|
|
|
|
+ * associated with the scene.
|
|
|
|
+ */
|
|
|
|
+ public get currentRTisSceneRT(): boolean {
|
|
|
|
+ return this._currentTarget === this.defaultRT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public _geometryBuffer: Nullable<GeometryBufferRenderer>;
|
|
|
|
+ public _useGeometryBufferFallback = false;
|
|
|
|
+ /**
|
|
|
|
+ * Uses the geometry buffer renderer as a fallback for non prepass capable effects
|
|
|
|
+ */
|
|
|
|
+ public get useGeometryBufferFallback() : boolean {
|
|
|
|
+ return this._useGeometryBufferFallback;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public set useGeometryBufferFallback(value: boolean) {
|
|
|
|
+ this._useGeometryBufferFallback = value;
|
|
|
|
+
|
|
|
|
+ if (value) {
|
|
|
|
+ this._geometryBuffer = this._scene.enableGeometryBufferRenderer();
|
|
|
|
+
|
|
|
|
+ if (!this._geometryBuffer) {
|
|
|
|
+ // Not supported
|
|
|
|
+ this._useGeometryBufferFallback = false;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this._geometryBuffer.renderList = [];
|
|
|
|
+ this._geometryBuffer._linkPrePassRenderer(this);
|
|
|
|
+ this._updateGeometryBufferLayout();
|
|
|
|
+ } else {
|
|
|
|
+ if (this._geometryBuffer) {
|
|
|
|
+ this._geometryBuffer._unlinkPrePassRenderer();
|
|
|
|
+ }
|
|
|
|
+ this._geometryBuffer = null;
|
|
|
|
+ this._scene.disableGeometryBufferRenderer();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private _currentTarget: PrePassRenderTarget;
|
|
private _currentTarget: PrePassRenderTarget;
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -99,12 +202,12 @@ export class PrePassRenderer {
|
|
this._engine = scene.getEngine();
|
|
this._engine = scene.getEngine();
|
|
|
|
|
|
PrePassRenderer._SceneComponentInitialization(this._scene);
|
|
PrePassRenderer._SceneComponentInitialization(this._scene);
|
|
- this.defaultRT = this._createRenderTarget("sceneprePassRT");
|
|
|
|
|
|
+ this.defaultRT = this._createRenderTarget("sceneprePassRT", null);
|
|
this._setRenderTarget(null);
|
|
this._setRenderTarget(null);
|
|
}
|
|
}
|
|
|
|
|
|
- public _createRenderTarget(name: string) : PrePassRenderTarget {
|
|
|
|
- const rt = new PrePassRenderTarget(name, this, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene,
|
|
|
|
|
|
+ public _createRenderTarget(name: string, renderTargetTexture: Nullable<RenderTargetTexture>) : PrePassRenderTarget {
|
|
|
|
+ const rt = new PrePassRenderTarget(name, renderTargetTexture, { width: this._engine.getRenderWidth(), height: this._engine.getRenderHeight() }, 0, this._scene,
|
|
{ generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: [] });
|
|
{ generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: [] });
|
|
rt.samples = 1;
|
|
rt.samples = 1;
|
|
|
|
|
|
@@ -127,9 +230,9 @@ export class PrePassRenderer {
|
|
public bindAttachmentsForEffect(effect: Effect, subMesh: SubMesh) {
|
|
public bindAttachmentsForEffect(effect: Effect, subMesh: SubMesh) {
|
|
if (this.enabled && this._currentTarget.enabled) {
|
|
if (this.enabled && this._currentTarget.enabled) {
|
|
if (effect._multiTarget) {
|
|
if (effect._multiTarget) {
|
|
- this._engine.bindAttachments(this._currentTarget._multiRenderAttachments);
|
|
|
|
|
|
+ this._engine.bindAttachments(this._multiRenderAttachments);
|
|
} else {
|
|
} else {
|
|
- this._engine.bindAttachments(this._currentTarget._defaultAttachments);
|
|
|
|
|
|
+ this._engine.bindAttachments(this._defaultAttachments);
|
|
|
|
|
|
// TODO : geometry buffer renderer
|
|
// TODO : geometry buffer renderer
|
|
// if (this._geometryBuffer) {
|
|
// if (this._geometryBuffer) {
|
|
@@ -142,12 +245,86 @@ export class PrePassRenderer {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private _reinitializeAttachments() {
|
|
|
|
+ const multiRenderLayout = [];
|
|
|
|
+ const clearLayout = [false];
|
|
|
|
+ const defaultLayout = [true];
|
|
|
|
+
|
|
|
|
+ for (let i = 0; i < this.mrtCount; i++) {
|
|
|
|
+ multiRenderLayout.push(true);
|
|
|
|
+
|
|
|
|
+ if (i > 0) {
|
|
|
|
+ clearLayout.push(true);
|
|
|
|
+ defaultLayout.push(false);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this._multiRenderAttachments = this._engine.buildTextureLayout(multiRenderLayout);
|
|
|
|
+ this._clearAttachments = this._engine.buildTextureLayout(clearLayout);
|
|
|
|
+ this._defaultAttachments = this._engine.buildTextureLayout(defaultLayout);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private _resetLayout() {
|
|
|
|
+ for (let i = 0 ; i < PrePassRenderer._textureFormats.length; i++) {
|
|
|
|
+ this._textureIndices[PrePassRenderer._textureFormats[i].type] = -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this._textureIndices[Constants.PREPASS_COLOR_TEXTURE_TYPE] = 0;
|
|
|
|
+ this._mrtLayout = [Constants.PREPASS_COLOR_TEXTURE_TYPE];
|
|
|
|
+ this._mrtFormats = [Constants.TEXTURETYPE_HALF_FLOAT];
|
|
|
|
+ this.mrtCount = 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private _updateGeometryBufferLayout() {
|
|
|
|
+ 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: Constants.PREPASS_DEPTHNORMAL_TEXTURE_TYPE,
|
|
|
|
+ geometryBufferConstant: GeometryBufferRenderer.DEPTHNORMAL_TEXTURE_TYPE,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ prePassConstant: Constants.PREPASS_POSITION_TEXTURE_TYPE,
|
|
|
|
+ geometryBufferConstant: GeometryBufferRenderer.POSITION_TEXTURE_TYPE,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ prePassConstant: Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE,
|
|
|
|
+ geometryBufferConstant: GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ prePassConstant: Constants.PREPASS_VELOCITY_TEXTURE_TYPE,
|
|
|
|
+ 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.
|
|
* Restores attachments for single texture draw.
|
|
*/
|
|
*/
|
|
public restoreAttachments() {
|
|
public restoreAttachments() {
|
|
- if (this.enabled && this._currentTarget._defaultAttachments) {
|
|
|
|
- this._engine.bindAttachments(this._currentTarget._defaultAttachments);
|
|
|
|
|
|
+ if (this.enabled && this._defaultAttachments) {
|
|
|
|
+ this._engine.bindAttachments(this._defaultAttachments);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -157,11 +334,11 @@ export class PrePassRenderer {
|
|
public _beforeDraw(camera: Nullable<Camera>, texture: Nullable<RenderTargetTexture>) {
|
|
public _beforeDraw(camera: Nullable<Camera>, texture: Nullable<RenderTargetTexture>) {
|
|
let postProcesses = undefined;
|
|
let postProcesses = undefined;
|
|
if (texture) {
|
|
if (texture) {
|
|
- postProcesses = texture.postProcesses || texture.activeCamera?._postProcesses || [];
|
|
|
|
- }
|
|
|
|
|
|
+ postProcesses = texture.postProcesses || texture.activeCamera?._postProcesses || [];
|
|
|
|
+ }
|
|
|
|
|
|
- if (this._currentTarget._isDirty) {
|
|
|
|
- this._update(this._currentTarget, postProcesses);
|
|
|
|
|
|
+ if (this._isDirty) {
|
|
|
|
+ this._update();
|
|
}
|
|
}
|
|
|
|
|
|
if (!this._enabled || !this._currentTarget.enabled) {
|
|
if (!this._enabled || !this._currentTarget.enabled) {
|
|
@@ -178,8 +355,8 @@ export class PrePassRenderer {
|
|
}
|
|
}
|
|
|
|
|
|
// TODO : handle geometry buffer renderer fallback
|
|
// TODO : handle geometry buffer renderer fallback
|
|
- if (this._currentTarget._geometryBuffer) {
|
|
|
|
- this._currentTarget._geometryBuffer.renderList!.length = 0;
|
|
|
|
|
|
+ if (this._geometryBuffer) {
|
|
|
|
+ this._geometryBuffer.renderList!.length = 0;
|
|
}
|
|
}
|
|
|
|
|
|
this._setupOutputForThisPass(this._currentTarget, camera, postProcesses);
|
|
this._setupOutputForThisPass(this._currentTarget, camera, postProcesses);
|
|
@@ -211,7 +388,7 @@ export class PrePassRenderer {
|
|
this._scene.postProcessManager._prepareFrame(this._currentTarget.getInternalTexture()!, postProcessChain);
|
|
this._scene.postProcessManager._prepareFrame(this._currentTarget.getInternalTexture()!, postProcessChain);
|
|
}
|
|
}
|
|
|
|
|
|
- // Renders the post process chain
|
|
|
|
|
|
+ // Renders the post process chain
|
|
this._scene.postProcessManager.directRender(postProcessChain, outputTexture);
|
|
this._scene.postProcessManager.directRender(postProcessChain, outputTexture);
|
|
|
|
|
|
if (!outputTexture) {
|
|
if (!outputTexture) {
|
|
@@ -221,18 +398,19 @@ export class PrePassRenderer {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Clears the render target (in the sense of settings pixels to the scene clear color value)
|
|
|
|
|
|
+ * Clears the current prepass render target (in the sense of settings pixels to the scene clear color value)
|
|
|
|
+ * @hidden
|
|
*/
|
|
*/
|
|
public _clear() {
|
|
public _clear() {
|
|
if (this._enabled && this._currentTarget.enabled) {
|
|
if (this._enabled && this._currentTarget.enabled) {
|
|
this._bindFrameBuffer(this._currentTarget);
|
|
this._bindFrameBuffer(this._currentTarget);
|
|
|
|
|
|
// Clearing other attachment with 0 on all other attachments
|
|
// Clearing other attachment with 0 on all other attachments
|
|
- this._engine.bindAttachments(this._currentTarget._clearAttachments);
|
|
|
|
|
|
+ this._engine.bindAttachments(this._clearAttachments);
|
|
this._engine.clear(this._clearColor, true, false, false);
|
|
this._engine.clear(this._clearColor, true, false, false);
|
|
|
|
|
|
// Regular clear color with the scene clear color of the 1st attachment
|
|
// Regular clear color with the scene clear color of the 1st attachment
|
|
- this._engine.bindAttachments(this._currentTarget._defaultAttachments);
|
|
|
|
|
|
+ this._engine.bindAttachments(this._defaultAttachments);
|
|
this._engine.clear(this._scene.clearColor,
|
|
this._engine.clear(this._scene.clearColor,
|
|
this._scene.autoClear || this._scene.forceWireframe || this._scene.forcePointsCloud,
|
|
this._scene.autoClear || this._scene.forceWireframe || this._scene.forcePointsCloud,
|
|
this._scene.autoClearDepthAndStencil,
|
|
this._scene.autoClearDepthAndStencil,
|
|
@@ -250,74 +428,88 @@ export class PrePassRenderer {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private _setState(prePassRenderTarget: PrePassRenderTarget, enabled: boolean) {
|
|
|
|
|
|
+ private _setState(enabled: boolean) {
|
|
this._enabled = enabled;
|
|
this._enabled = enabled;
|
|
|
|
|
|
- prePassRenderTarget.enabled = enabled;
|
|
|
|
|
|
+ // TODO : enable/disable per texture
|
|
|
|
+ for (let i = 0; i < this.renderTargets.length; i++) {
|
|
|
|
+ const prePassRenderTarget = this.renderTargets[i];
|
|
|
|
+
|
|
|
|
+ prePassRenderTarget.enabled = enabled;
|
|
|
|
|
|
- if (prePassRenderTarget.imageProcessingPostProcess) {
|
|
|
|
- prePassRenderTarget.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = enabled;
|
|
|
|
|
|
+ if (prePassRenderTarget.imageProcessingPostProcess) {
|
|
|
|
+ prePassRenderTarget.imageProcessingPostProcess.imageProcessingConfiguration.applyByPostProcess = enabled;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Adds an effect configuration to the current prepass render target.
|
|
|
|
|
|
+ * 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
|
|
* If an effect has already been added, it won't add it twice and will return the configuration
|
|
* already present.
|
|
* already present.
|
|
* @param cfg the effect configuration
|
|
* @param cfg the effect configuration
|
|
* @return the effect configuration now used by the prepass
|
|
* @return the effect configuration now used by the prepass
|
|
*/
|
|
*/
|
|
- public addEffectConfiguration(effectConfiguration: PrePassEffectConfiguration): PrePassEffectConfiguration {
|
|
|
|
- return this.getRenderTarget()._addEffectConfiguration(effectConfiguration);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private _enable(prePassRenderTarget: PrePassRenderTarget) {
|
|
|
|
- const previousMrtCount = prePassRenderTarget.mrtCount;
|
|
|
|
-
|
|
|
|
- for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
|
|
|
|
- if (prePassRenderTarget._effectConfigurations[i].enabled) {
|
|
|
|
- this._enableTextures(prePassRenderTarget, prePassRenderTarget._effectConfigurations[i].texturesRequired);
|
|
|
|
|
|
+ public addEffectConfiguration(cfg: PrePassEffectConfiguration) : PrePassEffectConfiguration {
|
|
|
|
+ // Do not add twice
|
|
|
|
+ for (let i = 0; i < this._effectConfigurations.length; i++) {
|
|
|
|
+ if (this._effectConfigurations[i].name === cfg.name) {
|
|
|
|
+ return this._effectConfigurations[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (prePassRenderTarget.mrtCount !== previousMrtCount) {
|
|
|
|
- prePassRenderTarget.updateCount(prePassRenderTarget.mrtCount, { types: prePassRenderTarget._mrtFormats });
|
|
|
|
- }
|
|
|
|
|
|
+ this._effectConfigurations.push(cfg);
|
|
|
|
+ return cfg;
|
|
|
|
+ }
|
|
|
|
|
|
- prePassRenderTarget._updateGeometryBufferLayout();
|
|
|
|
- prePassRenderTarget._resetPostProcessChain();
|
|
|
|
|
|
+ private _enable() {
|
|
|
|
+ const previousMrtCount = this.mrtCount;
|
|
|
|
|
|
- for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
|
|
|
|
- if (prePassRenderTarget._effectConfigurations[i].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 (!prePassRenderTarget._effectConfigurations[i].postProcess && prePassRenderTarget._effectConfigurations[i].createPostProcess) {
|
|
|
|
- prePassRenderTarget._effectConfigurations[i].createPostProcess!();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (prePassRenderTarget._effectConfigurations[i].postProcess) {
|
|
|
|
- prePassRenderTarget._beforeCompositionPostProcesses.push(prePassRenderTarget._effectConfigurations[i].postProcess!);
|
|
|
|
- }
|
|
|
|
|
|
+ for (let i = 0; i < this._effectConfigurations.length; i++) {
|
|
|
|
+ if (this._effectConfigurations[i].enabled) {
|
|
|
|
+ this._enableTextures(this._effectConfigurations[i].texturesRequired);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- prePassRenderTarget._reinitializeAttachments();
|
|
|
|
|
|
+ for (let i = 0; i < this.renderTargets.length; i++) {
|
|
|
|
+ if (this.mrtCount !== previousMrtCount) {
|
|
|
|
+ this.renderTargets[i].updateCount(this.mrtCount, { types: this._mrtFormats });
|
|
|
|
+ }
|
|
|
|
+ // TODO : gbr
|
|
|
|
+ this._updateGeometryBufferLayout();
|
|
|
|
+ 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!);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- if (!prePassRenderTarget.imageProcessingPostProcess) {
|
|
|
|
- prePassRenderTarget._createCompositionEffect();
|
|
|
|
|
|
+ if (!this.renderTargets[i].imageProcessingPostProcess) {
|
|
|
|
+ this.renderTargets[i]._createCompositionEffect();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- this._setState(prePassRenderTarget, true);
|
|
|
|
|
|
+ this._reinitializeAttachments();
|
|
|
|
+ this._setState(true);
|
|
}
|
|
}
|
|
|
|
|
|
- private _disable(prePassRenderTarget: PrePassRenderTarget) {
|
|
|
|
- this._setState(prePassRenderTarget, false);
|
|
|
|
|
|
+ private _disable() {
|
|
|
|
+ this._setState(false);
|
|
|
|
|
|
- prePassRenderTarget._resetLayout();
|
|
|
|
|
|
+ this._resetLayout();
|
|
|
|
|
|
- for (let i = 0; i < prePassRenderTarget._effectConfigurations.length; i++) {
|
|
|
|
- prePassRenderTarget._effectConfigurations[i].enabled = false;
|
|
|
|
|
|
+ for (let i = 0; i < this._effectConfigurations.length; i++) {
|
|
|
|
+ this._effectConfigurations[i].enabled = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -339,8 +531,8 @@ export class PrePassRenderer {
|
|
// Order is : draw ===> prePassRenderTarget._postProcesses ==> ipp ==> camera._postProcesses
|
|
// Order is : draw ===> prePassRenderTarget._postProcesses ==> ipp ==> camera._postProcesses
|
|
const secondaryCamera = camera && this._scene.activeCameras && !!this._scene.activeCameras.length && this._scene.activeCameras.indexOf(camera) !== 0;
|
|
const secondaryCamera = camera && this._scene.activeCameras && !!this._scene.activeCameras.length && this._scene.activeCameras.indexOf(camera) !== 0;
|
|
const postProcessesSource = camera ? camera._postProcesses : postProcesses;
|
|
const postProcessesSource = camera ? camera._postProcesses : postProcesses;
|
|
- this._needsCompositionForThisPass = !this._hasImageProcessing(postProcessesSource) &&
|
|
|
|
- !this.disableGammaTransform &&
|
|
|
|
|
|
+ this._needsCompositionForThisPass = !this._hasImageProcessing(postProcessesSource) &&
|
|
|
|
+ !this.disableGammaTransform &&
|
|
!secondaryCamera;
|
|
!secondaryCamera;
|
|
const firstCameraPP = this._getFirstPostProcess(postProcessesSource);
|
|
const firstCameraPP = this._getFirstPostProcess(postProcessesSource);
|
|
const firstPrePassPP = prePassRenderTarget._beforeCompositionPostProcesses && prePassRenderTarget._beforeCompositionPostProcesses[0];
|
|
const firstPrePassPP = prePassRenderTarget._beforeCompositionPostProcesses && prePassRenderTarget._beforeCompositionPostProcesses[0];
|
|
@@ -359,7 +551,7 @@ export class PrePassRenderer {
|
|
firstCameraPP.inputTexture = prePassRenderTarget.getInternalTexture()!;
|
|
firstCameraPP.inputTexture = prePassRenderTarget.getInternalTexture()!;
|
|
firstPP = firstCameraPP;
|
|
firstPP = firstCameraPP;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
if (firstPP) {
|
|
if (firstPP) {
|
|
firstPP.autoClear = false;
|
|
firstPP.autoClear = false;
|
|
}
|
|
}
|
|
@@ -397,30 +589,28 @@ export class PrePassRenderer {
|
|
* Marks the prepass renderer as dirty, triggering a check if the prepass is necessary for the next rendering.
|
|
* Marks the prepass renderer as dirty, triggering a check if the prepass is necessary for the next rendering.
|
|
*/
|
|
*/
|
|
public markAsDirty() {
|
|
public markAsDirty() {
|
|
- for (let i = 0; i < this.renderTargets.length; i++) {
|
|
|
|
- this.renderTargets[i]._isDirty = true;
|
|
|
|
- }
|
|
|
|
|
|
+ this._isDirty = true;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Enables a texture on the MultiRenderTarget for prepass
|
|
* Enables a texture on the MultiRenderTarget for prepass
|
|
*/
|
|
*/
|
|
- private _enableTextures(prePassRenderTarget: PrePassRenderTarget, types: number[]) {
|
|
|
|
|
|
+ private _enableTextures(types: number[]) {
|
|
for (let i = 0; i < types.length; i++) {
|
|
for (let i = 0; i < types.length; i++) {
|
|
let type = types[i];
|
|
let type = types[i];
|
|
|
|
|
|
- if (prePassRenderTarget._textureIndices[type] === -1) {
|
|
|
|
- prePassRenderTarget._textureIndices[type] = prePassRenderTarget._mrtLayout.length;
|
|
|
|
- prePassRenderTarget._mrtLayout.push(type);
|
|
|
|
|
|
+ if (this._textureIndices[type] === -1) {
|
|
|
|
+ this._textureIndices[type] = this._mrtLayout.length;
|
|
|
|
+ this._mrtLayout.push(type);
|
|
|
|
|
|
- prePassRenderTarget._mrtFormats.push(PrePassRenderTarget._textureFormats[type].format);
|
|
|
|
- prePassRenderTarget.mrtCount++;
|
|
|
|
|
|
+ this._mrtFormats.push(PrePassRenderer._textureFormats[type].format);
|
|
|
|
+ this.mrtCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private _update(prePassRenderTarget: PrePassRenderTarget, forcePostProcesses?: PostProcess[]) {
|
|
|
|
- this._disable(prePassRenderTarget);
|
|
|
|
|
|
+ private _update() {
|
|
|
|
+ this._disable();
|
|
let enablePrePass = false;
|
|
let enablePrePass = false;
|
|
|
|
|
|
for (let i = 0; i < this._scene.materials.length; i++) {
|
|
for (let i = 0; i < this._scene.materials.length; i++) {
|
|
@@ -431,32 +621,38 @@ export class PrePassRenderer {
|
|
|
|
|
|
let postProcesses;
|
|
let postProcesses;
|
|
|
|
|
|
- if (forcePostProcesses) {
|
|
|
|
- postProcesses = forcePostProcesses;
|
|
|
|
- } else {
|
|
|
|
- const camera = this._scene.activeCamera;
|
|
|
|
- if (!camera) {
|
|
|
|
- return;
|
|
|
|
|
|
+ for (let i = 0; i < this.renderTargets.length; i++) {
|
|
|
|
+ if (this.renderTargets[i].renderTargetTexture) {
|
|
|
|
+ postProcesses = this.renderTargets[i].renderTargetTexture!.activeCamera?._postProcesses;
|
|
|
|
+ } else {
|
|
|
|
+ const camera = this._scene.activeCamera;
|
|
|
|
+ if (!camera) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ postProcesses = camera._postProcesses;
|
|
}
|
|
}
|
|
|
|
|
|
- postProcesses = camera._postProcesses;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!postProcesses) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
|
|
- postProcesses = (<Nullable<PostProcess[]>>postProcesses.filter((pp) => { return pp != null; }));
|
|
|
|
|
|
+ postProcesses = (<Nullable<PostProcess[]>>postProcesses.filter((pp) => { return pp != null; }));
|
|
|
|
|
|
- if (postProcesses) {
|
|
|
|
- for (let i = 0; i < postProcesses.length; i++) {
|
|
|
|
- if (postProcesses[i].setPrePassRenderer(this)) {
|
|
|
|
- enablePrePass = true;
|
|
|
|
|
|
+ if (postProcesses) {
|
|
|
|
+ for (let i = 0; i < postProcesses.length; i++) {
|
|
|
|
+ if (postProcesses[i].setPrePassRenderer(this)) {
|
|
|
|
+ enablePrePass = true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
this._markAllMaterialsAsPrePassDirty();
|
|
this._markAllMaterialsAsPrePassDirty();
|
|
- prePassRenderTarget._isDirty = false;
|
|
|
|
|
|
+ this._isDirty = false;
|
|
|
|
|
|
if (enablePrePass) {
|
|
if (enablePrePass) {
|
|
- this._enable(prePassRenderTarget);
|
|
|
|
|
|
+ this._enable();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -473,13 +669,13 @@ export class PrePassRenderer {
|
|
*/
|
|
*/
|
|
public dispose() {
|
|
public dispose() {
|
|
for (let i = this.renderTargets.length - 1; i >= 0; i--) {
|
|
for (let i = this.renderTargets.length - 1; i >= 0; i--) {
|
|
|
|
+ this.renderTargets[i].dispose();
|
|
|
|
+ }
|
|
|
|
|
|
- for (let j = 0; j < this.renderTargets[i]._effectConfigurations.length; j++) {
|
|
|
|
- if (this.renderTargets[i]._effectConfigurations[j].dispose) {
|
|
|
|
- this.renderTargets[i]._effectConfigurations[j].dispose!();
|
|
|
|
- }
|
|
|
|
|
|
+ for (let i = 0; i < this._effectConfigurations.length; i++) {
|
|
|
|
+ if (this._effectConfigurations[i].dispose) {
|
|
|
|
+ this._effectConfigurations[i].dispose!();
|
|
}
|
|
}
|
|
- this.renderTargets[i].dispose();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|