Skip to content

Commit

Permalink
Added support of Screen Space Reflection Post-Process
Browse files Browse the repository at this point in the history
  • Loading branch information
julien-moreau committed Oct 21, 2019
1 parent 07519b6 commit 892d453
Show file tree
Hide file tree
Showing 8 changed files with 730 additions and 114 deletions.
188 changes: 126 additions & 62 deletions src/PostProcesses/RenderPipeline/Pipelines/standardRenderingPipeline.ts

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/PostProcesses/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ export * from "./stereoscopicInterlacePostProcess";
export * from "./tonemapPostProcess";
export * from "./volumetricLightScatteringPostProcess";
export * from "./vrDistortionCorrectionPostProcess";
export * from "./vrMultiviewToSingleviewPostProcess";
export * from "./vrMultiviewToSingleviewPostProcess";
export * from "./screenSpaceReflectionPostProcess";
195 changes: 195 additions & 0 deletions src/PostProcesses/screenSpaceReflectionPostProcess.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import { Nullable } from "../types";
import { Camera } from "../Cameras/camera";
import { Effect } from "../Materials/effect";
import { PostProcess, PostProcessOptions } from "./postProcess";
import { Constants } from "../Engines/constants";
import { Scene } from '../scene';
import { GeometryBufferRenderer } from '../Rendering/geometryBufferRenderer';
import { serialize } from '../Misc/decorators';

import "../Shaders/screenSpaceReflection.fragment";

declare type Engine = import("../Engines/engine").Engine;
/**
* The ScreenSpaceReflectionPostProcess performs realtime reflections using only and only the available informations on the screen (positions and normals).
* Basically, the screen space reflection post-process will compute reflections according the material's roughness.
*/
export class ScreenSpaceReflectionPostProcess extends PostProcess {
/**
* Gets or sets a reflection threshold mainly used to adjust the reflection's height.
*/
@serialize()
public threshold: number = 0;
/**
* Gets or sets the current reflection strength. 1.0 is an ideal value but can be increased/decreased for particular results.
*/
@serialize()
public strength: number = 1;
/**
* Gets or sets the falloff exponent used while computing fresnel. More the exponent is high, more the reflections will be discrete.
*/
@serialize()
public reflectionSpecularFalloffExponent: number = 1;
/**
* Gets or sets the step size used to iterate until the effect finds the color of the reflection's pixel. Typically in interval [0.1, 1.0]
*/
@serialize()
public step: number = 0.2;

/**
* @hidden
*/
public _geometryBufferRenderer: Nullable<GeometryBufferRenderer>;

private _enableSmoothReflections: boolean = true;
private _reflectionSamples: number = 64;
private _smoothSteps: number = 5;

/**
* Creates a new instance ConvolutionPostProcess
* @param name The name of the effect.
* @param scene The scene containing the objects to calculate reflections.
* @param options The required width/height ratio to downsize to before computing the render pass.
* @param camera The camera to apply the render pass to.
* @param samplingMode The sampling mode to be used when computing the pass. (default: 0)
* @param engine The engine which the post process will be applied. (default: current engine)
* @param reusable If the post process can be reused on the same frame. (default: false)
* @param textureType Type of textures used when performing the post process. (default: 0)
* @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
*/
constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
super(name, "screenSpaceReflection", [
"projection", "view", "threshold", "reflectionSpecularFalloffExponent", "strength", "step"
], [
"textureSampler", "normalSampler", "positionSampler", "roughnessSampler"
], options, camera, samplingMode, engine, reusable,
"#define SSR_SUPPORTED\n#define REFLECTION_SAMPLES 64\n#define SMOOTH_STEPS 5\n",
textureType, undefined, null, blockCompilation);

// Get geometry buffer renderer and update effect
const geometryBufferRenderer = scene.enableGeometryBufferRenderer();
if (geometryBufferRenderer) {
if (geometryBufferRenderer.isSupported) {
geometryBufferRenderer.enablePosition = true;
geometryBufferRenderer.enableRoughness = true;
this._geometryBufferRenderer = geometryBufferRenderer;
}
}

this._updateEffectDefines();

// On apply, send uniforms
this.onApply = (effect: Effect) => {
if (!geometryBufferRenderer) {
return;
}

// Samplers
const positionIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.POSITION_TEXTURE_TYPE);
const roughnessIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.ROUGHNESS_TEXTURE_TYPE);

effect.setTexture("normalSampler", geometryBufferRenderer.getGBuffer().textures[1]);
effect.setTexture("positionSampler", geometryBufferRenderer.getGBuffer().textures[positionIndex]);
effect.setTexture("roughnessSampler", geometryBufferRenderer.getGBuffer().textures[roughnessIndex]);

// Uniforms
const camera = scene.activeCamera;
if (!camera) {
return;
}

const viewMatrix = camera.getViewMatrix();
const projectionMatrix = camera.getProjectionMatrix();

effect.setMatrix("projection", projectionMatrix);
effect.setMatrix("view", viewMatrix);
effect.setFloat("threshold", this.threshold);
effect.setFloat("reflectionSpecularFalloffExponent", this.reflectionSpecularFalloffExponent);
effect.setFloat("strength", this.strength);
effect.setFloat("step", this.step);
};
}

/**
* Gets wether or not smoothing reflections is enabled.
* Enabling smoothing will require more GPU power and can generate a drop in FPS.
*/
@serialize()
public get enableSmoothReflections(): boolean {
return this._enableSmoothReflections;
}

/**
* Sets wether or not smoothing reflections is enabled.
* Enabling smoothing will require more GPU power and can generate a drop in FPS.
*/
public set enableSmoothReflections(enabled: boolean) {
if (enabled === this._enableSmoothReflections) {
return;
}

this._enableSmoothReflections = enabled;
this._updateEffectDefines();
}

/**
* Gets the number of samples taken while computing reflections. More samples count is high,
* more the post-process wil require GPU power and can generate a drop in FPS.
*/
@serialize()
public get reflectionSamples(): number {
return this._reflectionSamples;
}

/**
* Sets the number of samples taken while computing reflections. More samples count is high,
* more the post-process wil require GPU power and can generate a drop in FPS.
*/
public set reflectionSamples(samples: number) {
if (samples === this._reflectionSamples) {
return;
}

this._reflectionSamples = samples;
this._updateEffectDefines();
}

/**
* Gets the number of samples taken while smoothing reflections. More samples count is high,
* more the post-process will require GPU power and can generate a drop in FPS.
* Default value (5.0) work pretty well in all cases but can be adjust.
*/
@serialize()
public get smoothSteps(): number {
return this._smoothSteps;
}

/*
* Sets the number of samples taken while smoothing reflections. More samples count is high,
* more the post-process will require GPU power and can generate a drop in FPS.
* Default value (5.0) work pretty well in all cases but can be adjust.
*/
public set smoothSteps(steps: number) {
if (steps === this._smoothSteps) {
return;
}

this._smoothSteps = steps;
this._updateEffectDefines();
}

private _updateEffectDefines(): void {
const defines: string[] = [];
if (this._geometryBufferRenderer) {
defines.push("#define SSR_SUPPORTED");
}
if (this._enableSmoothReflections) {
defines.push("#define ENABLE_SMOOTH_REFLECTIONS");
}

defines.push("#define REFLECTION_SAMPLES " + (this._reflectionSamples >> 0));
defines.push("#define SMOOTH_STEPS " + (this._smoothSteps >> 0));

this.updateEffect(defines.join("\n"));
}
}
Loading

0 comments on commit 892d453

Please sign in to comment.