|
@@ -0,0 +1,234 @@
|
|
|
+var __extends = (this && this.__extends) || function (d, b) {
|
|
|
+ for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
|
|
+ function __() { this.constructor = d; }
|
|
|
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
|
+};
|
|
|
+var BABYLON;
|
|
|
+(function (BABYLON) {
|
|
|
+ var StandardRenderingPipeline = (function (_super) {
|
|
|
+ __extends(StandardRenderingPipeline, _super);
|
|
|
+ /**
|
|
|
+ * @constructor
|
|
|
+ * @param {string} name - The rendering pipeline name
|
|
|
+ * @param {BABYLON.Scene} scene - The scene linked to this pipeline
|
|
|
+ * @param {any} ratio - The size of the postprocesses (0.5 means that your postprocess will have a width = canvas.width 0.5 and a height = canvas.height 0.5)
|
|
|
+ * @param {BABYLON.PostProcess} originalPostProcess - the custom original color post-process. Must be "reusable". Can be null.
|
|
|
+ * @param {BABYLON.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
|
|
|
+ */
|
|
|
+ function StandardRenderingPipeline(name, scene, ratio, originalPostProcess, cameras) {
|
|
|
+ var _this = this;
|
|
|
+ if (originalPostProcess === void 0) { originalPostProcess = null; }
|
|
|
+ _super.call(this, scene.getEngine(), name);
|
|
|
+ this.downSampleX4PostProcess = null;
|
|
|
+ this.brightPassPostProcess = null;
|
|
|
+ this.gaussianBlurHPostProcesses = [];
|
|
|
+ this.gaussianBlurVPostProcesses = [];
|
|
|
+ this.textureAdderPostProcess = null;
|
|
|
+ this.depthOfFieldSourcePostProcess = null;
|
|
|
+ this.depthOfFieldPostProcess = null;
|
|
|
+ this.brightThreshold = 1.0;
|
|
|
+ this.gaussianCoefficient = 0.25;
|
|
|
+ this.gaussianMean = 1.0;
|
|
|
+ this.gaussianStandardDeviation = 1.0;
|
|
|
+ this.exposure = 1.0;
|
|
|
+ this.lensTexture = null;
|
|
|
+ this.depthOfFieldDistance = 10.0;
|
|
|
+ this._depthRenderer = null;
|
|
|
+ // Getters and setters
|
|
|
+ this._blurEnabled = true;
|
|
|
+ this._depthOfFieldEnabled = false;
|
|
|
+ // Initialize
|
|
|
+ this._scene = scene;
|
|
|
+ // Create pass post-processe
|
|
|
+ if (!originalPostProcess) {
|
|
|
+ this.originalPostProcess = new BABYLON.PostProcess("HDRPass", "standard", [], [], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), true, "#define PASS_POST_PROCESS", BABYLON.Engine.TEXTURETYPE_FLOAT);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.originalPostProcess = originalPostProcess;
|
|
|
+ }
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRPassPostProcess", function () { return _this.originalPostProcess; }, true));
|
|
|
+ // Create down sample X4 post-process
|
|
|
+ this._createDownSampleX4PostProcess(scene, ratio / 2);
|
|
|
+ // Create bright pass post-process
|
|
|
+ this._createBrightPassPostProcess(scene, ratio / 2);
|
|
|
+ // Create gaussian blur post-processes (down sampling blurs)
|
|
|
+ this._createGaussianBlurPostProcesses(scene, ratio / 2, 0);
|
|
|
+ this._createGaussianBlurPostProcesses(scene, ratio / 4, 1);
|
|
|
+ this._createGaussianBlurPostProcesses(scene, ratio / 8, 2);
|
|
|
+ this._createGaussianBlurPostProcesses(scene, ratio / 16, 3);
|
|
|
+ // Create texture adder post-process
|
|
|
+ this._createTextureAdderPostProcess(scene, ratio);
|
|
|
+ // Create depth-of-field source post-process
|
|
|
+ this.depthOfFieldSourcePostProcess = new BABYLON.PostProcess("HDRDepthOfFieldSource", "standard", [], [], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), true, "#define PASS_POST_PROCESS", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRDepthOfFieldSource", function () { return _this.depthOfFieldSourcePostProcess; }, true));
|
|
|
+ // Create gaussian blur used by depth-of-field
|
|
|
+ this._createGaussianBlurPostProcesses(scene, ratio / 2, 4);
|
|
|
+ // Create depth-of-field post-process
|
|
|
+ this._createDepthOfFieldPostProcess(scene, ratio);
|
|
|
+ // Finish
|
|
|
+ scene.postProcessRenderPipelineManager.addPipeline(this);
|
|
|
+ if (cameras !== null) {
|
|
|
+ scene.postProcessRenderPipelineManager.attachCamerasToRenderPipeline(name, cameras);
|
|
|
+ }
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRDepthOfFieldSource", cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRGaussianBlurH4", cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRGaussianBlurV4", cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRDepthOfField", cameras);
|
|
|
+ }
|
|
|
+ Object.defineProperty(StandardRenderingPipeline.prototype, "BlurEnabled", {
|
|
|
+ get: function () {
|
|
|
+ return this._blurEnabled;
|
|
|
+ },
|
|
|
+ set: function (enabled) {
|
|
|
+ if (enabled && !this._blurEnabled || !enabled && this._blurEnabled) {
|
|
|
+ for (var i = 0; i < this.gaussianBlurHPostProcesses.length - 1; i++) {
|
|
|
+ if (enabled) {
|
|
|
+ this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRGaussianBlurH" + i, this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRGaussianBlurV" + i, this._scene.cameras);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRGaussianBlurH" + i, this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRGaussianBlurV" + i, this._scene.cameras);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this._blurEnabled = enabled;
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ Object.defineProperty(StandardRenderingPipeline.prototype, "DepthOfFieldEnabled", {
|
|
|
+ get: function () {
|
|
|
+ return this._depthOfFieldEnabled;
|
|
|
+ },
|
|
|
+ set: function (enabled) {
|
|
|
+ if (enabled && !this._depthOfFieldEnabled) {
|
|
|
+ this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRDepthOfFieldSource", this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRGaussianBlurH4", this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRGaussianBlurV4", this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.enableEffectInPipeline(this._name, "HDRDepthOfField", this._scene.cameras);
|
|
|
+ this._depthRenderer = this._scene.enableDepthRenderer();
|
|
|
+ }
|
|
|
+ else if (!enabled && this._depthOfFieldEnabled) {
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRDepthOfFieldSource", this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRGaussianBlurH4", this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRGaussianBlurV4", this._scene.cameras);
|
|
|
+ this._scene.postProcessRenderPipelineManager.disableEffectInPipeline(this._name, "HDRDepthOfField", this._scene.cameras);
|
|
|
+ }
|
|
|
+ this._depthOfFieldEnabled = enabled;
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ // Down Sample X4 Post-Processs
|
|
|
+ StandardRenderingPipeline.prototype._createDownSampleX4PostProcess = function (scene, ratio) {
|
|
|
+ var _this = this;
|
|
|
+ var downSampleX4Offsets = new Array(32);
|
|
|
+ this.downSampleX4PostProcess = new BABYLON.PostProcess("HDRDownSampleX4", "standard", ["dsOffsets"], [], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define DOWN_SAMPLE_X4", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ this.downSampleX4PostProcess.onApply = function (effect) {
|
|
|
+ var id = 0;
|
|
|
+ for (var i = -2; i < 2; i++) {
|
|
|
+ for (var j = -2; j < 2; j++) {
|
|
|
+ downSampleX4Offsets[id] = (i + 0.5) * (1.0 / _this.downSampleX4PostProcess.width);
|
|
|
+ downSampleX4Offsets[id + 1] = (j + 0.5) * (1.0 / _this.downSampleX4PostProcess.height);
|
|
|
+ id += 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ effect.setArray2("dsOffsets", downSampleX4Offsets);
|
|
|
+ };
|
|
|
+ // Add to pipeline
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRDownSampleX4", function () { return _this.downSampleX4PostProcess; }, true));
|
|
|
+ };
|
|
|
+ // Brightpass Post-Process
|
|
|
+ StandardRenderingPipeline.prototype._createBrightPassPostProcess = function (scene, ratio) {
|
|
|
+ var _this = this;
|
|
|
+ var brightOffsets = new Array(8);
|
|
|
+ this.brightPassPostProcess = new BABYLON.PostProcess("HDRBrightPass", "standard", ["dsOffsets", "brightThreshold"], [], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define BRIGHT_PASS", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ this.brightPassPostProcess.onApply = function (effect) {
|
|
|
+ var sU = (1.0 / _this.brightPassPostProcess.width);
|
|
|
+ var sV = (1.0 / _this.brightPassPostProcess.height);
|
|
|
+ brightOffsets[0] = -0.5 * sU;
|
|
|
+ brightOffsets[1] = 0.5 * sV;
|
|
|
+ brightOffsets[2] = 0.5 * sU;
|
|
|
+ brightOffsets[3] = 0.5 * sV;
|
|
|
+ brightOffsets[4] = -0.5 * sU;
|
|
|
+ brightOffsets[5] = -0.5 * sV;
|
|
|
+ brightOffsets[6] = 0.5 * sU;
|
|
|
+ brightOffsets[7] = -0.5 * sV;
|
|
|
+ effect.setArray2("dsOffsets", brightOffsets);
|
|
|
+ effect.setFloat("brightThreshold", _this.brightThreshold);
|
|
|
+ };
|
|
|
+ // Add to pipeline
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRBrightPass", function () { return _this.brightPassPostProcess; }, true));
|
|
|
+ };
|
|
|
+ // Create gaussian blur H&V post-processes
|
|
|
+ StandardRenderingPipeline.prototype._createGaussianBlurPostProcesses = function (scene, ratio, indice) {
|
|
|
+ var _this = this;
|
|
|
+ var blurOffsets = new Array(9);
|
|
|
+ var blurWeights = new Array(9);
|
|
|
+ var uniforms = ["blurOffsets", "blurWeights"];
|
|
|
+ var callback = function (height) {
|
|
|
+ return function (effect) {
|
|
|
+ // Weights
|
|
|
+ var x = 0.0;
|
|
|
+ for (var i = 0; i < 9; i++) {
|
|
|
+ x = (i - 4.0) / 4.0;
|
|
|
+ blurWeights[i] =
|
|
|
+ _this.gaussianCoefficient
|
|
|
+ * (1.0 / Math.sqrt(2.0 * Math.PI * _this.gaussianStandardDeviation))
|
|
|
+ * Math.exp((-((x - _this.gaussianMean) * (x - _this.gaussianMean))) / (2.0 * _this.gaussianStandardDeviation * _this.gaussianStandardDeviation));
|
|
|
+ }
|
|
|
+ var lastOutputDimensions = {
|
|
|
+ width: scene.getEngine().getRenderWidth(),
|
|
|
+ height: scene.getEngine().getRenderHeight()
|
|
|
+ };
|
|
|
+ for (var i = 0; i < 9; i++) {
|
|
|
+ var value = (i - 4.0) * (1.0 / (height === true ? lastOutputDimensions.height : lastOutputDimensions.width));
|
|
|
+ blurOffsets[i] = value;
|
|
|
+ }
|
|
|
+ effect.setArray("blurOffsets", blurOffsets);
|
|
|
+ effect.setArray("blurWeights", blurWeights);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ // Create horizontal gaussian blur post-processes
|
|
|
+ var gaussianBlurHPostProcess = new BABYLON.PostProcess("HDRGaussianBlurH" + ratio, "standard", uniforms, [], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define GAUSSIAN_BLUR_H", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ gaussianBlurHPostProcess.onApply = callback(false);
|
|
|
+ // Create vertical gaussian blur post-process
|
|
|
+ var gaussianBlurVPostProcess = new BABYLON.PostProcess("HDRGaussianBlurV" + ratio, "standard", uniforms, [], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define GAUSSIAN_BLUR_V", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ gaussianBlurVPostProcess.onApply = callback(true);
|
|
|
+ // Add to pipeline
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRGaussianBlurH" + indice, function () { return gaussianBlurHPostProcess; }, true));
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRGaussianBlurV" + indice, function () { return gaussianBlurVPostProcess; }, true));
|
|
|
+ // Finish
|
|
|
+ this.gaussianBlurHPostProcesses.push(gaussianBlurHPostProcess);
|
|
|
+ this.gaussianBlurVPostProcesses.push(gaussianBlurVPostProcess);
|
|
|
+ };
|
|
|
+ // Create texture adder post-process
|
|
|
+ StandardRenderingPipeline.prototype._createTextureAdderPostProcess = function (scene, ratio) {
|
|
|
+ var _this = this;
|
|
|
+ var lastGaussianBlurPostProcess = this.gaussianBlurVPostProcesses[3];
|
|
|
+ this.textureAdderPostProcess = new BABYLON.PostProcess("HDRTextureAdder", "standard", ["exposure"], ["otherSampler", "lensSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), true, "#define TEXTURE_ADDER", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ this.textureAdderPostProcess.onApply = function (effect) {
|
|
|
+ effect.setTextureFromPostProcess("otherSampler", _this.originalPostProcess);
|
|
|
+ effect.setTexture("lensSampler", _this.lensTexture);
|
|
|
+ effect.setFloat("exposure", _this.exposure);
|
|
|
+ };
|
|
|
+ // Add to pipeline
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRTextureAdder", function () { return _this.textureAdderPostProcess; }, true));
|
|
|
+ };
|
|
|
+ // Create depth-of-field post-process
|
|
|
+ StandardRenderingPipeline.prototype._createDepthOfFieldPostProcess = function (scene, ratio) {
|
|
|
+ var _this = this;
|
|
|
+ this.depthOfFieldPostProcess = new BABYLON.PostProcess("HDRDepthOfField", "standard", ["distance"], ["otherSampler", "depthSampler"], ratio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, "#define DEPTH_OF_FIELD", BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
|
|
|
+ this.depthOfFieldPostProcess.onApply = function (effect) {
|
|
|
+ effect.setTextureFromPostProcess("otherSampler", _this.depthOfFieldSourcePostProcess);
|
|
|
+ effect.setTexture("depthSampler", _this._depthRenderer.getDepthMap());
|
|
|
+ effect.setFloat("distance", _this.depthOfFieldDistance);
|
|
|
+ };
|
|
|
+ // Add to pipeline
|
|
|
+ this.addEffect(new BABYLON.PostProcessRenderEffect(scene.getEngine(), "HDRDepthOfField", function () { return _this.depthOfFieldPostProcess; }, true));
|
|
|
+ };
|
|
|
+ return StandardRenderingPipeline;
|
|
|
+ }(BABYLON.PostProcessRenderPipeline));
|
|
|
+ BABYLON.StandardRenderingPipeline = StandardRenderingPipeline;
|
|
|
+})(BABYLON || (BABYLON = {}));
|