forked from BabylonJS/Babylon.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support of Screen Space Reflection Post-Process
- Loading branch information
1 parent
07519b6
commit 892d453
Showing
8 changed files
with
730 additions
and
114 deletions.
There are no files selected for viewing
188 changes: 126 additions & 62 deletions
188
src/PostProcesses/RenderPipeline/Pipelines/standardRenderingPipeline.ts
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")); | ||
} | ||
} |
Oops, something went wrong.