瀏覽代碼

Merge pull request #16505 from Mugen87/dev32

JSM: Added module and TS file for CinematicCamera and BokehShader2.
Michael Herzog 6 年之前
父節點
當前提交
bd92ece157

+ 11 - 0
docs/manual/en/introduction/Import-via-modules.html

@@ -76,6 +76,11 @@
 		<p>
 			The following examples files are already available as modules:
 			<ul>
+				<li>cameras
+					<ul>
+						<li>CinematicCamera</li>
+					</ul>
+				</li>
 				<li>controls
 					<ul>
 						<li>DeviceOrientationControls</li>
@@ -149,6 +154,12 @@
 						<li>SVGRenderer</li>
 					</ul>
 				</li>
+				<li>shaders
+					<ul>
+						<li>BokehShader2</li>
+						<li>UnpackDepthRGBAShader</li>
+					</ul>
+				</li>
 				<li>utils
 					<ul>
 						<li>BufferGeometryUtils</li>

+ 2 - 2
examples/js/cameras/CinematicCamera.js

@@ -186,14 +186,14 @@ THREE.CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) {
 		scene.overrideMaterial = null;
 		renderer.setRenderTarget( this.postprocessing.rtTextureColor );
 		renderer.clear();
-		renderer.render( scene, camera );
+		renderer.render( scene, this );
 
 		// Render depth into texture
 
 		scene.overrideMaterial = this.materialDepth;
 		renderer.setRenderTarget( this.postprocessing.rtTextureDepth );
 		renderer.clear();
-		renderer.render( scene, camera );
+		renderer.render( scene, this );
 
 		// Render bokeh composite
 

+ 21 - 21
examples/js/shaders/BokehShader2.js

@@ -14,37 +14,37 @@ THREE.BokehShader = {
 
 	uniforms: {
 
-		"textureWidth":  { value: 1.0 },
-		"textureHeight":  { value: 1.0 },
+		"textureWidth": { value: 1.0 },
+		"textureHeight": { value: 1.0 },
 
-		"focalDepth":   { value: 1.0 },
-		"focalLength":   { value: 24.0 },
+		"focalDepth": { value: 1.0 },
+		"focalLength": { value: 24.0 },
 		"fstop": { value: 0.9 },
 
-		"tColor":   { value: null },
-		"tDepth":   { value: null },
+		"tColor": { value: null },
+		"tDepth": { value: null },
 
-		"maxblur":  { value: 1.0 },
+		"maxblur": { value: 1.0 },
 
-		"showFocus":   { value: 0 },
-		"manualdof":   { value: 0 },
-		"vignetting":   { value: 0 },
-		"depthblur":   { value: 0 },
+		"showFocus": { value: 0 },
+		"manualdof": { value: 0 },
+		"vignetting": { value: 0 },
+		"depthblur": { value: 0 },
 
-		"threshold":  { value: 0.5 },
-		"gain":  { value: 2.0 },
-		"bias":  { value: 0.5 },
-		"fringe":  { value: 0.7 },
+		"threshold": { value: 0.5 },
+		"gain": { value: 2.0 },
+		"bias": { value: 0.5 },
+		"fringe": { value: 0.7 },
 
-		"znear":  { value: 0.1 },
-		"zfar":  { value: 100 },
+		"znear": { value: 0.1 },
+		"zfar": { value: 100 },
 
-		"noise":  { value: 1 },
-		"dithering":  { value: 0.0001 },
+		"noise": { value: 1 },
+		"dithering": { value: 0.0001 },
 		"pentagon": { value: 0 },
 
-		"shaderFocus":  { value: 1 },
-		"focusCoords":  { value: new THREE.Vector2() }
+		"shaderFocus": { value: 1 },
+		"focusCoords": { value: new THREE.Vector2() }
 
 
 	},

+ 32 - 0
examples/jsm/cameras/CinematicCamera.d.ts

@@ -0,0 +1,32 @@
+import {
+  PerspectiveCamera,
+  ShaderMaterial,
+  Scene,
+  WebGLRenderer
+} from '../../../src/Three';
+
+export class CinematicCamera extends PerspectiveCamera {
+  constructor(fov: number, aspect: number, near: number, far: number);
+
+  postprocessing: {
+    enabled: boolean;
+  };
+  shaderSettings: {
+    rings: number;
+    samples: number;
+  };
+  materialDepth: ShaderMaterial;
+  coc: number;
+  aperture: number;
+  fNumber: number;
+  hyperFocal: number;
+  filmGauge: number;
+
+  linearize(depth: number): number;
+  smoothstep(near: number, far: number, depth: number): number;
+  saturate(x: number): number;
+  focusAt(focusDistance: number): void;
+  initPostProcessing(): void;
+  renderCinematic(scene: Scene, renderer: WebGLRenderer): void;
+
+}

+ 224 - 0
examples/jsm/cameras/CinematicCamera.js

@@ -0,0 +1,224 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author greggman / http://games.greggman.com/
+ * @author zz85 / http://www.lab4games.net/zz85/blog
+ * @author kaypiKun
+ */
+
+import {
+	LinearFilter,
+	Mesh,
+	OrthographicCamera,
+	PerspectiveCamera,
+	PlaneBufferGeometry,
+	RGBFormat,
+	Scene,
+	ShaderMaterial,
+	UniformsUtils,
+	WebGLRenderTarget
+} from "../../../build/three.module.js";
+import { BokehShader } from "../shaders/BokehShader2.js";
+import { BokehDepthShader } from "../shaders/BokehShader2.js";
+
+var CinematicCamera = function ( fov, aspect, near, far ) {
+
+	PerspectiveCamera.call( this, fov, aspect, near, far );
+
+	this.type = 'CinematicCamera';
+
+	this.postprocessing = { enabled: true };
+	this.shaderSettings = {
+		rings: 3,
+		samples: 4
+	};
+
+	var depthShader = BokehDepthShader;
+
+	this.materialDepth = new ShaderMaterial( {
+		uniforms: depthShader.uniforms,
+		vertexShader: depthShader.vertexShader,
+		fragmentShader: depthShader.fragmentShader
+	} );
+
+	this.materialDepth.uniforms[ 'mNear' ].value = near;
+	this.materialDepth.uniforms[ 'mFar' ].value = far;
+
+	// In case of cinematicCamera, having a default lens set is important
+	this.setLens();
+
+	this.initPostProcessing();
+
+};
+
+CinematicCamera.prototype = Object.create( PerspectiveCamera.prototype );
+CinematicCamera.prototype.constructor = CinematicCamera;
+
+
+// providing fnumber and coc(Circle of Confusion) as extra arguments
+CinematicCamera.prototype.setLens = function ( focalLength, filmGauge, fNumber, coc ) {
+
+	// In case of cinematicCamera, having a default lens set is important
+	if ( focalLength === undefined ) focalLength = 35;
+	if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
+
+	this.setFocalLength( focalLength );
+
+	// if fnumber and coc are not provided, cinematicCamera tries to act as a basic PerspectiveCamera
+	if ( fNumber === undefined ) fNumber = 8;
+	if ( coc === undefined ) coc = 0.019;
+
+	this.fNumber = fNumber;
+	this.coc = coc;
+
+	// fNumber is focalLength by aperture
+	this.aperture = focalLength / this.fNumber;
+
+	// hyperFocal is required to calculate depthOfField when a lens tries to focus at a distance with given fNumber and focalLength
+	this.hyperFocal = ( focalLength * focalLength ) / ( this.aperture * this.coc );
+
+};
+
+CinematicCamera.prototype.linearize = function ( depth ) {
+
+	var zfar = this.far;
+	var znear = this.near;
+	return - zfar * znear / ( depth * ( zfar - znear ) - zfar );
+
+};
+
+CinematicCamera.prototype.smoothstep = function ( near, far, depth ) {
+
+	var x = this.saturate( ( depth - near ) / ( far - near ) );
+	return x * x * ( 3 - 2 * x );
+
+};
+
+CinematicCamera.prototype.saturate = function ( x ) {
+
+	return Math.max( 0, Math.min( 1, x ) );
+
+};
+
+// function for focusing at a distance from the camera
+CinematicCamera.prototype.focusAt = function ( focusDistance ) {
+
+	if ( focusDistance === undefined ) focusDistance = 20;
+
+	var focalLength = this.getFocalLength();
+
+	// distance from the camera (normal to frustrum) to focus on
+	this.focus = focusDistance;
+
+	// the nearest point from the camera which is in focus (unused)
+	this.nearPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal + ( this.focus - focalLength ) );
+
+	// the farthest point from the camera which is in focus (unused)
+	this.farPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal - ( this.focus - focalLength ) );
+
+	// the gap or width of the space in which is everything is in focus (unused)
+	this.depthOfField = this.farPoint - this.nearPoint;
+
+	// Considering minimum distance of focus for a standard lens (unused)
+	if ( this.depthOfField < 0 ) this.depthOfField = 0;
+
+	this.sdistance = this.smoothstep( this.near, this.far, this.focus );
+
+	this.ldistance = this.linearize( 1 -	this.sdistance );
+
+	this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = this.ldistance;
+
+};
+
+CinematicCamera.prototype.initPostProcessing = function () {
+
+	if ( this.postprocessing.enabled ) {
+
+		this.postprocessing.scene = new Scene();
+
+		this.postprocessing.camera = new OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2,	window.innerHeight / 2, window.innerHeight / - 2, - 10000, 10000 );
+
+		this.postprocessing.scene.add( this.postprocessing.camera );
+
+		var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBFormat };
+		this.postprocessing.rtTextureDepth = new WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
+		this.postprocessing.rtTextureColor = new WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
+
+		var bokeh_shader = BokehShader;
+
+		this.postprocessing.bokeh_uniforms = UniformsUtils.clone( bokeh_shader.uniforms );
+
+		this.postprocessing.bokeh_uniforms[ "tColor" ].value = this.postprocessing.rtTextureColor.texture;
+		this.postprocessing.bokeh_uniforms[ "tDepth" ].value = this.postprocessing.rtTextureDepth.texture;
+
+		this.postprocessing.bokeh_uniforms[ "manualdof" ].value = 0;
+		this.postprocessing.bokeh_uniforms[ "shaderFocus" ].value = 0;
+
+		this.postprocessing.bokeh_uniforms[ "fstop" ].value = 2.8;
+
+		this.postprocessing.bokeh_uniforms[ "showFocus" ].value = 1;
+
+		this.postprocessing.bokeh_uniforms[ "focalDepth" ].value = 0.1;
+
+		//console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value );
+
+		this.postprocessing.bokeh_uniforms[ "znear" ].value = this.near;
+		this.postprocessing.bokeh_uniforms[ "zfar" ].value = this.near;
+
+
+		this.postprocessing.bokeh_uniforms[ "textureWidth" ].value = window.innerWidth;
+
+		this.postprocessing.bokeh_uniforms[ "textureHeight" ].value = window.innerHeight;
+
+		this.postprocessing.materialBokeh = new ShaderMaterial( {
+			uniforms: this.postprocessing.bokeh_uniforms,
+			vertexShader: bokeh_shader.vertexShader,
+			fragmentShader: bokeh_shader.fragmentShader,
+			defines: {
+				RINGS: this.shaderSettings.rings,
+				SAMPLES: this.shaderSettings.samples,
+				DEPTH_PACKING: 1
+			}
+		} );
+
+		this.postprocessing.quad = new Mesh( new PlaneBufferGeometry( window.innerWidth, window.innerHeight ), this.postprocessing.materialBokeh );
+		this.postprocessing.quad.position.z = - 500;
+		this.postprocessing.scene.add( this.postprocessing.quad );
+
+	}
+
+};
+
+CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) {
+
+	if ( this.postprocessing.enabled ) {
+
+		var currentRenderTarget = renderer.getRenderTarget();
+
+		renderer.clear();
+
+		// Render scene into texture
+
+		scene.overrideMaterial = null;
+		renderer.setRenderTarget( this.postprocessing.rtTextureColor );
+		renderer.clear();
+		renderer.render( scene, this );
+
+		// Render depth into texture
+
+		scene.overrideMaterial = this.materialDepth;
+		renderer.setRenderTarget( this.postprocessing.rtTextureDepth );
+		renderer.clear();
+		renderer.render( scene, this );
+
+		// Render bokeh composite
+
+		renderer.setRenderTarget( null );
+		renderer.render( this.postprocessing.scene, this.postprocessing.camera );
+
+		renderer.setRenderTarget( currentRenderTarget );
+
+	}
+
+};
+
+export { CinematicCamera };

+ 42 - 0
examples/jsm/shaders/BokehShader2.d.ts

@@ -0,0 +1,42 @@
+import {
+  Uniform
+} from '../../../src/Three';
+
+export interface BokehShader {
+  uniforms: {
+    textureWidth: Uniform;
+    textureHeight: Uniform;
+    focalDepth: Uniform;
+    focalLength: Uniform;
+    fstop: Uniform;
+    tColor: Uniform;
+    tDepth: Uniform;
+    maxblur: Uniform;
+    showFocus: Uniform;
+    manualdof: Uniform;
+    vignetting: Uniform;
+    depthblur: Uniform;
+    threshold: Uniform;
+    gain: Uniform;
+    bias: Uniform;
+    fringe: Uniform;
+    znear: Uniform;
+    zfar: Uniform;
+    noise: Uniform;
+    dithering: Uniform;
+    pentagon: Uniform;
+    shaderFocus: Uniform;
+    focusCoords: Uniform;
+  };
+  vertexShader: string;
+  fragmentShader:string;
+}
+
+export interface BokehDepthShader {
+  uniforms: {
+    mNear: Uniform;
+    mFar: Uniform;
+  };
+  vertexShader: string;
+  fragmentShader:string;
+}

+ 404 - 0
examples/jsm/shaders/BokehShader2.js

@@ -0,0 +1,404 @@
+/**
+ * @author zz85 / https://github.com/zz85 | twitter.com/blurspline
+ *
+ * Depth-of-field shader with bokeh
+ * ported from GLSL shader by Martins Upitis
+ * http://blenderartists.org/forum/showthread.php?237488-GLSL-depth-of-field-with-bokeh-v2-4-(update)
+ *
+ * Requires #define RINGS and SAMPLES integers
+ */
+
+import {
+	Vector2
+} from "../../../build/three.module.js";
+
+
+
+var BokehShader = {
+
+	uniforms: {
+
+		"textureWidth": { value: 1.0 },
+		"textureHeight": { value: 1.0 },
+
+		"focalDepth": { value: 1.0 },
+		"focalLength": { value: 24.0 },
+		"fstop": { value: 0.9 },
+
+		"tColor": { value: null },
+		"tDepth": { value: null },
+
+		"maxblur": { value: 1.0 },
+
+		"showFocus": { value: 0 },
+		"manualdof": { value: 0 },
+		"vignetting": { value: 0 },
+		"depthblur": { value: 0 },
+
+		"threshold": { value: 0.5 },
+		"gain": { value: 2.0 },
+		"bias": { value: 0.5 },
+		"fringe": { value: 0.7 },
+
+		"znear": { value: 0.1 },
+		"zfar": { value: 100 },
+
+		"noise": { value: 1 },
+		"dithering": { value: 0.0001 },
+		"pentagon": { value: 0 },
+
+		"shaderFocus": { value: 1 },
+		"focusCoords": { value: new Vector2() }
+
+
+	},
+
+	vertexShader: [
+
+		"varying vec2 vUv;",
+
+		"void main() {",
+
+			"vUv = uv;",
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+		"}"
+
+	].join( "\n" ),
+
+	fragmentShader: [
+
+		"#include <common>",
+
+		"varying vec2 vUv;",
+
+		"uniform sampler2D tColor;",
+		"uniform sampler2D tDepth;",
+		"uniform float textureWidth;",
+		"uniform float textureHeight;",
+
+		"uniform float focalDepth;  //focal distance value in meters, but you may use autofocus option below",
+		"uniform float focalLength; //focal length in mm",
+		"uniform float fstop; //f-stop value",
+		"uniform bool showFocus; //show debug focus point and focal range (red = focal point, green = focal range)",
+
+		"/*",
+		"make sure that these two values are the same for your camera, otherwise distances will be wrong.",
+		"*/",
+
+		"uniform float znear; // camera clipping start",
+		"uniform float zfar; // camera clipping end",
+
+		"//------------------------------------------",
+		"//user variables",
+
+		"const int samples = SAMPLES; //samples on the first ring",
+		"const int rings = RINGS; //ring count",
+
+		"const int maxringsamples = rings * samples;",
+
+		"uniform bool manualdof; // manual dof calculation",
+		"float ndofstart = 1.0; // near dof blur start",
+		"float ndofdist = 2.0; // near dof blur falloff distance",
+		"float fdofstart = 1.0; // far dof blur start",
+		"float fdofdist = 3.0; // far dof blur falloff distance",
+
+		"float CoC = 0.03; //circle of confusion size in mm (35mm film = 0.03mm)",
+
+		"uniform bool vignetting; // use optical lens vignetting",
+
+		"float vignout = 1.3; // vignetting outer border",
+		"float vignin = 0.0; // vignetting inner border",
+		"float vignfade = 22.0; // f-stops till vignete fades",
+
+		"uniform bool shaderFocus;",
+		"// disable if you use external focalDepth value",
+
+		"uniform vec2 focusCoords;",
+		"// autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right)",
+		"// if center of screen use vec2(0.5, 0.5);",
+
+		"uniform float maxblur;",
+		"//clamp value of max blur (0.0 = no blur, 1.0 default)",
+
+		"uniform float threshold; // highlight threshold;",
+		"uniform float gain; // highlight gain;",
+
+		"uniform float bias; // bokeh edge bias",
+		"uniform float fringe; // bokeh chromatic aberration / fringing",
+
+		"uniform bool noise; //use noise instead of pattern for sample dithering",
+
+		"uniform float dithering;",
+
+		"uniform bool depthblur; // blur the depth buffer",
+		"float dbsize = 1.25; // depth blur size",
+
+		"/*",
+		"next part is experimental",
+		"not looking good with small sample and ring count",
+		"looks okay starting from samples = 4, rings = 4",
+		"*/",
+
+		"uniform bool pentagon; //use pentagon as bokeh shape?",
+		"float feather = 0.4; //pentagon shape feather",
+
+		"//------------------------------------------",
+
+		"float penta(vec2 coords) {",
+			"//pentagonal shape",
+			"float scale = float(rings) - 1.3;",
+			"vec4  HS0 = vec4( 1.0,         0.0,         0.0,  1.0);",
+			"vec4  HS1 = vec4( 0.309016994, 0.951056516, 0.0,  1.0);",
+			"vec4  HS2 = vec4(-0.809016994, 0.587785252, 0.0,  1.0);",
+			"vec4  HS3 = vec4(-0.809016994,-0.587785252, 0.0,  1.0);",
+			"vec4  HS4 = vec4( 0.309016994,-0.951056516, 0.0,  1.0);",
+			"vec4  HS5 = vec4( 0.0        ,0.0         , 1.0,  1.0);",
+
+			"vec4  one = vec4( 1.0 );",
+
+			"vec4 P = vec4((coords),vec2(scale, scale));",
+
+			"vec4 dist = vec4(0.0);",
+			"float inorout = -4.0;",
+
+			"dist.x = dot( P, HS0 );",
+			"dist.y = dot( P, HS1 );",
+			"dist.z = dot( P, HS2 );",
+			"dist.w = dot( P, HS3 );",
+
+			"dist = smoothstep( -feather, feather, dist );",
+
+			"inorout += dot( dist, one );",
+
+			"dist.x = dot( P, HS4 );",
+			"dist.y = HS5.w - abs( P.z );",
+
+			"dist = smoothstep( -feather, feather, dist );",
+			"inorout += dist.x;",
+
+			"return clamp( inorout, 0.0, 1.0 );",
+		"}",
+
+		"float bdepth(vec2 coords) {",
+			"// Depth buffer blur",
+			"float d = 0.0;",
+			"float kernel[9];",
+			"vec2 offset[9];",
+
+			"vec2 wh = vec2(1.0/textureWidth,1.0/textureHeight) * dbsize;",
+
+			"offset[0] = vec2(-wh.x,-wh.y);",
+			"offset[1] = vec2( 0.0, -wh.y);",
+			"offset[2] = vec2( wh.x -wh.y);",
+
+			"offset[3] = vec2(-wh.x,  0.0);",
+			"offset[4] = vec2( 0.0,   0.0);",
+			"offset[5] = vec2( wh.x,  0.0);",
+
+			"offset[6] = vec2(-wh.x, wh.y);",
+			"offset[7] = vec2( 0.0,  wh.y);",
+			"offset[8] = vec2( wh.x, wh.y);",
+
+			"kernel[0] = 1.0/16.0;   kernel[1] = 2.0/16.0;   kernel[2] = 1.0/16.0;",
+			"kernel[3] = 2.0/16.0;   kernel[4] = 4.0/16.0;   kernel[5] = 2.0/16.0;",
+			"kernel[6] = 1.0/16.0;   kernel[7] = 2.0/16.0;   kernel[8] = 1.0/16.0;",
+
+
+			"for( int i=0; i<9; i++ ) {",
+				"float tmp = texture2D(tDepth, coords + offset[i]).r;",
+				"d += tmp * kernel[i];",
+			"}",
+
+			"return d;",
+		"}",
+
+
+		"vec3 color(vec2 coords,float blur) {",
+			"//processing the sample",
+
+			"vec3 col = vec3(0.0);",
+			"vec2 texel = vec2(1.0/textureWidth,1.0/textureHeight);",
+
+			"col.r = texture2D(tColor,coords + vec2(0.0,1.0)*texel*fringe*blur).r;",
+			"col.g = texture2D(tColor,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;",
+			"col.b = texture2D(tColor,coords + vec2(0.866,-0.5)*texel*fringe*blur).b;",
+
+			"vec3 lumcoeff = vec3(0.299,0.587,0.114);",
+			"float lum = dot(col.rgb, lumcoeff);",
+			"float thresh = max((lum-threshold)*gain, 0.0);",
+			"return col+mix(vec3(0.0),col,thresh*blur);",
+		"}",
+
+		"vec3 debugFocus(vec3 col, float blur, float depth) {",
+			"float edge = 0.002*depth; //distance based edge smoothing",
+			"float m = clamp(smoothstep(0.0,edge,blur),0.0,1.0);",
+			"float e = clamp(smoothstep(1.0-edge,1.0,blur),0.0,1.0);",
+
+			"col = mix(col,vec3(1.0,0.5,0.0),(1.0-m)*0.6);",
+			"col = mix(col,vec3(0.0,0.5,1.0),((1.0-e)-(1.0-m))*0.2);",
+
+			"return col;",
+		"}",
+
+		"float linearize(float depth) {",
+			"return -zfar * znear / (depth * (zfar - znear) - zfar);",
+		"}",
+
+
+		"float vignette() {",
+			"float dist = distance(vUv.xy, vec2(0.5,0.5));",
+			"dist = smoothstep(vignout+(fstop/vignfade), vignin+(fstop/vignfade), dist);",
+			"return clamp(dist,0.0,1.0);",
+		"}",
+
+		"float gather(float i, float j, int ringsamples, inout vec3 col, float w, float h, float blur) {",
+			"float rings2 = float(rings);",
+			"float step = PI*2.0 / float(ringsamples);",
+			"float pw = cos(j*step)*i;",
+			"float ph = sin(j*step)*i;",
+			"float p = 1.0;",
+			"if (pentagon) {",
+				"p = penta(vec2(pw,ph));",
+			"}",
+			"col += color(vUv.xy + vec2(pw*w,ph*h), blur) * mix(1.0, i/rings2, bias) * p;",
+			"return 1.0 * mix(1.0, i /rings2, bias) * p;",
+		"}",
+
+		"void main() {",
+			"//scene depth calculation",
+
+			"float depth = linearize(texture2D(tDepth,vUv.xy).x);",
+
+			"// Blur depth?",
+			"if ( depthblur ) {",
+				"depth = linearize(bdepth(vUv.xy));",
+			"}",
+
+			"//focal plane calculation",
+
+			"float fDepth = focalDepth;",
+
+			"if (shaderFocus) {",
+
+				"fDepth = linearize(texture2D(tDepth,focusCoords).x);",
+
+			"}",
+
+			"// dof blur factor calculation",
+
+			"float blur = 0.0;",
+
+			"if (manualdof) {",
+				"float a = depth-fDepth; // Focal plane",
+				"float b = (a-fdofstart)/fdofdist; // Far DoF",
+				"float c = (-a-ndofstart)/ndofdist; // Near Dof",
+				"blur = (a>0.0) ? b : c;",
+			"} else {",
+				"float f = focalLength; // focal length in mm",
+				"float d = fDepth*1000.0; // focal plane in mm",
+				"float o = depth*1000.0; // depth in mm",
+
+				"float a = (o*f)/(o-f);",
+				"float b = (d*f)/(d-f);",
+				"float c = (d-f)/(d*fstop*CoC);",
+
+				"blur = abs(a-b)*c;",
+			"}",
+
+			"blur = clamp(blur,0.0,1.0);",
+
+			"// calculation of pattern for dithering",
+
+			"vec2 noise = vec2(rand(vUv.xy), rand( vUv.xy + vec2( 0.4, 0.6 ) ) )*dithering*blur;",
+
+			"// getting blur x and y step factor",
+
+			"float w = (1.0/textureWidth)*blur*maxblur+noise.x;",
+			"float h = (1.0/textureHeight)*blur*maxblur+noise.y;",
+
+			"// calculation of final color",
+
+			"vec3 col = vec3(0.0);",
+
+			"if(blur < 0.05) {",
+				"//some optimization thingy",
+				"col = texture2D(tColor, vUv.xy).rgb;",
+			"} else {",
+				"col = texture2D(tColor, vUv.xy).rgb;",
+				"float s = 1.0;",
+				"int ringsamples;",
+
+				"for (int i = 1; i <= rings; i++) {",
+					"/*unboxstart*/",
+					"ringsamples = i * samples;",
+
+					"for (int j = 0 ; j < maxringsamples ; j++) {",
+						"if (j >= ringsamples) break;",
+						"s += gather(float(i), float(j), ringsamples, col, w, h, blur);",
+					"}",
+					"/*unboxend*/",
+				"}",
+
+				"col /= s; //divide by sample count",
+			"}",
+
+			"if (showFocus) {",
+				"col = debugFocus(col, blur, depth);",
+			"}",
+
+			"if (vignetting) {",
+				"col *= vignette();",
+			"}",
+
+			"gl_FragColor.rgb = col;",
+			"gl_FragColor.a = 1.0;",
+		"} "
+
+	].join( "\n" )
+
+};
+
+var BokehDepthShader = {
+
+	uniforms: {
+
+		"mNear": { value: 1.0 },
+		"mFar": { value: 1000.0 },
+
+	},
+
+	vertexShader: [
+
+		"varying float vViewZDepth;",
+
+		"void main() {",
+
+		"	#include <begin_vertex>",
+		"	#include <project_vertex>",
+
+		"	vViewZDepth = - mvPosition.z;",
+
+		"}"
+
+	].join( "\n" ),
+
+	fragmentShader: [
+
+		"uniform float mNear;",
+		"uniform float mFar;",
+
+		"varying float vViewZDepth;",
+
+		"void main() {",
+
+		"	float color = 1.0 - smoothstep( mNear, mFar, vViewZDepth );",
+		"	gl_FragColor = vec4( vec3( color ), 1.0 );",
+
+		"} "
+
+	].join( "\n" )
+
+};
+
+export { BokehShader, BokehDepthShader };

+ 12 - 0
examples/jsm/shaders/UnpackDepthRGBAShader.d.ts

@@ -0,0 +1,12 @@
+import {
+  Uniform
+} from '../../../src/Three';
+
+export interface UnpackDepthRGBAShader {
+  uniforms: {
+    tDiffuse: Uniform;
+    opacity: Uniform;
+  };
+  vertexShader: string;
+  fragmentShader:string;
+}

+ 3 - 0
utils/modularize.js

@@ -9,6 +9,8 @@ var srcFolder = __dirname + '/../examples/js/';
 var dstFolder = __dirname + '/../examples/jsm/';
 
 var files = [
+	{ path: 'cameras/CinematicCamera.js', dependencies: [ { name: 'BokehShader', path: 'shaders/BokehShader2.js' }, { name: 'BokehDepthShader', path: 'shaders/BokehShader2.js' } ], ignoreList: [] },
+
 	{ path: 'controls/DragControls.js', dependencies: [], ignoreList: [] },
 	{ path: 'controls/DeviceOrientationControls.js', dependencies: [], ignoreList: [] },
 	{ path: 'controls/EditorControls.js', dependencies: [], ignoreList: [] },
@@ -57,6 +59,7 @@ var files = [
 	{ path: 'pmrem/PMREMCubeUVPacker.js', dependencies: [], ignoreList: [] },
 	{ path: 'pmrem/PMREMGenerator.js', dependencies: [], ignoreList: [] },
 
+	{ path: 'shaders/BokehShader2.js', dependencies: [], ignoreList: [] },
 	{ path: 'shaders/UnpackDepthRGBAShader.js', dependencies: [], ignoreList: [] },
 
 	{ path: 'renderers/CSS2DRenderer.js', dependencies: [], ignoreList: [] },