Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OIT aliasing fixes #12916

Merged
merged 3 commits into from
Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 22 additions & 24 deletions packages/dev/core/src/Engines/Extensions/engine.multiRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ ThinEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function (
samples = Math.min(samples, this.getCaps().maxMSAASamples);

// Dispose previous render buffers
if (rtWrapper._depthStencilBuffer) {
const useDepthStencil = !!rtWrapper._depthStencilBuffer;
CraigFeldspar marked this conversation as resolved.
Show resolved Hide resolved
if (useDepthStencil) {
gl.deleteRenderbuffer(rtWrapper._depthStencilBuffer);
rtWrapper._depthStencilBuffer = null;
}
Expand All @@ -395,14 +396,6 @@ ThinEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function (
rtWrapper._MSAAFramebuffer = null;
}

for (let i = 0; i < count; i++) {
const hardwareTexture = rtWrapper.textures![i]._hardwareTexture as Nullable<WebGLHardwareTexture>;
if (hardwareTexture?._MSAARenderBuffer) {
gl.deleteRenderbuffer(hardwareTexture._MSAARenderBuffer);
hardwareTexture._MSAARenderBuffer = null;
}
}

if (samples > 1 && gl.renderbufferStorageMultisample) {
const framebuffer = gl.createFramebuffer();

Expand All @@ -420,14 +413,17 @@ ThinEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function (
const hardwareTexture = texture._hardwareTexture as WebGLHardwareTexture;
const attachment = (<any>gl)[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];

const colorRenderbuffer = this._createRenderBuffer(
texture.width,
texture.height,
samples,
-1 /* not used */,
this._getRGBAMultiSampleBufferFormat(texture.type),
attachment
);
const colorRenderbuffer = hardwareTexture._MSAARenderBuffer
CraigFeldspar marked this conversation as resolved.
Show resolved Hide resolved
? this._updateRenderBuffer(
hardwareTexture._MSAARenderBuffer,
texture.width,
texture.height,
samples,
-1 /* not used */,
this._getRGBAMultiSampleBufferFormat(texture.type),
attachment
)
: this._createRenderBuffer(texture.width, texture.height, samples, -1 /* not used */, this._getRGBAMultiSampleBufferFormat(texture.type), attachment);

if (!colorRenderbuffer) {
throw new Error("Unable to create multi sampled framebuffer");
Expand All @@ -445,13 +441,15 @@ ThinEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function (
this._bindUnboundFramebuffer(rtWrapper._framebuffer);
}

rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(
rtWrapper._generateStencilBuffer,
rtWrapper._generateDepthBuffer,
rtWrapper.texture.width,
rtWrapper.texture.height,
samples
);
if (useDepthStencil) {
rtWrapper._depthStencilBuffer = this._setupFramebufferDepthAttachments(
rtWrapper._generateStencilBuffer,
rtWrapper._generateDepthBuffer,
rtWrapper.texture.width,
rtWrapper.texture.height,
samples
);
}

this._bindUnboundFramebuffer(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class WebGLRenderTargetWrapper extends RenderTargetWrapper {

const gl = this._context;
const depthbuffer = this._depthStencilBuffer;
const framebuffer = renderTarget._framebuffer;
const framebuffer = renderTarget._MSAAFramebuffer || renderTarget._framebuffer;

if (renderTarget._depthStencilBuffer) {
gl.deleteRenderbuffer(renderTarget._depthStencilBuffer);
Expand Down
7 changes: 5 additions & 2 deletions packages/dev/core/src/Engines/renderTargetWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class RenderTargetWrapper {
private _isCube: boolean;
private _isMulti: boolean;
private _textures: Nullable<InternalTexture[]> = null;
private _samples = 1;

/** @hidden */
public _attachments: Nullable<number[]> = null;
Expand Down Expand Up @@ -118,7 +119,7 @@ export class RenderTargetWrapper {
* Gets the sample count of the render target
*/
public get samples(): number {
return this.texture?.samples ?? 1;
return this._samples;
}

/**
Expand All @@ -133,9 +134,11 @@ export class RenderTargetWrapper {
return value;
}

return this._isMulti
const result = this._isMulti
? this._engine.updateMultipleRenderTargetTextureSampleCount(this, value, initializeBuffers)
: this._engine.updateRenderTargetTextureSampleCount(this, value);
this._samples = value;
Popov72 marked this conversation as resolved.
Show resolved Hide resolved
return result;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions packages/dev/core/src/Engines/thinEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4847,6 +4847,20 @@ export class ThinEngine {
): Nullable<WebGLRenderbuffer> {
const gl = this._gl;
const renderBuffer = gl.createRenderbuffer();
return this._updateRenderBuffer(renderBuffer, width, height, samples, internalFormat, msInternalFormat, attachment, unbindBuffer);
}

public _updateRenderBuffer(
renderBuffer: Nullable<WebGLRenderbuffer>,
width: number,
height: number,
samples: number,
internalFormat: number,
msInternalFormat: number,
attachment: number,
unbindBuffer = true
): Nullable<WebGLRenderbuffer> {
const gl = this._gl;

gl.bindRenderbuffer(gl.RENDERBUFFER, renderBuffer);

Expand Down
41 changes: 34 additions & 7 deletions packages/dev/core/src/Rendering/depthPeelingRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { EffectRenderer, EffectWrapper } from "../Materials/effectRenderer";
import type { PrePassEffectConfiguration } from "./prePassEffectConfiguration";
import type { PrePassRenderer } from "./prePassRenderer";
import type { InternalTexture } from "../Materials/Textures/internalTexture";
import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
import { Logger } from "../Misc/logger";
import type { IMaterialContext } from "../Engines/IMaterialContext";
import type { DrawWrapper } from "../Materials/drawWrapper";
Expand Down Expand Up @@ -53,6 +54,7 @@ export class DepthPeelingRenderer {
private _thinTextures: ThinTexture[] = [];
private _colorMrts: MultiRenderTarget[];
private _blendBackMrt: MultiRenderTarget;
private _outputRT: RenderTargetTexture;

private _blendBackEffectWrapper: EffectWrapper;
private _blendBackEffectWrapperPingPong: EffectWrapper;
Expand Down Expand Up @@ -165,25 +167,26 @@ export class DepthPeelingRenderer {
};

// 2 for ping pong
this._depthMrts = [new MultiRenderTarget("depthPeelingDepth0", size, 1, this._scene), new MultiRenderTarget("depthPeelingDepth1", size, 1, this._scene)];
this._depthMrts = [new MultiRenderTarget("depthPeelingDepth0", size, 3, this._scene), new MultiRenderTarget("depthPeelingDepth1", size, 3, this._scene)];
this._colorMrts = [
new MultiRenderTarget("depthPeelingColor0", size, 1, this._scene, { generateDepthBuffer: false }),
new MultiRenderTarget("depthPeelingColor1", size, 1, this._scene, { generateDepthBuffer: false }),
new MultiRenderTarget("depthPeelingColor0", size, 2, this._scene, { generateDepthBuffer: false }),
new MultiRenderTarget("depthPeelingColor1", size, 2, this._scene, { generateDepthBuffer: false }),
];
this._blendBackMrt = new MultiRenderTarget("depthPeelingBack", size, 1, this._scene, { generateDepthBuffer: false });
this._outputRT = new RenderTargetTexture("depthPeelingOutput", size, this._scene, false);

// 0 is a depth texture
// 1 is a color texture
const optionsArray = [
{
format: Constants.TEXTUREFORMAT_RG,
format: Constants.TEXTUREFORMAT_RG, // For MSAA we need RGBA
CraigFeldspar marked this conversation as resolved.
Show resolved Hide resolved
samplingMode: Constants.TEXTURE_NEAREST_SAMPLINGMODE,
type: this._engine.getCaps().textureFloatLinearFiltering ? Constants.TEXTURETYPE_FLOAT : Constants.TEXTURETYPE_HALF_FLOAT,
sebavan marked this conversation as resolved.
Show resolved Hide resolved
} as InternalTextureCreationOptions,
{
format: Constants.TEXTUREFORMAT_RGBA,
samplingMode: Constants.TEXTURE_NEAREST_SAMPLINGMODE,
type: Constants.TEXTURETYPE_HALF_FLOAT,
type: Constants.TEXTURETYPE_HALF_FLOAT, // For MSAA we need FLOAT
CraigFeldspar marked this conversation as resolved.
Show resolved Hide resolved
} as InternalTextureCreationOptions,
];

Expand All @@ -195,14 +198,23 @@ export class DepthPeelingRenderer {
this._depthMrts[i].setInternalTexture(depthTexture, 0);
this._depthMrts[i].setInternalTexture(frontColorTexture, 1);
this._depthMrts[i].setInternalTexture(backColorTexture, 2);

this._colorMrts[i].setInternalTexture(frontColorTexture, 0);
this._colorMrts[i].setInternalTexture(backColorTexture, 1);

this._thinTextures.push(new ThinTexture(depthTexture), new ThinTexture(frontColorTexture), new ThinTexture(backColorTexture));
}
}

// TODO : explore again MSAA with depth peeling when
// we are able to fetch individual samples in a multisampled renderbuffer
// public set samples(value: number) {
// for (let i = 0; i < 2; i++) {
// this._depthMrts[i].samples = value;
// this._colorMrts[i].samples = value;
// }
// this._scene.prePassRenderer!.samples = value;
// }

private _disposeTextures() {
for (let i = 0; i < this._thinTextures.length; i++) {
if (i === 6) {
Expand All @@ -217,6 +229,7 @@ export class DepthPeelingRenderer {
this._colorMrts[i].dispose(true);
this._blendBackMrt.dispose(true);
}
this._outputRT.dispose();

this._thinTextures = [];
this._colorMrts = [];
Expand Down Expand Up @@ -353,7 +366,12 @@ export class DepthPeelingRenderer {
}

private _finalCompose(writeId: number) {
this._engine.restoreDefaultFramebuffer();
const output = this._scene.prePassRenderer?.setCustomOutput(this._outputRT);
if (output) {
this._engine.bindFramebuffer(this._outputRT.renderTarget!);
} else {
this._engine.restoreDefaultFramebuffer();
}

this._engine.setAlphaMode(Constants.ALPHA_DISABLE);
this._engine.applyStates();
Expand Down Expand Up @@ -411,18 +429,22 @@ export class DepthPeelingRenderer {
this._engine.bindFramebuffer(this._depthMrts[0].renderTarget!);
this._engine.bindAttachments(this._layoutCache[0]);
this._engine.clear(this._colorCache[0], true, false, false);
this._engine.unBindFramebuffer(this._depthMrts[0].renderTarget!);

this._engine.bindFramebuffer(this._depthMrts[1].renderTarget!);
this._engine.bindAttachments(this._layoutCache[0]);
this._engine.clear(this._colorCache[1], true, false, false);
this._engine.unBindFramebuffer(this._depthMrts[1].renderTarget!);

this._engine.bindFramebuffer(this._colorMrts[0].renderTarget!);
this._engine.bindAttachments(this._layoutCache[1]);
this._engine.clear(this._colorCache[2], true, false, false);
this._engine.unBindFramebuffer(this._colorMrts[0].renderTarget!);

this._engine.bindFramebuffer(this._colorMrts[1].renderTarget!);
this._engine.bindAttachments(this._layoutCache[1]);
this._engine.clear(this._colorCache[2], true, false, false);
this._engine.unBindFramebuffer(this._colorMrts[1].renderTarget!);

// Draw depth for first pass
this._engine.bindFramebuffer(this._depthMrts[0].renderTarget!);
Expand All @@ -437,6 +459,7 @@ export class DepthPeelingRenderer {
this._currentPingPongState = 1;
// Render
this._renderSubMeshes(this._candidateSubMeshes);
this._engine.unBindFramebuffer(this._depthMrts[0].renderTarget!);

this._scene.resetCachedMaterial();

Expand All @@ -457,10 +480,12 @@ export class DepthPeelingRenderer {
this._engine.bindFramebuffer(this._depthMrts[writeId].renderTarget!);
this._engine.bindAttachments(this._layoutCache[0]);
this._engine.clear(this._colorCache[0], true, false, false);
this._engine.unBindFramebuffer(this._depthMrts[writeId].renderTarget!);

this._engine.bindFramebuffer(this._colorMrts[writeId].renderTarget!);
this._engine.bindAttachments(this._layoutCache[1]);
this._engine.clear(this._colorCache[2], true, false, false);
this._engine.unBindFramebuffer(this._colorMrts[writeId].renderTarget!);

this._engine.bindFramebuffer(this._depthMrts[writeId].renderTarget!);
this._engine.bindAttachments(this._layoutCache[2]);
Expand All @@ -472,6 +497,7 @@ export class DepthPeelingRenderer {

// Render
this._renderSubMeshes(this._candidateSubMeshes);
this._engine.unBindFramebuffer(this._depthMrts[writeId].renderTarget!);

this._scene.resetCachedMaterial();

Expand All @@ -486,6 +512,7 @@ export class DepthPeelingRenderer {
this._engine.enableEffect(blendBackEffectWrapper._drawWrapper);
blendBackEffectWrapper.effect.setTexture("uBackColor", this._thinTextures[writeId * 3 + 2]);
this._effectRenderer.render(blendBackEffectWrapper);
this._engine.unBindFramebuffer(this._blendBackMrt.renderTarget!);
}

this._engine.currentRenderPassId = currentRenderPassId;
Expand Down
18 changes: 18 additions & 0 deletions packages/dev/core/src/Rendering/prePassRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,24 @@ export class PrePassRenderer {
}
}

/**
* Sets an intermediary texture between prepass and postprocesses. This texture
* will be used as input for post processes
* @param rt
* @returns true if there are postprocesses that will use this texture,
* false if there is no postprocesses - and the function has no effect
*/
public setCustomOutput(rt: RenderTargetTexture) {
const firstPP = this._postProcessesSourceForThisPass[0];
if (!firstPP) {
return false;
}

firstPP.inputTexture = rt.renderTarget!;

return true;
}

private _renderPostProcesses(prePassRenderTarget: PrePassRenderTarget, faceIndex?: number) {
const firstPP = this._postProcessesSourceForThisPass[0];
const outputTexture = firstPP ? firstPP.inputTexture : prePassRenderTarget.renderTargetTexture ? prePassRenderTarget.renderTargetTexture.renderTarget : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
// alpha is cleared to 0, and we want to initialize alpha to 1.
// The operation will be canceled in the fragment shader by writing 1 - a for the next passes
float alphaMultiplier = 1.0 - lastFrontColor.a;

#ifdef USE_REVERSE_DEPTHBUFFER
if (fragDepth > nearestDepth || fragDepth < furthestDepth) {
#else
Expand Down