Browse Source

Merge pull request #446 from jahow/lens_pp_fix

Fix for LensRenderingPipeline
David Catuhe 10 years ago
parent
commit
452a0f2ebb

+ 87 - 43
Babylon/PostProcess/babylon.lensRenderingPipeline.ts

@@ -1,12 +1,15 @@
+/// <reference path="babylon.d.ts" />
+
 module BABYLON {
     export class LensRenderingPipeline extends PostProcessRenderPipeline {
 
     	// 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:
     	// - depth map (for depth-of-field)
@@ -18,6 +21,11 @@ module BABYLON {
         */
         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
         * @type {string}
         */
@@ -28,6 +36,7 @@ module BABYLON {
         private _grainTexture: Texture;
 
         private _chromaticAberrationPostProcess: PostProcess;
+        private _highlightsPostProcess: PostProcess;
         private _depthOfFieldPostProcess: PostProcess;
 
         private _edgeBlur: number;
@@ -41,50 +50,48 @@ module BABYLON {
         private _dofPentagon: boolean;
         private _blurNoise: boolean;
 
+
         /**
          * @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 {object} parameters - An object containing all parameters (see below)
+         * @param {object} parameters - An object containing all parameters (see above)
          * @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 {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[]) {
 			super(scene.getEngine(), name);
 
 			this._scene = scene;
-
+ 
 			// Fetch texture samplers
 			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
 			this._edgeBlur = parameters.edge_blur ? parameters.edge_blur : 0;
 			this._grainAmount = parameters.grain_amount ? parameters.grain_amount : 0;
 			this._chromaticAberration = parameters.chromatic_aberration ? parameters.chromatic_aberration : 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._dofDepth = parameters.dof_focus_depth !== undefined ? parameters.dof_focus_depth : -1;
 			this._dofAperture = parameters.dof_aperture ? parameters.dof_aperture : 1;
@@ -93,12 +100,18 @@ module BABYLON {
 
 			// Create effects
             this._createChromaticAberrationPostProcess(ratio);
+            this._createHighlightsPostProcess(ratio);
             this._createDepthOfFieldPostProcess(ratio);
 
             // Set up pipeline
             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));
 
+            if(this._highlightsGain == -1) {
+                this._disableEffect(this.HighlightsEnhancingEffect, null);
+            }
+
             // Finish
             scene.postProcessRenderPipelineManager.addPipeline(this);
             if(cameras) {
@@ -106,7 +119,8 @@ module BABYLON {
             }
         }
 
-        // public methods
+        // public methods (self explanatory)
+
         public setEdgeBlur(amount: number) { this._edgeBlur = amount; }
         public disableEdgeBlur() { this._edgeBlur = 0; }
         public setGrainAmount(amount: number) { this._grainAmount = amount; }
@@ -115,8 +129,6 @@ module BABYLON {
         public disableChromaticAberration() { this._chromaticAberration = 0; }
         public setEdgeDistortion(amount: number) { this._distortion = amount; }
         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 disableDepthOfField() { this._dofDepth = -1; }
         public setAperture(amount: number) { this._dofAperture = amount; }
@@ -124,6 +136,18 @@ module BABYLON {
         public disablePentagonBokeh() { this._dofPentagon = false; }
         public enableNoiseBlur() { this._blurNoise = true; }
         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
@@ -132,6 +156,7 @@ module BABYLON {
             this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
 
             this._chromaticAberrationPostProcess = undefined;
+            this._highlightsPostProcess = undefined;
             this._depthOfFieldPostProcess = undefined;
 
             this._grainTexture.dispose();
@@ -150,8 +175,26 @@ module BABYLON {
 
             this._chromaticAberrationPostProcess.onApply = (effect: Effect) => {
             	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 {
             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,
                 this._scene.getEngine(), false);
 
             this._depthOfFieldPostProcess.onApply = (effect: Effect) => {
-	            effect.setBool('pentagon', this._dofPentagon);
             	effect.setBool('blur_noise', this._blurNoise);
             	effect.setFloat('maxZ', this._scene.activeCamera.maxZ);
             	effect.setFloat('grain_amount', this._grainAmount);
 
             	effect.setTexture("depthSampler", this._depthTexture);
             	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('focus_depth', this._dofDepth);
 	            effect.setFloat('aperture', this._dofAperture);
-            	effect.setFloat('gain', this._highlightsGain);
-            	effect.setFloat('threshold', this._highlightsThreshold);
 
             	effect.setFloat('edge_blur', this._edgeBlur);
+
+                effect.setBool('highlights', (this._highlightsGain != -1));
             };
         }
 

+ 3 - 3
Babylon/Shaders/chromaticAberration.fragment.fx

@@ -31,9 +31,9 @@ void main(void)
 
 	if(chromatic_aberration > 0.0) {
 		//index of refraction of each color channel, causing chromatic dispersion
-		vec3 ref_indices = vec3(0.6, 0.3, 0.0);
-		float ref_shiftX = chromatic_aberration * radius * 12.0 / screen_width;
-		float ref_shiftY = chromatic_aberration * radius * 12.0 / screen_height;
+		vec3 ref_indices = vec3(-0.3, 0.0, 0.3);
+		float ref_shiftX = chromatic_aberration * radius * 17.0 / screen_width;
+		float ref_shiftY = chromatic_aberration * radius * 17.0 / screen_height;
 
 		// shifts for red, green & blue
 		vec2 ref_coords_r = vec2(vUV.x + ref_indices.r*ref_shiftX, vUV.y + ref_indices.r*ref_shiftY*0.5);

+ 74 - 143
Babylon/Shaders/depthOfField.fragment.fx

@@ -1,7 +1,7 @@
 /*
 	BABYLON.JS Depth-of-field GLSL Shader
 	Author: Olivier Guyot
-	Does depth-of-field blur, edge blur, highlights enhancing
+	Does depth-of-field blur, edge blur
 	Inspired by Francois Tarlier & Martins Upitis
 */
 
@@ -12,12 +12,12 @@ precision highp float;
 
 // samplers
 uniform sampler2D textureSampler;
+uniform sampler2D highlightsSampler;
 uniform sampler2D depthSampler;
 uniform sampler2D grainSampler;
 
 // uniforms
 uniform float grain_amount;
-uniform bool pentagon;
 uniform float maxZ;
 uniform bool blur_noise;
 uniform float screen_width;
@@ -25,24 +25,14 @@ uniform float screen_height;
 uniform float distortion;
 uniform float focus_depth;
 uniform float aperture;
-uniform float gain;
-uniform float threshold;
 uniform float edge_blur;
+uniform bool highlights;
 
 // varyings
 varying vec2 vUV;
 
 // constants
 #define PI 3.14159265
-const int RING_1_SAMPLES = 4;
-const int RING_2_SAMPLES = 6;
-const int RING_3_SAMPLES = 9;
-const int RING_4_SAMPLES = 12;
-const int RING_5_SAMPLES = 16;
-//const int RING_6_SAMPLES = 15;
-const float RING_STEP_DIST = 0.4;			// a new blur ring is added each time this distance is passed
-const float PENTAGON_ANGLE_SUB = 1.2566;		// 2PI / 5
-const float PENTAGON_ANGLE_SUB_HALF = 0.6283;	// 2PI / 10
 
 // common calculations
 vec2 centered_screen_pos;
@@ -66,137 +56,67 @@ vec2 getDistortedCoords(vec2 coords) {
 	return dist_coords;
 }
 
-// picks either original screen color or highlights only
-vec4 getColor(vec2 coords, bool highlight) {
-
-	vec4 color = texture2D(textureSampler, coords);
-
-	if(highlight) {
-		float luminance = dot(color.rgb, vec3(0.2125, 0.7154, 0.0721));
-		float lum_threshold;
-		if(threshold > 1.0) { lum_threshold = 0.94 + 0.01 * threshold; }
-		else { lum_threshold = 0.5 + 0.44 * threshold; }
-		if(luminance < lum_threshold) {
-			color.rgb = vec3(0.0, 0.0, 0.0);
-			color.a = 1.0;
-		}
-	}
-
-	return color;
-}
+// returns original screen color after blur
+vec4 getBlurColor(vec2 coords, float size) {
 
-// returns a modifier to be applied on the radius, in order to simulate a pentagon
-float pentagonShape(float angle) {
-    float a1 = mod(angle, PENTAGON_ANGLE_SUB) / PENTAGON_ANGLE_SUB - 0.5;
-    float a2 = 0.5 - a1 * a1;
-    return 1.35 - 0.94 * a2;
-}
+	vec4 col = texture2D(textureSampler, coords);
+	if(size == 0.0) { return col; }
 
-// returns original screen color after blur
-vec4 getBlurColor(vec2 coords, float size, bool highlight) {
+	// there are max. 30 samples; the number of samples chosen is dependant on the blur size
+	// there can be 10, 20 or 30 samples chosen; levels of blur are then 1, 2 or 3
+	float blur_level = min(3.0, ceil(size / 1.0));
 
 	float w = (size/screen_width);
 	float h = (size/screen_height);
+	float total_weight = 1.0;
+
+	col += texture2D(textureSampler, coords + vec2(-0.53*w, 0.15*h))*0.93;
+	col += texture2D(textureSampler, coords + vec2(0.42*w, -0.69*h))*0.90;
+	col += texture2D(textureSampler, coords + vec2(0.20*w, 1.00*h))*0.87;
+	col += texture2D(textureSampler, coords + vec2(-0.97*w, -0.72*h))*0.85;
+	col += texture2D(textureSampler, coords + vec2(1.37*w, -0.14*h))*0.83;
+	col += texture2D(textureSampler, coords + vec2(-1.02*w, 1.16*h))*0.80;
+	col += texture2D(textureSampler, coords + vec2(-0.03*w, -1.69*h))*0.78;
+	col += texture2D(textureSampler, coords + vec2(1.27*w, 1.34*h))*0.76;
+	col += texture2D(textureSampler, coords + vec2(-1.98*w, -0.14*h))*0.74;
+	col += texture2D(textureSampler, coords + vec2(1.66*w, -1.32*h))*0.72;
+	total_weight += 8.18;
+
+	if(blur_level > 1.0) {
+		col += texture2D(textureSampler, coords + vec2(-0.35*w, 2.22*h))*0.70;
+		col += texture2D(textureSampler, coords + vec2(-1.31*w, -1.98*h))*0.67;
+		col += texture2D(textureSampler, coords + vec2(2.42*w, 0.61*h))*0.65;
+		col += texture2D(textureSampler, coords + vec2(-2.31*w, 1.25*h))*0.63;
+		col += texture2D(textureSampler, coords + vec2(0.90*w, -2.59*h))*0.61;
+		col += texture2D(textureSampler, coords + vec2(1.14*w, 2.62*h))*0.59;
+		col += texture2D(textureSampler, coords + vec2(-2.72*w, -1.21*h))*0.56;
+		col += texture2D(textureSampler, coords + vec2(2.93*w, -0.98*h))*0.54;
+		col += texture2D(textureSampler, coords + vec2(-1.56*w, 2.80*h))*0.52;
+		col += texture2D(textureSampler, coords + vec2(-0.77*w, -3.22*h))*0.49;
+		total_weight += 5.96;
+	}
 
-	vec4 col = getColor(coords, highlight);
-	if(size == 0.0) { return col; }
-
-	float s = 1.0;
-	float pw;			// sample x relative coord
-	float ph;			// sample y relative coord
-	float bias = 0.65;	// inner/outer ring bias
-	if(highlight) { bias = 0.95; }
-	float sample_angle;
-	float ratio_rings;
-	float ring_radius;
-	float penta;		// pentagon shape modifier
-
-	int ring_count;
-	if(size >= 6.0 * RING_STEP_DIST) { ring_count = 6; }
-	else if(size >= 5.0 * RING_STEP_DIST) { ring_count = 5; }
-	else if(size >= 4.0 * RING_STEP_DIST) { ring_count = 4; }
-	else if(size >= 3.0 * RING_STEP_DIST) { ring_count = 3; }
-	else if(size >= 2.0 * RING_STEP_DIST) { ring_count = 2; }
-	else { ring_count = 1; }
-	
-	// RING 1
-	if(size > RING_STEP_DIST) {
-		ring_radius = size / float(ring_count);
-		ratio_rings = 1.0 / float(ring_count);
-		for(int i = 0; i < RING_1_SAMPLES; i++) {
-			sample_angle = PI *2.0 * float(i) / float(RING_1_SAMPLES);
-			if(pentagon) { penta = pentagonShape(sample_angle); }
-			else { penta = 1.0; }
-			pw = cos( sample_angle ) * penta * ring_radius;
-			ph = sin( sample_angle ) * penta * ring_radius;
-			col += getColor(coords + vec2(pw*w,ph*h), highlight) * mix( 1.0, ratio_rings, bias );
-			s += 1.0 * mix(1.0, ratio_rings, bias);
-		}
-	}	
-
-	// RING 2
-	if(size > RING_STEP_DIST * 2.0) {
-		ring_radius = 2.0 * size / float(ring_count);
-		ratio_rings = 2.0 / float(ring_count);
-		for(int i = 0; i < RING_2_SAMPLES; i++) {
-			sample_angle = PI *2.0 * float(i) / float(RING_2_SAMPLES);
-			if(pentagon) { penta = pentagonShape(sample_angle); }
-			else { penta = 1.0; }
-			pw = cos( sample_angle ) * penta * ring_radius;
-			ph = sin( sample_angle ) * penta * ring_radius;
-			col += getColor(coords + vec2(pw*w,ph*h), highlight) * mix( 1.0, ratio_rings, bias );
-			s += 1.0 * mix(1.0, ratio_rings, bias);  
-		}
-	}	
-
-	// RING 3
-	if(size > RING_STEP_DIST * 3.0) {
-		ring_radius = 3.0 * size / float(ring_count);
-		ratio_rings = 3.0 / float(ring_count);
-		for(int i = 0; i < RING_3_SAMPLES; i++) {
-			sample_angle = PI *2.0 * float(i) / float(RING_3_SAMPLES);
-			if(pentagon) { penta = pentagonShape(sample_angle); }
-			else { penta = 1.0; }
-			pw = cos( sample_angle ) * penta * ring_radius;
-			ph = sin( sample_angle ) * penta * ring_radius;
-			col += getColor(coords + vec2(pw*w,ph*h), highlight) * mix( 1.0, ratio_rings, bias );
-			s += 1.0 * mix(1.0, ratio_rings, bias);  
-		}
-	}	
-
-	// RING 4
-	if(size > RING_STEP_DIST * 4.0) {
-		ring_radius = 4.0 * size / float(ring_count);
-		ratio_rings = 4.0 / float(ring_count);
-		for(int i = 0; i < RING_4_SAMPLES; i++) {
-			sample_angle = PI *2.0 * float(i) / float(RING_4_SAMPLES);
-			if(pentagon) { penta = pentagonShape(sample_angle); }
-			else { penta = 1.0; }
-			pw = cos( sample_angle ) * penta * ring_radius;
-			ph = sin( sample_angle ) * penta * ring_radius;
-			col += getColor(coords + vec2(pw*w,ph*h), highlight) * mix( 1.0, ratio_rings, bias );
-			s += 1.0 * mix(1.0, ratio_rings, bias);  
-		}
-	}	
-
-	// RING 5
-	if(size > RING_STEP_DIST * 5.0) {
-		ring_radius = 5.0 * size / float(ring_count);
-		ratio_rings = 5.0 / float(ring_count);
-		for(int i = 0; i < RING_5_SAMPLES; i++) {
-			sample_angle = PI *2.0 * float(i) / float(RING_5_SAMPLES);
-			if(pentagon) { penta = pentagonShape(sample_angle); }
-			else { penta = 1.0; }
-			pw = cos( sample_angle ) * penta * ring_radius;
-			ph = sin( sample_angle ) * penta * ring_radius;
-			col += getColor(coords + vec2(pw*w,ph*h), highlight) * mix( 1.0, ratio_rings, bias );
-			s += 1.0 * mix(1.0, ratio_rings, bias);  
-		}
-	}	
+	if(blur_level > 2.0) {
+		col += texture2D(textureSampler, coords + vec2(2.83*w, 1.92*h))*0.46;
+		col += texture2D(textureSampler, coords + vec2(-3.49*w, 0.51*h))*0.44;
+		col += texture2D(textureSampler, coords + vec2(2.30*w, -2.82*h))*0.41;
+		col += texture2D(textureSampler, coords + vec2(0.22*w, 3.74*h))*0.38;
+		col += texture2D(textureSampler, coords + vec2(-2.76*w, -2.68*h))*0.34;
+		col += texture2D(textureSampler, coords + vec2(3.95*w, 0.11*h))*0.31;
+		col += texture2D(textureSampler, coords + vec2(-3.07*w, 2.65*h))*0.26;
+		col += texture2D(textureSampler, coords + vec2(0.48*w, -4.13*h))*0.22;
+		col += texture2D(textureSampler, coords + vec2(2.49*w, 3.46*h))*0.15;
+		total_weight += 2.97;
+	}
 
-	col /= s;		// scales color according to samples taken
+	col /= total_weight;		// scales color according to weights
 	col.a = 1.0;
 
+	// blur levels debug
+	// if(blur_level == 1.0) { col.b = 0.0; }
+	// if(blur_level == 2.0) { col.r = 0.0; }
+	// if(blur_level == 3.0) { col.g = 0.0; }
+
 	return col;
 }
 
@@ -222,13 +142,17 @@ void main(void)
 
 	// blur from depth of field effect
 	float dof_blur_amount = 0.0;
+	float depth_bias = 0.0;		// positive if the pixel is further than focus depth; negative if closer
 	if(focus_depth != -1.0) {
 		vec4 depth_sample = texture2D(depthSampler, distorted_coords);
 		float depth = depth_sample.r;
-		dof_blur_amount = abs(depth - focus_depth) * aperture * 3.5;
-		if(dof_blur_amount < 0.05) { dof_blur_amount = 0.0; }				// no blur at all
-		else if( depth - focus_depth < 0.0 ) { dof_blur_amount *= 2.0; }	// blur more when close to camera
-		dof_blur_amount = clamp(dof_blur_amount, 0.0, 1.0);
+		depth_bias = depth - focus_depth;
+
+		// compute blur amount with distance
+		if( depth_bias > 0.0 ) { dof_blur_amount = depth_bias * aperture * 2.2; }
+		else { dof_blur_amount = depth_bias * depth_bias * aperture * 30.0; }
+
+		if(dof_blur_amount < 0.05) { dof_blur_amount = 0.0; }	// no blur at all
 	}
 
 	// blur from edge blur effect
@@ -242,19 +166,26 @@ void main(void)
 
 	// apply blur if necessary
 	if(blur_amount == 0.0) {
-		gl_FragColor = getColor(distorted_coords, false);
+		gl_FragColor = texture2D(textureSampler, distorted_coords);
 	} else {
-		gl_FragColor = getBlurColor(distorted_coords, blur_amount * 1.7, false)
-					   + gain * blur_amount*getBlurColor(distorted_coords, blur_amount * 2.75, true);
+
+		// add blurred color
+		gl_FragColor = getBlurColor(distorted_coords, blur_amount * 1.7);
+					   
+		// if further than focus depth & we have computed highlights: enhance highlights
+		if(depth_bias > 0.0 && highlights) {
+			gl_FragColor += clamp(dof_blur_amount, 0.0, 1.0)*texture2D(highlightsSampler, distorted_coords);
+		}
 
 		if(blur_noise) {
 			// we put a slight amount of noise in the blurred color
 			vec2 noise = rand(distorted_coords) * 0.01 * blur_amount;
 			vec2 blurred_coord = vec2(distorted_coords.x + noise.x, distorted_coords.y + noise.y);
-			gl_FragColor = 0.04 * getColor(blurred_coord, false) + 0.96 * gl_FragColor;
+			gl_FragColor = 0.04 * texture2D(textureSampler, blurred_coord) + 0.96 * gl_FragColor;
 		}
 	}
 
+	// apply grain
 	if(grain_amount > 0.0) {
 		vec4 grain_color = texture2D(grainSampler, texels_coords*0.003);
 		gl_FragColor.rgb += ( -0.5 + grain_color.rgb ) * 0.20;

+ 139 - 0
Babylon/Shaders/lensHighlights.fragment.fx

@@ -0,0 +1,139 @@
+#ifdef GL_ES
+precision highp float;
+#endif
+
+// samplers
+uniform sampler2D textureSampler;	// original color
+
+// uniforms
+uniform float gain;
+uniform float threshold;
+uniform bool pentagon;
+uniform float screen_width;
+uniform float screen_height;
+
+// varyings
+varying vec2 vUV;
+
+// apply luminance filter
+vec4 highlightColor(vec4 color) {
+	vec4 highlight = color;
+	float luminance = dot(highlight.rgb, vec3(0.2125, 0.7154, 0.0721));
+	float lum_threshold;
+	if(threshold > 1.0) { lum_threshold = 0.94 + 0.01 * threshold; }
+	else { lum_threshold = 0.5 + 0.44 * threshold; }
+
+	luminance = clamp((luminance-lum_threshold) * (1.0 / (1.0 - lum_threshold)), 0.0, 1.0);
+
+	highlight *= luminance * gain;
+	highlight.a = 1.0;
+
+	return highlight;
+}
+
+void main(void)
+{
+	vec4 original = texture2D(textureSampler, vUV);
+
+	// quick exit if no highlight computing
+	if(gain == -1.0) {
+		gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+		return;
+	}
+
+	float w = 2.0 / screen_width;
+	float h = 2.0 / screen_height;
+
+	float weight = 1.0;
+
+	// compute blurred color
+	vec4 blurred = vec4(0.0, 0.0, 0.0, 0.0);
+
+	if(pentagon) {
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.84*w, 0.43*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.48*w, -1.29*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.61*w, 1.51*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.55*w, -0.74*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.71*w, -0.52*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.94*w, 1.59*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.40*w, -1.87*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.62*w, 1.16*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.09*w, 0.25*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.46*w, -1.71*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.08*w, 2.42*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.85*w, -1.89*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.89*w, 0.16*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.29*w, 1.88*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.40*w, -2.81*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.54*w, 2.26*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.60*w, -0.61*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.31*w, -1.30*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.83*w, 2.53*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.12*w, -2.48*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.60*w, 1.11*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.82*w, 0.99*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.50*w, -2.81*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.85*w, 3.33*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.94*w, -1.92*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(3.27*w, -0.53*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.95*w, 2.48*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.23*w, -3.04*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.17*w, 2.05*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.97*w, -0.04*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.25*w, -2.00*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.31*w, 3.08*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.94*w, -2.59*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(3.37*w, 0.64*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-3.13*w, 1.93*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.03*w, -3.65*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.60*w, 3.17*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-3.14*w, -1.19*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(3.00*w, -1.19*h)));
+	} else {
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.85*w, 0.36*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.52*w, -1.14*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.46*w, 1.42*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.46*w, -0.83*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.79*w, -0.42*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.11*w, 1.62*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.29*w, -2.07*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.69*w, 1.39*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.28*w, 0.12*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.65*w, -1.69*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.08*w, 2.44*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.63*w, -1.90*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.55*w, 0.31*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.13*w, 1.52*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.56*w, -2.61*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.38*w, 2.34*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.64*w, -0.81*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.53*w, -1.21*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.06*w, 2.63*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.00*w, -2.69*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.59*w, 1.32*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.82*w, 0.78*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.57*w, -2.50*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(0.54*w, 2.93*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.39*w, -1.81*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(3.01*w, -0.28*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.04*w, 2.25*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.02*w, -3.05*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.09*w, 2.25*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-3.07*w, -0.25*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.44*w, -1.90*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-0.52*w, 3.05*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-1.68*w, -2.61*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(3.01*w, 0.79*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.76*w, 1.46*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.05*w, -2.94*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(1.21*w, 2.88*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(-2.84*w, -1.30*h)));
+		blurred += highlightColor(texture2D(textureSampler, vUV + vec2(2.98*w, -0.96*h)));
+	}
+
+	blurred /= 39.0;
+
+	gl_FragColor = blurred;
+
+	//if(vUV.x > 0.5) { gl_FragColor.rgb *= 0.0; }
+}