| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 | ( function () {	class Lensflare extends THREE.Mesh {		constructor() {			super( Lensflare.Geometry, new THREE.MeshBasicMaterial( {				opacity: 0,				transparent: true			} ) );			this.type = 'Lensflare';			this.frustumCulled = false;			this.renderOrder = Infinity; //			const positionScreen = new THREE.Vector3();			const positionView = new THREE.Vector3(); // textures			const tempMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );			tempMap.minFilter = THREE.NearestFilter;			tempMap.magFilter = THREE.NearestFilter;			tempMap.wrapS = THREE.ClampToEdgeWrapping;			tempMap.wrapT = THREE.ClampToEdgeWrapping;			const occlusionMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );			occlusionMap.minFilter = THREE.NearestFilter;			occlusionMap.magFilter = THREE.NearestFilter;			occlusionMap.wrapS = THREE.ClampToEdgeWrapping;			occlusionMap.wrapT = THREE.ClampToEdgeWrapping; // material			const geometry = Lensflare.Geometry;			const material1a = new THREE.RawShaderMaterial( {				uniforms: {					'scale': {						value: null					},					'screenPosition': {						value: null					}				},				vertexShader:      /* glsl */      `				precision highp float;				uniform vec3 screenPosition;				uniform vec2 scale;				attribute vec3 position;				void main() {					gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );				}`,				fragmentShader:      /* glsl */      `				precision highp float;				void main() {					gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );				}`,				depthTest: true,				depthWrite: false,				transparent: false			} );			const material1b = new THREE.RawShaderMaterial( {				uniforms: {					'map': {						value: tempMap					},					'scale': {						value: null					},					'screenPosition': {						value: null					}				},				vertexShader:      /* glsl */      `				precision highp float;				uniform vec3 screenPosition;				uniform vec2 scale;				attribute vec3 position;				attribute vec2 uv;				varying vec2 vUV;				void main() {					vUV = uv;					gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );				}`,				fragmentShader:      /* glsl */      `				precision highp float;				uniform sampler2D map;				varying vec2 vUV;				void main() {					gl_FragColor = texture2D( map, vUV );				}`,				depthTest: false,				depthWrite: false,				transparent: false			} ); // the following object is used for occlusionMap generation			const mesh1 = new THREE.Mesh( geometry, material1a ); //			const elements = [];			const shader = LensflareElement.Shader;			const material2 = new THREE.RawShaderMaterial( {				uniforms: {					'map': {						value: null					},					'occlusionMap': {						value: occlusionMap					},					'color': {						value: new THREE.Color( 0xffffff )					},					'scale': {						value: new THREE.Vector2()					},					'screenPosition': {						value: new THREE.Vector3()					}				},				vertexShader: shader.vertexShader,				fragmentShader: shader.fragmentShader,				blending: THREE.AdditiveBlending,				transparent: true,				depthWrite: false			} );			const mesh2 = new THREE.Mesh( geometry, material2 );			this.addElement = function ( element ) {				elements.push( element );			}; //			const scale = new THREE.Vector2();			const screenPositionPixels = new THREE.Vector2();			const validArea = new THREE.Box2();			const viewport = new THREE.Vector4();			this.onBeforeRender = function ( renderer, scene, camera ) {				renderer.getCurrentViewport( viewport );				const invAspect = viewport.w / viewport.z;				const halfViewportWidth = viewport.z / 2.0;				const halfViewportHeight = viewport.w / 2.0;				let size = 16 / viewport.w;				scale.set( size * invAspect, size );				validArea.min.set( viewport.x, viewport.y );				validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); // calculate position in screen space				positionView.setFromMatrixPosition( this.matrixWorld );				positionView.applyMatrix4( camera.matrixWorldInverse );				if ( positionView.z > 0 ) return; // lensflare is behind the camera				positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); // horizontal and vertical coordinate of the lower left corner of the pixels to copy				screenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8;				screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; // screen cull				if ( validArea.containsPoint( screenPositionPixels ) ) {					// save current RGB to temp texture					renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); // render pink quad					let uniforms = material1a.uniforms;					uniforms[ 'scale' ].value = scale;					uniforms[ 'screenPosition' ].value = positionScreen;					renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); // copy result to occlusionMap					renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); // restore graphics					uniforms = material1b.uniforms;					uniforms[ 'scale' ].value = scale;					uniforms[ 'screenPosition' ].value = positionScreen;					renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); // render elements					const vecX = - positionScreen.x * 2;					const vecY = - positionScreen.y * 2;					for ( let i = 0, l = elements.length; i < l; i ++ ) {						const element = elements[ i ];						const uniforms = material2.uniforms;						uniforms[ 'color' ].value.copy( element.color );						uniforms[ 'map' ].value = element.texture;						uniforms[ 'screenPosition' ].value.x = positionScreen.x + vecX * element.distance;						uniforms[ 'screenPosition' ].value.y = positionScreen.y + vecY * element.distance;						size = element.size / viewport.w;						const invAspect = viewport.w / viewport.z;						uniforms[ 'scale' ].value.set( size * invAspect, size );						material2.uniformsNeedUpdate = true;						renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );					}				}			};			this.dispose = function () {				material1a.dispose();				material1b.dispose();				material2.dispose();				tempMap.dispose();				occlusionMap.dispose();				for ( let i = 0, l = elements.length; i < l; i ++ ) {					elements[ i ].texture.dispose();				}			};		}	}	Lensflare.prototype.isLensflare = true; //	class LensflareElement {		constructor( texture, size = 1, distance = 0, color = new THREE.Color( 0xffffff ) ) {			this.texture = texture;			this.size = size;			this.distance = distance;			this.color = color;		}	}	LensflareElement.Shader = {		uniforms: {			'map': {				value: null			},			'occlusionMap': {				value: null			},			'color': {				value: null			},			'scale': {				value: null			},			'screenPosition': {				value: null			}		},		vertexShader:  /* glsl */  `		precision highp float;		uniform vec3 screenPosition;		uniform vec2 scale;		uniform sampler2D occlusionMap;		attribute vec3 position;		attribute vec2 uv;		varying vec2 vUV;		varying float vVisibility;		void main() {			vUV = uv;			vec2 pos = position.xy;			vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );			visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );			visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );			visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );			visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );			visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );			visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );			visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );			visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );			vVisibility =        visibility.r / 9.0;			vVisibility *= 1.0 - visibility.g / 9.0;			vVisibility *=       visibility.b / 9.0;			gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );		}`,		fragmentShader:  /* glsl */  `		precision highp float;		uniform sampler2D map;		uniform vec3 color;		varying vec2 vUV;		varying float vVisibility;		void main() {			vec4 texture = texture2D( map, vUV );			texture.a *= vVisibility;			gl_FragColor = texture;			gl_FragColor.rgb *= color;		}`	};	Lensflare.Geometry = function () {		const geometry = new THREE.BufferGeometry();		const float32Array = new Float32Array( [ - 1, - 1, 0, 0, 0, 1, - 1, 0, 1, 0, 1, 1, 0, 1, 1, - 1, 1, 0, 0, 1 ] );		const interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 );		geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );		geometry.setAttribute( 'position', new THREE.InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );		geometry.setAttribute( 'uv', new THREE.InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );		return geometry;	}();	THREE.Lensflare = Lensflare;	THREE.LensflareElement = LensflareElement;} )();
 |