200 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			200 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | import { | ||
|  | 	HalfFloatType, | ||
|  | 	LinearFilter, | ||
|  | 	NearestFilter, | ||
|  | 	ShaderMaterial, | ||
|  | 	Texture, | ||
|  | 	UniformsUtils, | ||
|  | 	WebGLRenderTarget | ||
|  | } from 'three'; | ||
|  | import { Pass, FullScreenQuad } from './Pass.js'; | ||
|  | import { SMAAEdgesShader } from '../shaders/SMAAShader.js'; | ||
|  | import { SMAAWeightsShader } from '../shaders/SMAAShader.js'; | ||
|  | import { SMAABlendShader } from '../shaders/SMAAShader.js'; | ||
|  | 
 | ||
|  | class SMAAPass extends Pass { | ||
|  | 
 | ||
|  | 	constructor( width, height ) { | ||
|  | 
 | ||
|  | 		super(); | ||
|  | 
 | ||
|  | 		// render targets
 | ||
|  | 
 | ||
|  | 		this.edgesRT = new WebGLRenderTarget( width, height, { | ||
|  | 			depthBuffer: false, | ||
|  | 			type: HalfFloatType | ||
|  | 		} ); | ||
|  | 		this.edgesRT.texture.name = 'SMAAPass.edges'; | ||
|  | 
 | ||
|  | 		this.weightsRT = new WebGLRenderTarget( width, height, { | ||
|  | 			depthBuffer: false, | ||
|  | 			type: HalfFloatType | ||
|  | 		} ); | ||
|  | 		this.weightsRT.texture.name = 'SMAAPass.weights'; | ||
|  | 
 | ||
|  | 		// textures
 | ||
|  | 		const scope = this; | ||
|  | 
 | ||
|  | 		const areaTextureImage = new Image(); | ||
|  | 		areaTextureImage.src = this.getAreaTexture(); | ||
|  | 		areaTextureImage.onload = function () { | ||
|  | 
 | ||
|  | 			// assigning data to HTMLImageElement.src is asynchronous (see #15162)
 | ||
|  | 			scope.areaTexture.needsUpdate = true; | ||
|  | 
 | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		this.areaTexture = new Texture(); | ||
|  | 		this.areaTexture.name = 'SMAAPass.area'; | ||
|  | 		this.areaTexture.image = areaTextureImage; | ||
|  | 		this.areaTexture.minFilter = LinearFilter; | ||
|  | 		this.areaTexture.generateMipmaps = false; | ||
|  | 		this.areaTexture.flipY = false; | ||
|  | 
 | ||
|  | 		const searchTextureImage = new Image(); | ||
|  | 		searchTextureImage.src = this.getSearchTexture(); | ||
|  | 		searchTextureImage.onload = function () { | ||
|  | 
 | ||
|  | 			// assigning data to HTMLImageElement.src is asynchronous (see #15162)
 | ||
|  | 			scope.searchTexture.needsUpdate = true; | ||
|  | 
 | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		this.searchTexture = new Texture(); | ||
|  | 		this.searchTexture.name = 'SMAAPass.search'; | ||
|  | 		this.searchTexture.image = searchTextureImage; | ||
|  | 		this.searchTexture.magFilter = NearestFilter; | ||
|  | 		this.searchTexture.minFilter = NearestFilter; | ||
|  | 		this.searchTexture.generateMipmaps = false; | ||
|  | 		this.searchTexture.flipY = false; | ||
|  | 
 | ||
|  | 		// materials - pass 1
 | ||
|  | 
 | ||
|  | 		this.uniformsEdges = UniformsUtils.clone( SMAAEdgesShader.uniforms ); | ||
|  | 
 | ||
|  | 		this.uniformsEdges[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
|  | 
 | ||
|  | 		this.materialEdges = new ShaderMaterial( { | ||
|  | 			defines: Object.assign( {}, SMAAEdgesShader.defines ), | ||
|  | 			uniforms: this.uniformsEdges, | ||
|  | 			vertexShader: SMAAEdgesShader.vertexShader, | ||
|  | 			fragmentShader: SMAAEdgesShader.fragmentShader | ||
|  | 		} ); | ||
|  | 
 | ||
|  | 		// materials - pass 2
 | ||
|  | 
 | ||
|  | 		this.uniformsWeights = UniformsUtils.clone( SMAAWeightsShader.uniforms ); | ||
|  | 
 | ||
|  | 		this.uniformsWeights[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
|  | 		this.uniformsWeights[ 'tDiffuse' ].value = this.edgesRT.texture; | ||
|  | 		this.uniformsWeights[ 'tArea' ].value = this.areaTexture; | ||
|  | 		this.uniformsWeights[ 'tSearch' ].value = this.searchTexture; | ||
|  | 
 | ||
|  | 		this.materialWeights = new ShaderMaterial( { | ||
|  | 			defines: Object.assign( {}, SMAAWeightsShader.defines ), | ||
|  | 			uniforms: this.uniformsWeights, | ||
|  | 			vertexShader: SMAAWeightsShader.vertexShader, | ||
|  | 			fragmentShader: SMAAWeightsShader.fragmentShader | ||
|  | 		} ); | ||
|  | 
 | ||
|  | 		// materials - pass 3
 | ||
|  | 
 | ||
|  | 		this.uniformsBlend = UniformsUtils.clone( SMAABlendShader.uniforms ); | ||
|  | 
 | ||
|  | 		this.uniformsBlend[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
|  | 		this.uniformsBlend[ 'tDiffuse' ].value = this.weightsRT.texture; | ||
|  | 
 | ||
|  | 		this.materialBlend = new ShaderMaterial( { | ||
|  | 			uniforms: this.uniformsBlend, | ||
|  | 			vertexShader: SMAABlendShader.vertexShader, | ||
|  | 			fragmentShader: SMAABlendShader.fragmentShader | ||
|  | 		} ); | ||
|  | 
 | ||
|  | 		this.fsQuad = new FullScreenQuad( null ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) { | ||
|  | 
 | ||
|  | 		// pass 1
 | ||
|  | 
 | ||
|  | 		this.uniformsEdges[ 'tDiffuse' ].value = readBuffer.texture; | ||
|  | 
 | ||
|  | 		this.fsQuad.material = this.materialEdges; | ||
|  | 
 | ||
|  | 		renderer.setRenderTarget( this.edgesRT ); | ||
|  | 		if ( this.clear ) renderer.clear(); | ||
|  | 		this.fsQuad.render( renderer ); | ||
|  | 
 | ||
|  | 		// pass 2
 | ||
|  | 
 | ||
|  | 		this.fsQuad.material = this.materialWeights; | ||
|  | 
 | ||
|  | 		renderer.setRenderTarget( this.weightsRT ); | ||
|  | 		if ( this.clear ) renderer.clear(); | ||
|  | 		this.fsQuad.render( renderer ); | ||
|  | 
 | ||
|  | 		// pass 3
 | ||
|  | 
 | ||
|  | 		this.uniformsBlend[ 'tColor' ].value = readBuffer.texture; | ||
|  | 
 | ||
|  | 		this.fsQuad.material = this.materialBlend; | ||
|  | 
 | ||
|  | 		if ( this.renderToScreen ) { | ||
|  | 
 | ||
|  | 			renderer.setRenderTarget( null ); | ||
|  | 			this.fsQuad.render( renderer ); | ||
|  | 
 | ||
|  | 		} else { | ||
|  | 
 | ||
|  | 			renderer.setRenderTarget( writeBuffer ); | ||
|  | 			if ( this.clear ) renderer.clear(); | ||
|  | 			this.fsQuad.render( renderer ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	setSize( width, height ) { | ||
|  | 
 | ||
|  | 		this.edgesRT.setSize( width, height ); | ||
|  | 		this.weightsRT.setSize( width, height ); | ||
|  | 
 | ||
|  | 		this.materialEdges.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
|  | 		this.materialWeights.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
|  | 		this.materialBlend.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getAreaTexture() { | ||
|  | 
 | ||
|  | 		return 'data:image/png;base64,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
 | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	getSearchTexture() { | ||
|  | 
 | ||
|  | 		return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII='; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	dispose() { | ||
|  | 
 | ||
|  | 		this.edgesRT.dispose(); | ||
|  | 		this.weightsRT.dispose(); | ||
|  | 
 | ||
|  | 		this.areaTexture.dispose(); | ||
|  | 		this.searchTexture.dispose(); | ||
|  | 
 | ||
|  | 		this.materialEdges.dispose(); | ||
|  | 		this.materialWeights.dispose(); | ||
|  | 		this.materialBlend.dispose(); | ||
|  | 
 | ||
|  | 		this.fsQuad.dispose(); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | export { SMAAPass }; |