CinematicCamera.js 6.0 KB
Newer Older
K
kaypikun 已提交
1
/**
M
Mr.doob 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 * @author mrdoob / http://mrdoob.com/
 * @author greggman / http://games.greggman.com/
 * @author zz85 / http://www.lab4games.net/zz85/blog
 * @author kaypiKun
 */

THREE.CinematicCamera = function( fov, aspect, near, far ) {

	THREE.PerspectiveCamera.call( this, fov, aspect, near, far );

	this.type = "CinematicCamera";

	this.postprocessing = { enabled	: true };
	this.shaderSettings = {
		rings: 3,
		samples: 4
	};

	this.material_depth = new THREE.MeshDepthMaterial();

	// In case of cinematicCamera, having a default lens set is important
	this.setLens();

	this.initPostProcessing();

K
kaypikun 已提交
27 28
};

M
Mr.doob 已提交
29
THREE.CinematicCamera.prototype = Object.create( THREE.PerspectiveCamera.prototype );
K
kaypikun 已提交
30 31 32
THREE.CinematicCamera.prototype.constructor = THREE.CinematicCamera;


M
Mr.doob 已提交
33
// providing fnumber and coc(Circle of Confusion) as extra arguments
T
tschw 已提交
34
THREE.CinematicCamera.prototype.setLens = function ( focalLength, filmGauge, fNumber, coc ) {
K
kaypikun 已提交
35

M
Mr.doob 已提交
36 37
	// In case of cinematicCamera, having a default lens set is important
	if ( focalLength === undefined ) focalLength = 35;
T
tschw 已提交
38
	if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
K
kaypikun 已提交
39

T
tschw 已提交
40
	this.setFocalLength( focalLength );
K
kaypikun 已提交
41

M
Mr.doob 已提交
42 43 44
	// 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;
K
kaypikun 已提交
45

M
Mr.doob 已提交
46 47
	this.fNumber = fNumber;
	this.coc = coc;
K
kaypikun 已提交
48

M
Mr.doob 已提交
49
	// fNumber is focalLength by aperture
T
tschw 已提交
50
	this.aperture = focalLength / this.fNumber;
K
kaypikun 已提交
51

M
Mr.doob 已提交
52
	// hyperFocal is required to calculate depthOfField when a lens tries to focus at a distance with given fNumber and focalLength
T
tschw 已提交
53
	this.hyperFocal = ( focalLength * focalLength ) / ( this.aperture * this.coc );
K
kaypikun 已提交
54

M
Mr.doob 已提交
55
};
K
kaypikun 已提交
56

M
Mr.doob 已提交
57 58 59 60 61
THREE.CinematicCamera.prototype.linearize = function ( depth ) {

	var zfar = this.far;
	var znear = this.near;
	return - zfar * znear / ( depth * ( zfar - znear ) - zfar );
K
kaypikun 已提交
62 63 64

};

M
Mr.doob 已提交
65
THREE.CinematicCamera.prototype.smoothstep = function ( near, far, depth ) {
K
kaypikun 已提交
66

M
Mr.doob 已提交
67 68
	var x = this.saturate( ( depth - near ) / ( far - near ) );
	return x * x * ( 3 - 2 * x );
K
kaypikun 已提交
69

M
Mr.doob 已提交
70
};
K
kaypikun 已提交
71

M
Mr.doob 已提交
72
THREE.CinematicCamera.prototype.saturate = function ( x ) {
K
kaypikun 已提交
73

M
Mr.doob 已提交
74
	return Math.max( 0, Math.min( 1, x ) );
K
kaypikun 已提交
75

M
Mr.doob 已提交
76
};
K
kaypikun 已提交
77

M
Mr.doob 已提交
78 79
// function for focusing at a distance from the camera
THREE.CinematicCamera.prototype.focusAt = function ( focusDistance ) {
K
kaypikun 已提交
80

M
Mr.doob 已提交
81
	if ( focusDistance === undefined ) focusDistance = 20;
K
kaypikun 已提交
82

T
tschw 已提交
83 84 85 86
	var focalLength = this.getFocalLength();

	// distance from the camera (normal to frustrum) to focus on
	this.focus = focusDistance;
K
kaypikun 已提交
87

M
Mr.doob 已提交
88
	// the nearest point from the camera which is in focus (unused)
T
tschw 已提交
89
	this.nearPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal + ( this.focus - focalLength ) );
K
kaypikun 已提交
90

M
Mr.doob 已提交
91
	// the farthest point from the camera which is in focus (unused)
T
tschw 已提交
92
	this.farPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal - ( this.focus - focalLength ) );
K
kaypikun 已提交
93

M
Mr.doob 已提交
94 95
	// the gap or width of the space in which is everything is in focus (unused)
	this.depthOfField = this.farPoint - this.nearPoint;
K
kaypikun 已提交
96

M
Mr.doob 已提交
97 98
	// Considering minimum distance of focus for a standard lens (unused)
	if ( this.depthOfField < 0 ) this.depthOfField = 0;
K
kaypikun 已提交
99

T
tschw 已提交
100
	this.sdistance = this.smoothstep( this.near, this.far, this.focus );
K
kaypikun 已提交
101

M
Mr.doob 已提交
102
	this.ldistance = this.linearize( 1 -	this.sdistance );
K
kaypikun 已提交
103 104 105 106 107

	this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = this.ldistance;

};

M
Mr.doob 已提交
108 109 110
THREE.CinematicCamera.prototype.initPostProcessing = function () {

	if ( this.postprocessing.enabled ) {
K
kaypikun 已提交
111

M
Mr.doob 已提交
112
		this.postprocessing.scene = new THREE.Scene();
K
kaypikun 已提交
113

M
Mr.doob 已提交
114
		this.postprocessing.camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2,	window.innerHeight / 2, window.innerHeight / - 2, - 10000, 10000 );
K
kaypikun 已提交
115

M
Mr.doob 已提交
116
		this.postprocessing.scene.add( this.postprocessing.camera );
K
kaypikun 已提交
117

M
Mr.doob 已提交
118 119 120
		var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
		this.postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
		this.postprocessing.rtTextureColor = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
K
kaypikun 已提交
121

M
Mr.doob 已提交
122
		var bokeh_shader = THREE.BokehShader;
K
kaypikun 已提交
123

M
Mr.doob 已提交
124
		this.postprocessing.bokeh_uniforms = THREE.UniformsUtils.clone( bokeh_shader.uniforms );
K
kaypikun 已提交
125

M
Mr.doob 已提交
126 127
		this.postprocessing.bokeh_uniforms[ "tColor" ].value = this.postprocessing.rtTextureColor;
		this.postprocessing.bokeh_uniforms[ "tDepth" ].value = this.postprocessing.rtTextureDepth;
K
kaypikun 已提交
128

M
Mr.doob 已提交
129 130
		this.postprocessing.bokeh_uniforms[ "manualdof" ].value = 0;
		this.postprocessing.bokeh_uniforms[ "shaderFocus" ].value = 0;
K
kaypikun 已提交
131

M
Mr.doob 已提交
132
		this.postprocessing.bokeh_uniforms[ "fstop" ].value = 2.8;
K
kaypikun 已提交
133

M
Mr.doob 已提交
134
		this.postprocessing.bokeh_uniforms[ "showFocus" ].value = 1;
K
kaypikun 已提交
135

M
Mr.doob 已提交
136
		this.postprocessing.bokeh_uniforms[ "focalDepth" ].value = 0.1;
K
kaypikun 已提交
137

M
Mr.doob 已提交
138
		console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value );
K
kaypikun 已提交
139

M
Mr.doob 已提交
140 141
		this.postprocessing.bokeh_uniforms[ "znear" ].value = this.near;
		this.postprocessing.bokeh_uniforms[ "zfar" ].value = this.near;
K
kaypikun 已提交
142 143


M
Mr.doob 已提交
144
		this.postprocessing.bokeh_uniforms[ "textureWidth" ].value = window.innerWidth;
K
kaypikun 已提交
145

M
Mr.doob 已提交
146
		this.postprocessing.bokeh_uniforms[ "textureHeight" ].value = window.innerHeight;
K
kaypikun 已提交
147

M
Mr.doob 已提交
148 149 150 151 152 153 154 155 156
		this.postprocessing.materialBokeh = new THREE.ShaderMaterial( {
			uniforms: this.postprocessing.bokeh_uniforms,
			vertexShader: bokeh_shader.vertexShader,
			fragmentShader: bokeh_shader.fragmentShader,
			defines: {
				RINGS: this.shaderSettings.rings,
				SAMPLES: this.shaderSettings.samples
			}
		} );
K
kaypikun 已提交
157

M
Mr.doob 已提交
158 159 160
		this.postprocessing.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight ), this.postprocessing.materialBokeh );
		this.postprocessing.quad.position.z = - 500;
		this.postprocessing.scene.add( this.postprocessing.quad );
K
kaypikun 已提交
161

M
Mr.doob 已提交
162
	}
K
kaypikun 已提交
163

M
Mr.doob 已提交
164
};
K
kaypikun 已提交
165

M
Mr.doob 已提交
166
THREE.CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) {
K
kaypikun 已提交
167

M
Mr.doob 已提交
168
	if ( this.postprocessing.enabled ) {
K
kaypikun 已提交
169

M
Mr.doob 已提交
170
		renderer.clear();
K
kaypikun 已提交
171

M
Mr.doob 已提交
172
		// Render scene into texture
K
kaypikun 已提交
173

M
Mr.doob 已提交
174 175
		scene.overrideMaterial = null;
		renderer.render( scene, camera, this.postprocessing.rtTextureColor, true );
K
kaypikun 已提交
176

M
Mr.doob 已提交
177
		// Render depth into texture
K
kaypikun 已提交
178

M
Mr.doob 已提交
179 180
		scene.overrideMaterial = this.material_depth;
		renderer.render( scene, camera, this.postprocessing.rtTextureDepth, true );
K
kaypikun 已提交
181

M
Mr.doob 已提交
182
		// Render bokeh composite
K
kaypikun 已提交
183

M
Mr.doob 已提交
184
		renderer.render( this.postprocessing.scene, this.postprocessing.camera );
K
kaypikun 已提交
185

M
Mr.doob 已提交
186
	}
K
kaypikun 已提交
187

M
Mr.doob 已提交
188
};