Skip to content

Commit

Permalink
Merge pull request #15587 from MiiBond/mbond/ssr-screen-space-depth
Browse files Browse the repository at this point in the history
Add option to use screen space depth for SSR
  • Loading branch information
Popov72 authored Sep 25, 2024
2 parents 51fe830 + de406ef commit d2d49e8
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
this._updateEffectDefines();
}

private _useScreenspaceDepth = false;

@serialize("environmentTexture")
private _environmentTexture: Nullable<CubeTexture>;

Expand Down Expand Up @@ -629,8 +631,9 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
* @param cameras The array of cameras that the rendering pipeline will be attached to (default: scene.cameras)
* @param forceGeometryBuffer Set to true if you want to use the legacy geometry buffer renderer (default: false)
* @param textureType The texture type used by the different post processes created by SSR (default: Constants.TEXTURETYPE_UNSIGNED_BYTE)
* @param useScreenspaceDepth Indicates if the depth buffer should be linear or screenspace (default: false). This allows sharing the buffer with other effect pipelines that may require the depth to be in screenspace.
*/
constructor(name: string, scene: Scene, cameras?: Camera[], forceGeometryBuffer = false, textureType = Constants.TEXTURETYPE_UNSIGNED_BYTE) {
constructor(name: string, scene: Scene, cameras?: Camera[], forceGeometryBuffer = false, textureType = Constants.TEXTURETYPE_UNSIGNED_BYTE, useScreenspaceDepth = false) {
super(scene.getEngine(), name);

this._cameras = cameras || scene.cameras;
Expand All @@ -640,6 +643,7 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
this._scene = scene;
this._textureType = textureType;
this._forceGeometryBuffer = forceGeometryBuffer;
this._useScreenspaceDepth = useScreenspaceDepth;

if (this.isSupported) {
scene.postProcessRenderPipelineManager.addPipeline(this);
Expand All @@ -649,6 +653,8 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
if (geometryBufferRenderer) {
geometryBufferRenderer.enableReflectivity = true;
geometryBufferRenderer.useSpecificClearForDepthTexture = true;
geometryBufferRenderer.enableScreenspaceDepth = this._useScreenspaceDepth;
geometryBufferRenderer.enableDepth = !this._useScreenspaceDepth;
}
} else {
const prePassRenderer = scene.enablePrePassRenderer();
Expand Down Expand Up @@ -738,6 +744,9 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
if (this._scene.useRightHandedSystem) {
defines.push("#define SSRAYTRACE_RIGHT_HANDED_SCENE");
}
if (this._useScreenspaceDepth) {
defines.push("#define SSRAYTRACE_SCREENSPACE_DEPTH");
}
if (this._environmentTexture) {
defines.push("#define SSR_USE_ENVIRONMENT_CUBE");
if (this._environmentTexture.boundingBoxSize) {
Expand Down Expand Up @@ -835,8 +844,18 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {

if (camera) {
this._depthRendererCamera = camera;
this._depthRenderer = new DepthRenderer(this._scene, undefined, undefined, undefined, Constants.TEXTURE_NEAREST_SAMPLINGMODE, true, "SSRBackDepth");
this._depthRenderer.clearColor.r = 1e8; // "infinity": put a big value because we use the storeCameraSpaceZ mode
this._depthRenderer = new DepthRenderer(
this._scene,
undefined,
undefined,
this._useScreenspaceDepth,
Constants.TEXTURE_NEAREST_SAMPLINGMODE,
!this._useScreenspaceDepth,
"SSRBackDepth"
);
if (!this._useScreenspaceDepth) {
this._depthRenderer.clearColor.r = 1e8; // "infinity": put a big value because we use the storeCameraSpaceZ mode
}
this._depthRenderer.reverseCulling = true; // we generate depth for the back faces
this._depthRenderer.forceDepthWriteTransparentMeshes = this._backfaceForceDepthWriteTransparentMeshes;

Expand Down Expand Up @@ -950,6 +969,7 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
"roughnessFactor",
"projectionPixel",
"nearPlaneZ",
"farPlaneZ",
"maxDistance",
"selfCollisionNumSkip",
"vReflectionPosition",
Expand Down Expand Up @@ -994,11 +1014,18 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
if (geometryBufferRenderer) {
const roughnessIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE);

effect.setTexture("normalSampler", geometryBufferRenderer.getGBuffer().textures[1]);
const normalIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.NORMAL_TEXTURE_TYPE);
effect.setTexture("normalSampler", geometryBufferRenderer.getGBuffer().textures[normalIndex]);
effect.setTexture("reflectivitySampler", geometryBufferRenderer.getGBuffer().textures[roughnessIndex]);
effect.setTexture("depthSampler", geometryBufferRenderer.getGBuffer().textures[0]);
if (this._useScreenspaceDepth) {
const depthIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.SCREENSPACE_DEPTH_TEXTURE_TYPE);
effect.setTexture("depthSampler", geometryBufferRenderer.getGBuffer().textures[depthIndex]);
} else {
const depthIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.DEPTH_TEXTURE_TYPE);
effect.setTexture("depthSampler", geometryBufferRenderer.getGBuffer().textures[depthIndex]);
}
} else if (prePassRenderer) {
const depthIndex = prePassRenderer.getIndex(Constants.PREPASS_DEPTH_TEXTURE_TYPE);
const depthIndex = prePassRenderer.getIndex(this._useScreenspaceDepth ? Constants.PREPASS_SCREENSPACE_DEPTH_TEXTURE_TYPE : Constants.PREPASS_DEPTH_TEXTURE_TYPE);
const roughnessIndex = prePassRenderer.getIndex(Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE);
const normalIndex = prePassRenderer.getIndex(Constants.PREPASS_NORMAL_TEXTURE_TYPE);

Expand Down Expand Up @@ -1034,6 +1061,7 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
effect.setFloat("maxSteps", this.maxSteps);
effect.setFloat("roughnessFactor", this.roughnessFactor);
effect.setFloat("nearPlaneZ", camera.minZ);
effect.setFloat("farPlaneZ", camera.maxZ);
effect.setFloat("maxDistance", this.maxDistance);
effect.setFloat("selfCollisionNumSkip", this.selfCollisionNumSkip);
effect.setFloat("reflectivityThreshold", this._reflectivityThreshold);
Expand All @@ -1060,7 +1088,7 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
this._ssrPostProcess.samples = this.samples;

if (!this._forceGeometryBuffer) {
this._ssrPostProcess._prePassEffectConfiguration = new ScreenSpaceReflections2Configuration();
this._ssrPostProcess._prePassEffectConfiguration = new ScreenSpaceReflections2Configuration(this._useScreenspaceDepth);
}
}

Expand Down Expand Up @@ -1150,9 +1178,12 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
if (this.useFresnel) {
defines += "#define SSR_BLEND_WITH_FRESNEL\n";

uniformNames.push("projection", "invProjectionMatrix");
uniformNames.push("projection", "invProjectionMatrix", "nearPlaneZ", "farPlaneZ");
samplerNames.push("depthSampler", "normalSampler");
}
if (this._useScreenspaceDepth) {
defines += "#define SSRAYTRACE_SCREENSPACE_DEPTH";
}
if (this._reflectivityThreshold === 0) {
defines += "#define SSR_DISABLE_REFLECTIVITY_TEST";
}
Expand Down Expand Up @@ -1206,14 +1237,31 @@ export class SSRRenderingPipeline extends PostProcessRenderPipeline {
const roughnessIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE);
effect.setTexture("reflectivitySampler", geometryBufferRenderer.getGBuffer().textures[roughnessIndex]);
if (this.useFresnel) {
const camera = this._scene.activeCamera;
if (camera && this._useScreenspaceDepth) {
effect.setFloat("nearPlaneZ", camera.minZ);
effect.setFloat("farPlaneZ", camera.maxZ);
}
effect.setTexture("normalSampler", geometryBufferRenderer.getGBuffer().textures[1]);
effect.setTexture("depthSampler", geometryBufferRenderer.getGBuffer().textures[0]);
if (this._useScreenspaceDepth) {
const depthIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.SCREENSPACE_DEPTH_TEXTURE_TYPE);
effect.setTexture("depthSampler", geometryBufferRenderer.getGBuffer().textures[depthIndex]);
} else {
effect.setTexture("depthSampler", geometryBufferRenderer.getGBuffer().textures[0]);
}
}
} else if (prePassRenderer) {
const roughnessIndex = prePassRenderer.getIndex(Constants.PREPASS_REFLECTIVITY_TEXTURE_TYPE);
effect.setTexture("reflectivitySampler", prePassRenderer.getRenderTarget().textures[roughnessIndex]);
if (this.useFresnel) {
const depthIndex = prePassRenderer.getIndex(Constants.PREPASS_DEPTH_TEXTURE_TYPE);
const camera = this._scene.activeCamera;
if (camera && this._useScreenspaceDepth) {
effect.setFloat("nearPlaneZ", camera.minZ);
effect.setFloat("farPlaneZ", camera.maxZ);
}
const depthIndex = prePassRenderer.getIndex(
this._useScreenspaceDepth ? Constants.PREPASS_SCREENSPACE_DEPTH_TEXTURE_TYPE : Constants.PREPASS_DEPTH_TEXTURE_TYPE
);
const normalIndex = prePassRenderer.getIndex(Constants.PREPASS_NORMAL_TEXTURE_TYPE);

effect.setTexture("normalSampler", prePassRenderer.getRenderTarget().textures[normalIndex]);
Expand Down
130 changes: 112 additions & 18 deletions packages/dev/core/src/Rendering/geometryBufferRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ export class GeometryBufferRenderer {
*/
public static readonly REFLECTIVITY_TEXTURE_TYPE = 4;

/**
* Constant used to retrieve the screen-space depth texture index in the G-Buffer textures array
* using getIndex(GeometryBufferRenderer.SCREENSPACE_DEPTH_TEXTURE_TYPE)
*/
public static readonly SCREENSPACE_DEPTH_TEXTURE_TYPE = 5;

/**
* Dictionary used to store the previous transformation matrices of each rendered mesh
* in order to compute objects velocities when enableVelocity is set to "true"
Expand Down Expand Up @@ -134,9 +140,12 @@ export class GeometryBufferRenderer {
private _multiRenderTarget: MultiRenderTarget;
private _textureTypesAndFormats: { [key: number]: { textureType: number; textureFormat: number } };
private _ratioOrDimensions: number | { width: number; height: number };
private _enableDepth: boolean = true;
private _enableNormal: boolean = true;
private _enablePosition: boolean = false;
private _enableVelocity: boolean = false;
private _enableReflectivity: boolean = false;
private _enableScreenspaceDepth: boolean = false;
private _depthFormat: number;
private _clearColor = new Color4(0, 0, 0, 0);
private _clearDepthColor = new Color4(1e8, 0, 0, 1); // "infinity" value - depth in the depth texture is view.z, not a 0..1 value!
Expand All @@ -146,6 +155,7 @@ export class GeometryBufferRenderer {
private _reflectivityIndex: number = -1;
private _depthIndex: number = -1;
private _normalIndex: number = -1;
private _screenspaceDepthIndex: number = -1;

private _linkedWithPrePass: boolean = false;
private _prePassRenderer: PrePassRenderer;
Expand Down Expand Up @@ -187,9 +197,12 @@ export class GeometryBufferRenderer {
* Resets the geometry buffer layout
*/
public _resetLayout() {
this._enableDepth = true;
this._enableNormal = true;
this._enablePosition = false;
this._enableReflectivity = false;
this._enableVelocity = false;
this._enableScreenspaceDepth = false;
this._attachmentsFromPrePass = [];
}

Expand All @@ -210,8 +223,13 @@ export class GeometryBufferRenderer {
this._enableReflectivity = true;
} else if (geometryBufferType === GeometryBufferRenderer.DEPTH_TEXTURE_TYPE) {
this._depthIndex = index;
this._enableDepth = true;
} else if (geometryBufferType === GeometryBufferRenderer.NORMAL_TEXTURE_TYPE) {
this._normalIndex = index;
this._enableNormal = true;
} else if (geometryBufferType === GeometryBufferRenderer.SCREENSPACE_DEPTH_TEXTURE_TYPE) {
this._screenspaceDepthIndex = index;
this._enableScreenspaceDepth = true;
}
}

Expand Down Expand Up @@ -269,14 +287,54 @@ export class GeometryBufferRenderer {
case GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE:
return this._reflectivityIndex;
case GeometryBufferRenderer.DEPTH_TEXTURE_TYPE:
return this._linkedWithPrePass ? this._depthIndex : 0;
return this._depthIndex;
case GeometryBufferRenderer.NORMAL_TEXTURE_TYPE:
return this._linkedWithPrePass ? this._normalIndex : 1;
return this._normalIndex;
case GeometryBufferRenderer.SCREENSPACE_DEPTH_TEXTURE_TYPE:
return this._screenspaceDepthIndex;
default:
return -1;
}
}

/**
* @returns a boolean indicating if object's depths are enabled for the G buffer.
*/
public get enableDepth(): boolean {
return this._enableDepth;
}

/**
* Sets whether or not object's depths are enabled for the G buffer.
*/
public set enableDepth(enable: boolean) {
this._enableDepth = enable;

if (!this._linkedWithPrePass) {
this.dispose();
this._createRenderTargets();
}
}

/**
* @returns a boolean indicating if object's normals are enabled for the G buffer.
*/
public get enableNormal(): boolean {
return this._enableNormal;
}

/**
* Sets whether or not object's normals are enabled for the G buffer.
*/
public set enableNormal(enable: boolean) {
this._enableNormal = enable;

if (!this._linkedWithPrePass) {
this.dispose();
this._createRenderTargets();
}
}

/**
* @returns a boolean indicating if objects positions are enabled for the G buffer.
*/
Expand Down Expand Up @@ -345,6 +403,22 @@ export class GeometryBufferRenderer {
}
}

/**
* Sets whether or not objects screenspace depth are enabled for the G buffer.
*/
public get enableScreenspaceDepth(): boolean {
return this._enableScreenspaceDepth;
}

public set enableScreenspaceDepth(enable: boolean) {
this._enableScreenspaceDepth = enable;

if (!this._linkedWithPrePass) {
this.dispose();
this._createRenderTargets();
}
}

/**
* 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.
Expand Down Expand Up @@ -599,20 +673,17 @@ export class GeometryBufferRenderer {
}
}

// PrePass
if (this._linkedWithPrePass) {
defines.push("#define PREPASS");
if (this._depthIndex !== -1) {
defines.push("#define DEPTH_INDEX " + this._depthIndex);
defines.push("#define PREPASS_DEPTH");
}
if (this._normalIndex !== -1) {
defines.push("#define NORMAL_INDEX " + this._normalIndex);
defines.push("#define PREPASS_NORMAL");
}
// Buffers
if (this._enableDepth) {
defines.push("#define DEPTH");
defines.push("#define DEPTH_INDEX " + this._depthIndex);
}

if (this._enableNormal) {
defines.push("#define NORMAL");
defines.push("#define NORMAL_INDEX " + this._normalIndex);
}

// Buffers
if (this._enablePosition) {
defines.push("#define POSITION");
defines.push("#define POSITION_INDEX " + this._positionIndex);
Expand All @@ -631,6 +702,13 @@ export class GeometryBufferRenderer {
defines.push("#define REFLECTIVITY_INDEX " + this._reflectivityIndex);
}

if (this._enableScreenspaceDepth) {
if (this._screenspaceDepthIndex !== -1) {
defines.push("#define SCREENSPACE_DEPTH_INDEX " + this._screenspaceDepthIndex);
defines.push("#define SCREENSPACE_DEPTH");
}
}

if (this.generateNormalsInWorldSpace) {
defines.push("#define NORMAL_WORLDSPACE");
}
Expand Down Expand Up @@ -756,12 +834,21 @@ export class GeometryBufferRenderer {
private _assignRenderTargetIndices(): [number, string[], Array<{ textureType: number; textureFormat: number } | undefined>] {
const textureNames: string[] = [];
const textureTypesAndFormats: Array<{ textureType: number; textureFormat: number } | undefined> = [];
let count = 2;
let count = 0;

textureNames.push("gBuffer_Depth", "gBuffer_Normal");
if (this._enableDepth) {
this._depthIndex = count;
count++;
textureNames.push("gBuffer_Depth");
textureTypesAndFormats.push(this._textureTypesAndFormats[GeometryBufferRenderer.DEPTH_TEXTURE_TYPE]);
}

textureTypesAndFormats.push(this._textureTypesAndFormats[GeometryBufferRenderer.DEPTH_TEXTURE_TYPE]);
textureTypesAndFormats.push(this._textureTypesAndFormats[GeometryBufferRenderer.NORMAL_TEXTURE_TYPE]);
if (this._enableNormal) {
this._normalIndex = count;
count++;
textureNames.push("gBuffer_Normal");
textureTypesAndFormats.push(this._textureTypesAndFormats[GeometryBufferRenderer.NORMAL_TEXTURE_TYPE]);
}

if (this._enablePosition) {
this._positionIndex = count;
Expand All @@ -784,6 +871,13 @@ export class GeometryBufferRenderer {
textureTypesAndFormats.push(this._textureTypesAndFormats[GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE]);
}

if (this._enableScreenspaceDepth) {
this._screenspaceDepthIndex = count;
count++;
textureNames.push("gBuffer_ScreenspaceDepth");
textureTypesAndFormats.push(this._textureTypesAndFormats[GeometryBufferRenderer.SCREENSPACE_DEPTH_TEXTURE_TYPE]);
}

return [count, textureNames, textureTypesAndFormats];
}

Expand Down
Loading

0 comments on commit d2d49e8

Please sign in to comment.