WebGLShadowMap.js 7.5 KB
Newer Older
A
alteredq 已提交
1 2
/**
 * @author alteredq / http://alteredqualia.com/
M
Mr.doob 已提交
3
 * @author mrdoob / http://mrdoob.com/
A
alteredq 已提交
4 5
 */

M
Mr.doob 已提交
6
THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
A
alteredq 已提交
7

8
	var _gl = _renderer.context,
M
Mr.doob 已提交
9
	_state = _renderer.state,
A
alteredq 已提交
10
	_frustum = new THREE.Frustum(),
A
alteredq 已提交
11
	_projScreenMatrix = new THREE.Matrix4(),
A
alteredq 已提交
12

13
	_min = new THREE.Vector3(),
14 15
	_max = new THREE.Vector3(),

O
OpenShift guest 已提交
16
	_matrixPosition = new THREE.Vector3(),
M
Mr.doob 已提交
17

O
OpenShift guest 已提交
18
	_renderList = [];
19

M
Mr.doob 已提交
20 21 22 23 24
	// init

	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );

25
	var _depthMaterial = new THREE.ShaderMaterial( {
M
Mr.doob 已提交
26 27 28 29 30
		uniforms: depthUniforms,
		vertexShader: depthShader.vertexShader,
		fragmentShader: depthShader.fragmentShader
	 } );

31
	var _depthMaterialMorph = new THREE.ShaderMaterial( {
M
Mr.doob 已提交
32 33 34 35 36 37
		uniforms: depthUniforms,
		vertexShader: depthShader.vertexShader,
		fragmentShader: depthShader.fragmentShader,
		morphTargets: true
	} );

38
	var _depthMaterialSkin = new THREE.ShaderMaterial( {
M
Mr.doob 已提交
39 40 41 42 43 44
		uniforms: depthUniforms,
		vertexShader: depthShader.vertexShader,
		fragmentShader: depthShader.fragmentShader,
		skinning: true
	} );

45
	var _depthMaterialMorphSkin = new THREE.ShaderMaterial( {
M
Mr.doob 已提交
46 47 48 49 50 51 52 53 54 55 56
		uniforms: depthUniforms,
		vertexShader: depthShader.vertexShader,
		fragmentShader: depthShader.fragmentShader,
		morphTargets: true,
		skinning: true
	} );

	_depthMaterial._shadowPass = true;
	_depthMaterialMorph._shadowPass = true;
	_depthMaterialSkin._shadowPass = true;
	_depthMaterialMorphSkin._shadowPass = true;
A
alteredq 已提交
57

58 59 60 61 62
	//

	var scope = this;

	this.enabled = false;
63 64 65 66

	this.autoUpdate = true;
	this.needsUpdate = false;

67 68 69
	this.type = THREE.PCFShadowMap;
	this.cullFace = THREE.CullFaceFront;

A
alteredq 已提交
70 71
	this.render = function ( scene, camera ) {

72
		if ( scope.enabled === false ) return;
73
		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
A
alteredq 已提交
74

A
alteredq 已提交
75 76
		// set GL state for depth map

77
		_gl.clearColor( 1, 1, 1, 1 );
78
		_state.disable( _gl.BLEND );
79

80
		_state.enable( _gl.CULL_FACE );
81
		_gl.frontFace( _gl.CCW );
82

83
		if ( scope.cullFace === THREE.CullFaceFront ) {
84 85 86 87 88 89 90 91

			_gl.cullFace( _gl.FRONT );

		} else {

			_gl.cullFace( _gl.BACK );

		}
A
alteredq 已提交
92

M
Mr.doob 已提交
93
		_state.setDepthTest( true );
A
alteredq 已提交
94

95
		// render depth map
96

97
		for ( var i = 0, il = _lights.length; i < il; i ++ ) {
98

99
			var light = _lights[ i ];
100 101 102

			if ( ! light.castShadow ) continue;

A
alteredq 已提交
103
			if ( ! light.shadowMap ) {
A
alteredq 已提交
104

105
				var shadowFilter = THREE.LinearFilter;
106

107
				if ( scope.type === THREE.PCFSoftShadowMap ) {
108

109
					shadowFilter = THREE.NearestFilter;
110

111
				}
112

113
				var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
A
alteredq 已提交
114

A
alteredq 已提交
115 116 117 118 119 120 121 122 123 124
				light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
				light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );

				light.shadowMatrix = new THREE.Matrix4();

			}

			if ( ! light.shadowCamera ) {

				if ( light instanceof THREE.SpotLight ) {
125 126

					light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
A
alteredq 已提交
127

A
alteredq 已提交
128 129 130
				} else if ( light instanceof THREE.DirectionalLight ) {

					light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );
131

A
alteredq 已提交
132 133
				} else {

134
					console.error( "THREE.ShadowMapPlugin: Unsupported light type for shadow", light );
A
alteredq 已提交
135
					continue;
136 137 138

				}

A
alteredq 已提交
139
				scene.add( light.shadowCamera );
140

141
				if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
142

A
alteredq 已提交
143
			}
A
alteredq 已提交
144

A
alteredq 已提交
145
			if ( light.shadowCameraVisible && ! light.cameraHelper ) {
A
alteredq 已提交
146

A
alteredq 已提交
147
				light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
148
				scene.add( light.cameraHelper );
A
alteredq 已提交
149

A
alteredq 已提交
150
			}
A
alteredq 已提交
151

152 153 154
			var shadowMap = light.shadowMap;
			var shadowMatrix = light.shadowMatrix;
			var shadowCamera = light.shadowCamera;
A
alteredq 已提交
155

M
Mr.doob 已提交
156 157
			//

158 159
			shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
			_matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
160
			shadowCamera.lookAt( _matrixPosition );
161
			shadowCamera.updateMatrixWorld();
A
alteredq 已提交
162

A
alteredq 已提交
163
			shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
A
alteredq 已提交
164

M
Mr.doob 已提交
165 166
			//

167
			if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
168
			if ( light.shadowCameraVisible ) light.cameraHelper.update();
A
alteredq 已提交
169

A
alteredq 已提交
170
			// compute shadow matrix
A
alteredq 已提交
171

M
Mr.doob 已提交
172 173 174 175 176 177
			shadowMatrix.set(
				0.5, 0.0, 0.0, 0.5,
				0.0, 0.5, 0.0, 0.5,
				0.0, 0.0, 0.5, 0.5,
				0.0, 0.0, 0.0, 1.0
			);
A
alteredq 已提交
178

179 180
			shadowMatrix.multiply( shadowCamera.projectionMatrix );
			shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
A
alteredq 已提交
181

A
alteredq 已提交
182
			// update camera matrices and frustum
A
alteredq 已提交
183

184
			_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
A
alteredq 已提交
185
			_frustum.setFromMatrix( _projScreenMatrix );
A
alteredq 已提交
186

A
alteredq 已提交
187 188
			// render shadow map

A
alteredq 已提交
189 190
			_renderer.setRenderTarget( shadowMap );
			_renderer.clear();
A
alteredq 已提交
191

A
alteredq 已提交
192
			// set object matrices & frustum culling
A
alteredq 已提交
193

O
OpenShift guest 已提交
194
			_renderList.length = 0;
M
Mr.doob 已提交
195

M
Mr.doob 已提交
196
			projectObject( scene, shadowCamera );
A
alteredq 已提交
197 198


A
alteredq 已提交
199
			// render regular objects
A
alteredq 已提交
200

201
			for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
A
alteredq 已提交
202

203 204 205
				var object = _renderList[ j ];
				var geometry = _objects.update( object );
				var material = object.material;
206

207
				if ( material instanceof THREE.MeshFaceMaterial ) {
208

209
					var groups = geometry.groups;
210
					var materials = material.materials;
211

212
					for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
213

214
						var group = groups[ k ];
215
						var groupMaterial = materials[ group.materialIndex ];
216

M
Mr.doob 已提交
217
						if ( groupMaterial.visible === true ) {
218

219
							_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, groupMaterial ), object, group );
220

221
						}
222

223
					}
A
alteredq 已提交
224

O
OpenShift guest 已提交
225
				} else {
A
alteredq 已提交
226

227
					_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, material ), object, null );
228

O
OpenShift guest 已提交
229
				}
230

A
alteredq 已提交
231
			}
A
alteredq 已提交
232 233 234

		}

A
alteredq 已提交
235 236 237 238 239
		// restore GL state

		var clearColor = _renderer.getClearColor(),
		clearAlpha = _renderer.getClearAlpha();

S
fix  
Steven Lu (PuTTY Win7 on rMBP[tmux]) 已提交
240
		_renderer.setClearColor( clearColor, clearAlpha );
241
		_state.enable( _gl.BLEND );
242

243
		if ( scope.cullFace === THREE.CullFaceFront ) {
244 245 246 247

			_gl.cullFace( _gl.BACK );

		}
A
alteredq 已提交
248

249 250
		_renderer.resetGLState();

251 252
		scope.needsUpdate = false;

A
alteredq 已提交
253
	};
M
Mr.doob 已提交
254

255
	function getDepthMaterial( object, material ) {
256

257
		var geometry = object.geometry;
258

259 260
		var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
		var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
261

262
		var depthMaterial;
263 264 265

		if ( object.customDepthMaterial ) {

266
			depthMaterial = object.customDepthMaterial;
267 268 269

		} else if ( useSkinning ) {

270
			depthMaterial = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
271 272 273

		} else if ( useMorphing ) {

274
			depthMaterial = _depthMaterialMorph;
275 276 277

		} else {

278
			depthMaterial = _depthMaterial;
279 280 281

		}

282
		depthMaterial.visible = material.visible;
283
		depthMaterial.wireframe = material.wireframe;
284
		depthMaterial.wireframeLinewidth = material.wireframeLinewidth;
285

286
		return depthMaterial;
287 288 289

	}

290
	function projectObject( object, camera ) {
M
Mr.doob 已提交
291

M
Mr.doob 已提交
292
		if ( object.visible === false ) return;
M
Mr.doob 已提交
293

294
		if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
M
Mr.doob 已提交
295

296
			if ( object.castShadow && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {
M
Mr.doob 已提交
297

298
				var material = object.material;
299

300
				if ( material.visible === true ) {
301

302 303 304 305
					object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
					_renderList.push( object );

				}
306 307

			}
M
Mr.doob 已提交
308

M
Mr.doob 已提交
309
		}
M
Mr.doob 已提交
310

M
Mr.doob 已提交
311
		var children = object.children;
M
Mr.doob 已提交
312

M
Mr.doob 已提交
313
		for ( var i = 0, l = children.length; i < l; i ++ ) {
M
Mr.doob 已提交
314

M
Mr.doob 已提交
315
			projectObject( children[ i ], camera );
M
Mr.doob 已提交
316

O
OpenShift guest 已提交
317
		}
M
Mr.doob 已提交
318

O
OpenShift guest 已提交
319
	}
A
alteredq 已提交
320

321
};