|
|
@@ -36,38 +36,29 @@
|
|
|
public totalStrength: number = 1.0;
|
|
|
|
|
|
/**
|
|
|
- * Number of samples used for the SSAO calculations. Default value is 8
|
|
|
+ * The radius around the analyzed pixel used by the SSAO post-process. Default value is 0.0006
|
|
|
* @type {number}
|
|
|
*/
|
|
|
@serialize()
|
|
|
- private _samples: number = 8;
|
|
|
+ public radius: number = 0.0001;
|
|
|
|
|
|
- public set samples(n: number) {
|
|
|
- this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
|
|
|
-
|
|
|
- this._samples = n;
|
|
|
- for (var i = 0; i < this._scene.cameras.length; i++) {
|
|
|
- var camera = this._scene.cameras[i];
|
|
|
- this._ssaoPostProcess.dispose(camera);
|
|
|
- }
|
|
|
-
|
|
|
- this._createSSAOPostProcess(this._ratio.ssaoRatio);
|
|
|
- this.addEffect(new PostProcessRenderEffect(this._scene.getEngine(), this.SSAORenderEffect, () => { return this._ssaoPostProcess; }, true));
|
|
|
-
|
|
|
- if (this._cameras)
|
|
|
- this._scene.postProcessRenderPipelineManager.attachCamerasToRenderPipeline(this._name, this._cameras);
|
|
|
- }
|
|
|
-
|
|
|
- public get samples(): number {
|
|
|
- return this._samples;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * Related to fallOff, used to interpolate SSAO samples (first interpolate function input) based on the occlusion difference of each pixel
|
|
|
+ * Must not be equal to fallOff and superior to fallOff.
|
|
|
+ * Default value is 0.975
|
|
|
+ * @type {number}
|
|
|
+ */
|
|
|
+ @serialize()
|
|
|
+ public area: number = 0.0075;
|
|
|
|
|
|
/**
|
|
|
- * The radius around the analyzed pixel used by the SSAO post-process. Default value is 2.0
|
|
|
+ * Related to area, used to interpolate SSAO samples (second interpolate function input) based on the occlusion difference of each pixel
|
|
|
+ * Must not be equal to area and inferior to area.
|
|
|
+ * Default value is 0.0
|
|
|
* @type {number}
|
|
|
*/
|
|
|
@serialize()
|
|
|
- public radius: number = 2.0;
|
|
|
+ public fallOff: number = 0.000001;
|
|
|
|
|
|
/**
|
|
|
* The base color of the SSAO post-process
|
|
|
@@ -78,8 +69,7 @@
|
|
|
public base: number = 0.5;
|
|
|
|
|
|
private _scene: Scene;
|
|
|
- private _depthTexture: Texture;
|
|
|
- private _normalTexture: Texture;
|
|
|
+ private _depthTexture: RenderTargetTexture;
|
|
|
private _randomTexture: DynamicTexture;
|
|
|
|
|
|
private _originalColorPostProcess: PassPostProcess;
|
|
|
@@ -105,6 +95,10 @@
|
|
|
|
|
|
this._scene = scene;
|
|
|
|
|
|
+ // Set up assets
|
|
|
+ this._createRandomTexture();
|
|
|
+ this._depthTexture = scene.enableDepthRenderer().getDepthMap(); // Force depth renderer "on"
|
|
|
+
|
|
|
var ssaoRatio = ratio.ssaoRatio || ratio;
|
|
|
var combineRatio = ratio.combineRatio || ratio;
|
|
|
this._ratio = {
|
|
|
@@ -112,11 +106,6 @@
|
|
|
combineRatio: combineRatio
|
|
|
};
|
|
|
|
|
|
- // Set up assets
|
|
|
- this._createRandomTexture();
|
|
|
- this._depthTexture = scene.enableGeometryRenderer(this._ratio.ssaoRatio).getGBuffer().depthTexture;
|
|
|
- this._normalTexture = scene.enableGeometryRenderer(this._ratio.ssaoRatio).getGBuffer().textures[1];
|
|
|
-
|
|
|
this._originalColorPostProcess = new PassPostProcess("SSAOOriginalSceneColor", combineRatio, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false);
|
|
|
this._createSSAOPostProcess(ssaoRatio);
|
|
|
this._createBlurPostProcess(ssaoRatio);
|
|
|
@@ -127,6 +116,7 @@
|
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAORenderEffect, () => { return this._ssaoPostProcess; }, true));
|
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAOBlurHRenderEffect, () => { return this._blurHPostProcess; }, true));
|
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAOBlurVRenderEffect, () => { return this._blurVPostProcess; }, true));
|
|
|
+
|
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.SSAOCombineRenderEffect, () => { return this._ssaoCombinePostProcess; }, true));
|
|
|
|
|
|
// Finish
|
|
|
@@ -140,7 +130,7 @@
|
|
|
/**
|
|
|
* Removes the internal pipeline assets and detatches the pipeline from the scene cameras
|
|
|
*/
|
|
|
- public dispose(disableGeometryRenderer: boolean = false): void {
|
|
|
+ public dispose(disableDepthRender: boolean = false): void {
|
|
|
for (var i = 0; i < this._scene.cameras.length; i++) {
|
|
|
var camera = this._scene.cameras[i];
|
|
|
|
|
|
@@ -153,8 +143,8 @@
|
|
|
|
|
|
this._randomTexture.dispose();
|
|
|
|
|
|
- if (disableGeometryRenderer)
|
|
|
- this._scene.disableGeometryRenderer();
|
|
|
+ if (disableDepthRender)
|
|
|
+ this._scene.disableDepthRenderer();
|
|
|
|
|
|
this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
|
|
|
|
|
|
@@ -163,6 +153,13 @@
|
|
|
|
|
|
// Private Methods
|
|
|
private _createBlurPostProcess(ratio: number): void {
|
|
|
+ /*
|
|
|
+ var samplerOffsets = [
|
|
|
+ -8.0, -6.0, -4.0, -2.0,
|
|
|
+ 0.0,
|
|
|
+ 2.0, 4.0, 6.0, 8.0
|
|
|
+ ];
|
|
|
+ */
|
|
|
var samples = 16;
|
|
|
var samplerOffsets = [];
|
|
|
|
|
|
@@ -170,12 +167,9 @@
|
|
|
samplerOffsets.push(i * 2);
|
|
|
}
|
|
|
|
|
|
- this._blurHPostProcess = new PostProcess("BlurH", "ssao", ["outSize", "samplerOffsets", "near", "far", "radius"], ["depthSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define BILATERAL_BLUR_H\n#define SAMPLES 16");
|
|
|
+ this._blurHPostProcess = new PostProcess("BlurH", "ssao", ["outSize", "samplerOffsets"], ["depthSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define BILATERAL_BLUR_H\n#define SAMPLES 16");
|
|
|
this._blurHPostProcess.onApply = (effect: Effect) => {
|
|
|
effect.setFloat("outSize", this._ssaoCombinePostProcess.width);
|
|
|
- effect.setFloat("near", this._scene.activeCamera.minZ);
|
|
|
- effect.setFloat("far", this._scene.activeCamera.maxZ);
|
|
|
- effect.setFloat("radius", this.radius);
|
|
|
effect.setTexture("depthSampler", this._depthTexture);
|
|
|
|
|
|
if (this._firstUpdate) {
|
|
|
@@ -183,12 +177,9 @@
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- this._blurVPostProcess = new PostProcess("BlurV", "ssao", ["outSize", "samplerOffsets", "near", "far", "radius"], ["depthSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define SAMPLES 16");
|
|
|
+ this._blurVPostProcess = new PostProcess("BlurV", "ssao", ["outSize", "samplerOffsets"], ["depthSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, "#define BILATERAL_BLUR\n#define SAMPLES 16");
|
|
|
this._blurVPostProcess.onApply = (effect: Effect) => {
|
|
|
effect.setFloat("outSize", this._ssaoCombinePostProcess.height);
|
|
|
- effect.setFloat("near", this._scene.activeCamera.minZ);
|
|
|
- effect.setFloat("far", this._scene.activeCamera.maxZ);
|
|
|
- effect.setFloat("radius", this.radius);
|
|
|
effect.setTexture("depthSampler", this._depthTexture);
|
|
|
|
|
|
if (this._firstUpdate) {
|
|
|
@@ -198,55 +189,34 @@
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- private _generateHemisphere(): number[] {
|
|
|
- var numSamples = this.samples;
|
|
|
- var result = [];
|
|
|
- var vector, scale;
|
|
|
-
|
|
|
- var rand = (min, max) => {
|
|
|
- return Math.random() * (max - min) + min;
|
|
|
- }
|
|
|
-
|
|
|
- var lerp = (start, end, percent) => {
|
|
|
- return (start + percent*(end - start));
|
|
|
- }
|
|
|
-
|
|
|
- var i = 0;
|
|
|
- var normal = new BABYLON.Vector3(0, 0, 1);
|
|
|
- while (i < numSamples) {
|
|
|
- vector = new BABYLON.Vector3(
|
|
|
- rand(-1.0, 1.0),
|
|
|
- rand(-1.0, 1.0),
|
|
|
- rand(0.0, 1.0));
|
|
|
- vector.normalize();
|
|
|
- if (BABYLON.Vector3.Dot(vector, normal) < 0.07) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- scale = i / numSamples;
|
|
|
- scale = lerp(0.1, 1.0, scale*scale);
|
|
|
- vector.scaleInPlace(scale);
|
|
|
-
|
|
|
-
|
|
|
- result.push(vector.x, vector.y, vector.z);
|
|
|
- i++;
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
private _createSSAOPostProcess(ratio: number): void {
|
|
|
- var numSamples = this.samples;
|
|
|
-
|
|
|
- var sampleSphere = this._generateHemisphere();
|
|
|
+ var numSamples = 16;
|
|
|
+ var sampleSphere = [
|
|
|
+ 0.5381, 0.1856, -0.4319,
|
|
|
+ 0.1379, 0.2486, 0.4430,
|
|
|
+ 0.3371, 0.5679, -0.0057,
|
|
|
+ -0.6999, -0.0451, -0.0019,
|
|
|
+ 0.0689, -0.1598, -0.8547,
|
|
|
+ 0.0560, 0.0069, -0.1843,
|
|
|
+ -0.0146, 0.1402, 0.0762,
|
|
|
+ 0.0100, -0.1924, -0.0344,
|
|
|
+ -0.3577, -0.5301, -0.4358,
|
|
|
+ -0.3169, 0.1063, 0.0158,
|
|
|
+ 0.0103, -0.5869, 0.0046,
|
|
|
+ -0.0897, -0.4940, 0.3287,
|
|
|
+ 0.7119, -0.0154, -0.0918,
|
|
|
+ -0.0533, 0.0596, -0.5411,
|
|
|
+ 0.0352, -0.0631, 0.5460,
|
|
|
+ -0.4776, 0.2847, -0.0271
|
|
|
+ ];
|
|
|
var samplesFactor = 1.0 / numSamples;
|
|
|
|
|
|
this._ssaoPostProcess = new PostProcess("ssao", "ssao",
|
|
|
[
|
|
|
"sampleSphere", "samplesFactor", "randTextureTiles", "totalStrength", "radius",
|
|
|
- "base", "range", "viewport", "projection", "near", "far",
|
|
|
- "xViewport", "yViewport"
|
|
|
+ "area", "fallOff", "base", "range", "viewport"
|
|
|
],
|
|
|
- ["randomSampler", "normalSampler"],
|
|
|
+ ["randomSampler"],
|
|
|
ratio, null, Texture.BILINEAR_SAMPLINGMODE,
|
|
|
this._scene.getEngine(), false,
|
|
|
"#define SAMPLES " + numSamples + "\n#define SSAO");
|
|
|
@@ -262,15 +232,11 @@
|
|
|
|
|
|
effect.setFloat("totalStrength", this.totalStrength);
|
|
|
effect.setFloat("radius", this.radius);
|
|
|
+ effect.setFloat("area", this.area);
|
|
|
+ effect.setFloat("fallOff", this.fallOff);
|
|
|
effect.setFloat("base", this.base);
|
|
|
- effect.setFloat("near", this._scene.activeCamera.minZ);
|
|
|
- effect.setFloat("far", this._scene.activeCamera.maxZ);
|
|
|
- effect.setFloat("xViewport", Math.tan(this._scene.activeCamera.fov / 2) * this._scene.activeCamera.minZ * this._scene.getEngine().getAspectRatio(this._scene.activeCamera, true));
|
|
|
- effect.setFloat("yViewport", Math.tan(this._scene.activeCamera.fov / 2) * this._scene.activeCamera.minZ );
|
|
|
- effect.setMatrix("projection", this._scene.getProjectionMatrix());
|
|
|
|
|
|
effect.setTexture("textureSampler", this._depthTexture);
|
|
|
- effect.setTexture("normalSampler", this._normalTexture);
|
|
|
effect.setTexture("randomSampler", this._randomTexture);
|
|
|
};
|
|
|
}
|
|
|
@@ -302,15 +268,9 @@
|
|
|
|
|
|
for (var x = 0; x < size; x++) {
|
|
|
for (var y = 0; y < size; y++) {
|
|
|
- randVector.x = rand(0.0, 1.0);
|
|
|
- randVector.y = rand(0.0, 1.0);
|
|
|
- randVector.z = 0.0;
|
|
|
-
|
|
|
- randVector.normalize();
|
|
|
-
|
|
|
- randVector.scaleInPlace(255);
|
|
|
- randVector.x = Math.floor(randVector.x);
|
|
|
- randVector.y = Math.floor(randVector.y);
|
|
|
+ randVector.x = Math.floor(rand(-1.0, 1.0) * 255);
|
|
|
+ randVector.y = Math.floor(rand(-1.0, 1.0) * 255);
|
|
|
+ randVector.z = Math.floor(rand(-1.0, 1.0) * 255);
|
|
|
|
|
|
context.fillStyle = 'rgb(' + randVector.x + ', ' + randVector.y + ', ' + randVector.z + ')';
|
|
|
context.fillRect(x, y, 1, 1);
|