|
@@ -1,12 +1,15 @@
|
|
|
|
+/// <reference path="babylon.d.ts" />
|
|
|
|
+
|
|
module BABYLON {
|
|
module BABYLON {
|
|
export class LensRenderingPipeline extends PostProcessRenderPipeline {
|
|
export class LensRenderingPipeline extends PostProcessRenderPipeline {
|
|
|
|
|
|
// Lens effects can be of the following:
|
|
// Lens effects can be of the following:
|
|
- // - chromatic aberration (slight shift of RGB colors)
|
|
|
|
- // - blur on the edge of the lens
|
|
|
|
- // - lens distortion
|
|
|
|
- // - depth-of-field 'bokeh' effect (shapes appearing in blured areas, stronger highlights)
|
|
|
|
- // - grain/dust-on-lens effect
|
|
|
|
|
|
+ // - chromatic aberration (slight shift of RGB colors)
|
|
|
|
+ // - blur on the edge of the lens
|
|
|
|
+ // - lens distortion
|
|
|
|
+ // - depth-of-field blur & highlights enhancing
|
|
|
|
+ // - depth-of-field 'bokeh' effect (shapes appearing in blurred areas)
|
|
|
|
+ // - grain effect (noise or custom texture)
|
|
|
|
|
|
// Two additional texture samplers are needed:
|
|
// Two additional texture samplers are needed:
|
|
// - depth map (for depth-of-field)
|
|
// - depth map (for depth-of-field)
|
|
@@ -18,6 +21,11 @@ module BABYLON {
|
|
*/
|
|
*/
|
|
public LensChromaticAberrationEffect: string = "LensChromaticAberrationEffect";
|
|
public LensChromaticAberrationEffect: string = "LensChromaticAberrationEffect";
|
|
/**
|
|
/**
|
|
|
|
+ * The highlights enhancing PostProcess id in the pipeline
|
|
|
|
+ * @type {string}
|
|
|
|
+ */
|
|
|
|
+ public HighlightsEnhancingEffect: string = "HighlightsEnhancingEffect";
|
|
|
|
+ /**
|
|
* The depth-of-field PostProcess id in the pipeline
|
|
* The depth-of-field PostProcess id in the pipeline
|
|
* @type {string}
|
|
* @type {string}
|
|
*/
|
|
*/
|
|
@@ -28,6 +36,7 @@ module BABYLON {
|
|
private _grainTexture: Texture;
|
|
private _grainTexture: Texture;
|
|
|
|
|
|
private _chromaticAberrationPostProcess: PostProcess;
|
|
private _chromaticAberrationPostProcess: PostProcess;
|
|
|
|
+ private _highlightsPostProcess: PostProcess;
|
|
private _depthOfFieldPostProcess: PostProcess;
|
|
private _depthOfFieldPostProcess: PostProcess;
|
|
|
|
|
|
private _edgeBlur: number;
|
|
private _edgeBlur: number;
|
|
@@ -41,50 +50,48 @@ module BABYLON {
|
|
private _dofPentagon: boolean;
|
|
private _dofPentagon: boolean;
|
|
private _blurNoise: boolean;
|
|
private _blurNoise: boolean;
|
|
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @constructor
|
|
* @constructor
|
|
|
|
+ *
|
|
|
|
+ * Effect parameters are as follow:
|
|
|
|
+ * {
|
|
|
|
+ * chromatic_aberration: number; // from 0 to x (1 for realism)
|
|
|
|
+ * edge_blur: number; // from 0 to x (1 for realism)
|
|
|
|
+ * distortion: number; // from 0 to x (1 for realism)
|
|
|
|
+ * grain_amount: number; // from 0 to 1
|
|
|
|
+ * grain_texture: BABYLON.Texture; // texture to use for grain effect; if unset, use random B&W noise
|
|
|
|
+ * dof_focus_depth: number; // depth-of-field: focus depth; unset to disable (disabled by default)
|
|
|
|
+ * dof_aperture: number; // depth-of-field: focus blur bias (default: 1)
|
|
|
|
+ * dof_pentagon: boolean; // depth-of-field: makes a pentagon-like "bokeh" effect
|
|
|
|
+ * dof_gain: number; // depth-of-field: depthOfField gain; unset to disable (disabled by default)
|
|
|
|
+ * dof_threshold: number; // depth-of-field: depthOfField threshold (default: 1)
|
|
|
|
+ * blur_noise: boolean; // add a little bit of noise to the blur (default: true)
|
|
|
|
+ * }
|
|
|
|
+ * Note: if an effect parameter is unset, effect is disabled
|
|
|
|
+ *
|
|
* @param {string} name - The rendering pipeline name
|
|
* @param {string} name - The rendering pipeline name
|
|
* @param {object} parameters - An object containing all parameters (see below)
|
|
* @param {object} parameters - An object containing all parameters (see below)
|
|
* @param {BABYLON.Scene} scene - The scene linked to this pipeline
|
|
* @param {BABYLON.Scene} scene - The scene linked to this pipeline
|
|
* @param {number} 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 {number} 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.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
|
|
* @param {BABYLON.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
|
|
-
|
|
|
|
- Effect parameters are as follow:
|
|
|
|
- {
|
|
|
|
- chromatic_aberration: number; // from 0 to x (1 for realism)
|
|
|
|
- edge_blur: number; // from 0 to x (1 for realism)
|
|
|
|
- distortion: number; // from 0 to x (1 for realism)
|
|
|
|
- grain_amount: number; // from 0 to 1
|
|
|
|
- grain_texture: BABYLON.Texture; // texture to use for grain effect; if unset, use random B&W noise
|
|
|
|
- dof_focus_depth: number; // depth-of-field: focus depth; unset to disable
|
|
|
|
- dof_aperture: number; // depth-of-field: focus blur bias (default: 1)
|
|
|
|
- dof_pentagon: boolean; // depth-of-field: makes a pentagon-like "bokeh" effect
|
|
|
|
- dof_gain: boolean; // depth-of-field: depthOfField gain (default: 1)
|
|
|
|
- dof_threshold: boolean; // depth-of-field: depthOfField threshold (default: 1)
|
|
|
|
- blur_noise: boolean; // add a little bit of noise to the blur (default: true)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Note: if an effect parameter is unset, effect is disabled
|
|
|
|
*/
|
|
*/
|
|
constructor(name: string, parameters: any, scene: Scene, ratio: number = 1.0, cameras?: Camera[]) {
|
|
constructor(name: string, parameters: any, scene: Scene, ratio: number = 1.0, cameras?: Camera[]) {
|
|
super(scene.getEngine(), name);
|
|
super(scene.getEngine(), name);
|
|
|
|
|
|
this._scene = scene;
|
|
this._scene = scene;
|
|
-
|
|
|
|
|
|
+
|
|
// Fetch texture samplers
|
|
// Fetch texture samplers
|
|
this._depthTexture = scene.enableDepthRenderer().getDepthMap(); // Force depth renderer "on"
|
|
this._depthTexture = scene.enableDepthRenderer().getDepthMap(); // Force depth renderer "on"
|
|
- if (parameters.grain_texture) {
|
|
|
|
- this._grainTexture = parameters.grain_texture;
|
|
|
|
- } else {
|
|
|
|
- this._createGrainTexture();
|
|
|
|
- }
|
|
|
|
|
|
+ if(parameters.grain_texture) { this._grainTexture = parameters.grain_texture; }
|
|
|
|
+ else { this._createGrainTexture(); }
|
|
|
|
|
|
// save parameters
|
|
// save parameters
|
|
this._edgeBlur = parameters.edge_blur ? parameters.edge_blur : 0;
|
|
this._edgeBlur = parameters.edge_blur ? parameters.edge_blur : 0;
|
|
this._grainAmount = parameters.grain_amount ? parameters.grain_amount : 0;
|
|
this._grainAmount = parameters.grain_amount ? parameters.grain_amount : 0;
|
|
this._chromaticAberration = parameters.chromatic_aberration ? parameters.chromatic_aberration : 0;
|
|
this._chromaticAberration = parameters.chromatic_aberration ? parameters.chromatic_aberration : 0;
|
|
this._distortion = parameters.distortion ? parameters.distortion : 0;
|
|
this._distortion = parameters.distortion ? parameters.distortion : 0;
|
|
- this._highlightsGain = parameters.dof_gain ? parameters.dof_gain : 1;
|
|
|
|
|
|
+ this._highlightsGain = parameters.dof_gain !== undefined ? parameters.dof_gain : -1;
|
|
this._highlightsThreshold = parameters.dof_threshold ? parameters.dof_threshold : 1;
|
|
this._highlightsThreshold = parameters.dof_threshold ? parameters.dof_threshold : 1;
|
|
this._dofDepth = parameters.dof_focus_depth !== undefined ? parameters.dof_focus_depth : -1;
|
|
this._dofDepth = parameters.dof_focus_depth !== undefined ? parameters.dof_focus_depth : -1;
|
|
this._dofAperture = parameters.dof_aperture ? parameters.dof_aperture : 1;
|
|
this._dofAperture = parameters.dof_aperture ? parameters.dof_aperture : 1;
|
|
@@ -93,12 +100,18 @@ module BABYLON {
|
|
|
|
|
|
// Create effects
|
|
// Create effects
|
|
this._createChromaticAberrationPostProcess(ratio);
|
|
this._createChromaticAberrationPostProcess(ratio);
|
|
|
|
+ this._createHighlightsPostProcess(ratio);
|
|
this._createDepthOfFieldPostProcess(ratio);
|
|
this._createDepthOfFieldPostProcess(ratio);
|
|
|
|
|
|
// Set up pipeline
|
|
// Set up pipeline
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.LensChromaticAberrationEffect, () => { return this._chromaticAberrationPostProcess; }, true));
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.LensChromaticAberrationEffect, () => { return this._chromaticAberrationPostProcess; }, true));
|
|
|
|
+ this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.HighlightsEnhancingEffect, () => { return this._highlightsPostProcess; }, true));
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.LensDepthOfFieldEffect, () => { return this._depthOfFieldPostProcess; }, true));
|
|
this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.LensDepthOfFieldEffect, () => { return this._depthOfFieldPostProcess; }, true));
|
|
|
|
|
|
|
|
+ if(this._highlightsGain == -1) {
|
|
|
|
+ this._disableEffect(this.HighlightsEnhancingEffect, null);
|
|
|
|
+ }
|
|
|
|
+
|
|
// Finish
|
|
// Finish
|
|
scene.postProcessRenderPipelineManager.addPipeline(this);
|
|
scene.postProcessRenderPipelineManager.addPipeline(this);
|
|
if(cameras) {
|
|
if(cameras) {
|
|
@@ -106,7 +119,8 @@ module BABYLON {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // public methods
|
|
|
|
|
|
+ // public methods (self explanatory)
|
|
|
|
+
|
|
public setEdgeBlur(amount: number) { this._edgeBlur = amount; }
|
|
public setEdgeBlur(amount: number) { this._edgeBlur = amount; }
|
|
public disableEdgeBlur() { this._edgeBlur = 0; }
|
|
public disableEdgeBlur() { this._edgeBlur = 0; }
|
|
public setGrainAmount(amount: number) { this._grainAmount = amount; }
|
|
public setGrainAmount(amount: number) { this._grainAmount = amount; }
|
|
@@ -115,8 +129,6 @@ module BABYLON {
|
|
public disableChromaticAberration() { this._chromaticAberration = 0; }
|
|
public disableChromaticAberration() { this._chromaticAberration = 0; }
|
|
public setEdgeDistortion(amount: number) { this._distortion = amount; }
|
|
public setEdgeDistortion(amount: number) { this._distortion = amount; }
|
|
public disableEdgeDistortion() { this._distortion = 0; }
|
|
public disableEdgeDistortion() { this._distortion = 0; }
|
|
- public setHighlightsGain(amount: number) { this._highlightsGain = amount; }
|
|
|
|
- public setHighlightsThreshold(amount: number) { this._highlightsThreshold = amount; }
|
|
|
|
public setFocusDepth(amount: number) { this._dofDepth = amount; }
|
|
public setFocusDepth(amount: number) { this._dofDepth = amount; }
|
|
public disableDepthOfField() { this._dofDepth = -1; }
|
|
public disableDepthOfField() { this._dofDepth = -1; }
|
|
public setAperture(amount: number) { this._dofAperture = amount; }
|
|
public setAperture(amount: number) { this._dofAperture = amount; }
|
|
@@ -124,6 +136,18 @@ module BABYLON {
|
|
public disablePentagonBokeh() { this._dofPentagon = false; }
|
|
public disablePentagonBokeh() { this._dofPentagon = false; }
|
|
public enableNoiseBlur() { this._blurNoise = true; }
|
|
public enableNoiseBlur() { this._blurNoise = true; }
|
|
public disableNoiseBlur() { this._blurNoise = false; }
|
|
public disableNoiseBlur() { this._blurNoise = false; }
|
|
|
|
+ public setHighlightsGain(amount: number) {
|
|
|
|
+ this._highlightsGain = amount;
|
|
|
|
+ }
|
|
|
|
+ public setHighlightsThreshold(amount: number) {
|
|
|
|
+ if(this._highlightsGain == -1) {
|
|
|
|
+ this._highlightsGain = 1.0;
|
|
|
|
+ }
|
|
|
|
+ this._highlightsThreshold = amount;
|
|
|
|
+ }
|
|
|
|
+ public disableHighlights() {
|
|
|
|
+ this._highlightsGain = -1;
|
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
/**
|
|
* Removes the internal pipeline assets and detaches the pipeline from the scene cameras
|
|
* Removes the internal pipeline assets and detaches the pipeline from the scene cameras
|
|
@@ -132,6 +156,7 @@ module BABYLON {
|
|
this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
|
|
this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
|
|
|
|
|
|
this._chromaticAberrationPostProcess = undefined;
|
|
this._chromaticAberrationPostProcess = undefined;
|
|
|
|
+ this._highlightsPostProcess = undefined;
|
|
this._depthOfFieldPostProcess = undefined;
|
|
this._depthOfFieldPostProcess = undefined;
|
|
|
|
|
|
this._grainTexture.dispose();
|
|
this._grainTexture.dispose();
|
|
@@ -150,8 +175,26 @@ module BABYLON {
|
|
|
|
|
|
this._chromaticAberrationPostProcess.onApply = (effect: Effect) => {
|
|
this._chromaticAberrationPostProcess.onApply = (effect: Effect) => {
|
|
effect.setFloat('chromatic_aberration', this._chromaticAberration);
|
|
effect.setFloat('chromatic_aberration', this._chromaticAberration);
|
|
- effect.setFloat('screen_width', this._scene.getEngine().getRenderWidth());
|
|
|
|
- effect.setFloat('screen_height', this._scene.getEngine().getRenderHeight());
|
|
|
|
|
|
+ effect.setFloat('screen_width', this._scene.getEngine().getRenderingCanvas().width);
|
|
|
|
+ effect.setFloat('screen_height', this._scene.getEngine().getRenderingCanvas().height);
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // highlights enhancing
|
|
|
|
+ private _createHighlightsPostProcess(ratio: number): void {
|
|
|
|
+ this._highlightsPostProcess = new PostProcess("LensHighlights", "lensHighlights",
|
|
|
|
+ [ "pentagon", "gain", "threshold", "screen_width", "screen_height" ], // uniforms
|
|
|
|
+ [], // samplers
|
|
|
|
+ ratio, null, Texture.TRILINEAR_SAMPLINGMODE,
|
|
|
|
+ this._scene.getEngine(), false);
|
|
|
|
+
|
|
|
|
+ this._highlightsPostProcess.onApply = (effect: Effect) => {
|
|
|
|
+ effect.setFloat('gain', this._highlightsGain);
|
|
|
|
+ effect.setFloat('threshold', this._highlightsThreshold);
|
|
|
|
+ effect.setBool('pentagon', this._dofPentagon);
|
|
|
|
+ effect.setTextureFromPostProcess("textureSampler", this._chromaticAberrationPostProcess);
|
|
|
|
+ effect.setFloat('screen_width', this._scene.getEngine().getRenderingCanvas().width);
|
|
|
|
+ effect.setFloat('screen_height', this._scene.getEngine().getRenderingCanvas().height);
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -159,33 +202,34 @@ module BABYLON {
|
|
private _createDepthOfFieldPostProcess(ratio: number): void {
|
|
private _createDepthOfFieldPostProcess(ratio: number): void {
|
|
this._depthOfFieldPostProcess = new PostProcess("LensDepthOfField", "depthOfField",
|
|
this._depthOfFieldPostProcess = new PostProcess("LensDepthOfField", "depthOfField",
|
|
[
|
|
[
|
|
- "gain", "threshold", "focus_depth", "aperture", "pentagon", "maxZ", "edge_blur",
|
|
|
|
- "chromatic_aberration", "distortion", "blur_noise", "grain_amount", "screen_width", "screen_height"
|
|
|
|
|
|
+ "focus_depth", "aperture", "pentagon", "maxZ", "edge_blur", "chromatic_aberration",
|
|
|
|
+ "distortion", "blur_noise", "grain_amount", "screen_width", "screen_height", "highlights"
|
|
],
|
|
],
|
|
- ["depthSampler", "grainSampler"],
|
|
|
|
|
|
+ ["depthSampler", "grainSampler", "highlightsSampler"],
|
|
ratio, null, Texture.TRILINEAR_SAMPLINGMODE,
|
|
ratio, null, Texture.TRILINEAR_SAMPLINGMODE,
|
|
this._scene.getEngine(), false);
|
|
this._scene.getEngine(), false);
|
|
|
|
|
|
this._depthOfFieldPostProcess.onApply = (effect: Effect) => {
|
|
this._depthOfFieldPostProcess.onApply = (effect: Effect) => {
|
|
- effect.setBool('pentagon', this._dofPentagon);
|
|
|
|
effect.setBool('blur_noise', this._blurNoise);
|
|
effect.setBool('blur_noise', this._blurNoise);
|
|
effect.setFloat('maxZ', this._scene.activeCamera.maxZ);
|
|
effect.setFloat('maxZ', this._scene.activeCamera.maxZ);
|
|
effect.setFloat('grain_amount', this._grainAmount);
|
|
effect.setFloat('grain_amount', this._grainAmount);
|
|
|
|
|
|
effect.setTexture("depthSampler", this._depthTexture);
|
|
effect.setTexture("depthSampler", this._depthTexture);
|
|
effect.setTexture("grainSampler", this._grainTexture);
|
|
effect.setTexture("grainSampler", this._grainTexture);
|
|
|
|
+ effect.setTextureFromPostProcess("textureSampler", this._highlightsPostProcess);
|
|
|
|
+ effect.setTextureFromPostProcess("highlightsSampler", this._depthOfFieldPostProcess);
|
|
|
|
|
|
- effect.setFloat('screen_width', this._scene.getEngine().getRenderWidth());
|
|
|
|
- effect.setFloat('screen_height', this._scene.getEngine().getRenderHeight());
|
|
|
|
|
|
+ effect.setFloat('screen_width', this._scene.getEngine().getRenderingCanvas().width);
|
|
|
|
+ effect.setFloat('screen_height', this._scene.getEngine().getRenderingCanvas().height);
|
|
|
|
|
|
effect.setFloat('distortion', this._distortion);
|
|
effect.setFloat('distortion', this._distortion);
|
|
|
|
|
|
effect.setFloat('focus_depth', this._dofDepth);
|
|
effect.setFloat('focus_depth', this._dofDepth);
|
|
effect.setFloat('aperture', this._dofAperture);
|
|
effect.setFloat('aperture', this._dofAperture);
|
|
- effect.setFloat('gain', this._highlightsGain);
|
|
|
|
- effect.setFloat('threshold', this._highlightsThreshold);
|
|
|
|
|
|
|
|
effect.setFloat('edge_blur', this._edgeBlur);
|
|
effect.setFloat('edge_blur', this._edgeBlur);
|
|
|
|
+
|
|
|
|
+ effect.setBool('highlights', (this._highlightsGain != -1));
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|