81 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			81 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
									Matrix4,
							 | 
						||
| 
								 | 
							
									Mesh,
							 | 
						||
| 
								 | 
							
									MeshBasicMaterial,
							 | 
						||
| 
								 | 
							
									EqualStencilFunc,
							 | 
						||
| 
								 | 
							
									IncrementStencilOp
							 | 
						||
| 
								 | 
							
								} from 'three';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * A shadow Mesh that follows a shadow-casting Mesh in the scene, but is confined to a single plane.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const _shadowMatrix = new Matrix4();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ShadowMesh extends Mesh {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									constructor( mesh ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const shadowMaterial = new MeshBasicMaterial( {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											color: 0x000000,
							 | 
						||
| 
								 | 
							
											transparent: true,
							 | 
						||
| 
								 | 
							
											opacity: 0.6,
							 | 
						||
| 
								 | 
							
											depthWrite: false,
							 | 
						||
| 
								 | 
							
											stencilWrite: true,
							 | 
						||
| 
								 | 
							
											stencilFunc: EqualStencilFunc,
							 | 
						||
| 
								 | 
							
											stencilRef: 0,
							 | 
						||
| 
								 | 
							
											stencilZPass: IncrementStencilOp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										super( mesh.geometry, shadowMaterial );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.isShadowMesh = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.meshMatrix = mesh.matrixWorld;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.frustumCulled = false;
							 | 
						||
| 
								 | 
							
										this.matrixAutoUpdate = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									update( plane, lightPosition4D ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// based on https://www.opengl.org/archives/resources/features/StencilTalk/tsld021.htm
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const dot = plane.normal.x * lightPosition4D.x +
							 | 
						||
| 
								 | 
							
											  plane.normal.y * lightPosition4D.y +
							 | 
						||
| 
								 | 
							
											  plane.normal.z * lightPosition4D.z +
							 | 
						||
| 
								 | 
							
											  - plane.constant * lightPosition4D.w;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const sme = _shadowMatrix.elements;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sme[ 0 ] = dot - lightPosition4D.x * plane.normal.x;
							 | 
						||
| 
								 | 
							
										sme[ 4 ] = - lightPosition4D.x * plane.normal.y;
							 | 
						||
| 
								 | 
							
										sme[ 8 ] = - lightPosition4D.x * plane.normal.z;
							 | 
						||
| 
								 | 
							
										sme[ 12 ] = - lightPosition4D.x * - plane.constant;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sme[ 1 ] = - lightPosition4D.y * plane.normal.x;
							 | 
						||
| 
								 | 
							
										sme[ 5 ] = dot - lightPosition4D.y * plane.normal.y;
							 | 
						||
| 
								 | 
							
										sme[ 9 ] = - lightPosition4D.y * plane.normal.z;
							 | 
						||
| 
								 | 
							
										sme[ 13 ] = - lightPosition4D.y * - plane.constant;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sme[ 2 ] = - lightPosition4D.z * plane.normal.x;
							 | 
						||
| 
								 | 
							
										sme[ 6 ] = - lightPosition4D.z * plane.normal.y;
							 | 
						||
| 
								 | 
							
										sme[ 10 ] = dot - lightPosition4D.z * plane.normal.z;
							 | 
						||
| 
								 | 
							
										sme[ 14 ] = - lightPosition4D.z * - plane.constant;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sme[ 3 ] = - lightPosition4D.w * plane.normal.x;
							 | 
						||
| 
								 | 
							
										sme[ 7 ] = - lightPosition4D.w * plane.normal.y;
							 | 
						||
| 
								 | 
							
										sme[ 11 ] = - lightPosition4D.w * plane.normal.z;
							 | 
						||
| 
								 | 
							
										sme[ 15 ] = dot - lightPosition4D.w * - plane.constant;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.matrix.multiplyMatrices( _shadowMatrix, this.meshMatrix );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export { ShadowMesh };
							 |