194 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			194 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | import TempNode from '../core/TempNode.js'; | ||
|  | import { addNodeClass } from '../core/Node.js'; | ||
|  | import { texture } from '../accessors/TextureNode.js'; | ||
|  | import { textureCubeUV } from './PMREMUtils.js'; | ||
|  | import { uniform } from '../core/UniformNode.js'; | ||
|  | import { NodeUpdateType } from '../core/constants.js'; | ||
|  | import { nodeProxy, vec3 } from '../shadernode/ShaderNode.js'; | ||
|  | import { WebGLCoordinateSystem } from 'three'; | ||
|  | 
 | ||
|  | let _generator = null; | ||
|  | 
 | ||
|  | const _cache = new WeakMap(); | ||
|  | 
 | ||
|  | function _generateCubeUVSize( imageHeight ) { | ||
|  | 
 | ||
|  | 	const maxMip = Math.log2( imageHeight ) - 2; | ||
|  | 
 | ||
|  | 	const texelHeight = 1.0 / imageHeight; | ||
|  | 
 | ||
|  | 	const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); | ||
|  | 
 | ||
|  | 	return { texelWidth, texelHeight, maxMip }; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | function _getPMREMFromTexture( texture ) { | ||
|  | 
 | ||
|  | 	let cacheTexture = _cache.get( texture ); | ||
|  | 
 | ||
|  | 	const pmremVersion = cacheTexture !== undefined ? cacheTexture.pmremVersion : - 1; | ||
|  | 
 | ||
|  | 	if ( pmremVersion !== texture.pmremVersion ) { | ||
|  | 
 | ||
|  | 		if ( texture.isCubeTexture ) { | ||
|  | 
 | ||
|  | 			if ( texture.source.data.some( ( texture ) => texture === undefined ) ) { | ||
|  | 
 | ||
|  | 				throw new Error( 'PMREMNode: Undefined texture in CubeTexture. Use onLoad callback or async loader' ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			cacheTexture = _generator.fromCubemap( texture, cacheTexture ); | ||
|  | 
 | ||
|  | 		} else { | ||
|  | 
 | ||
|  | 			if ( texture.image === undefined ) { | ||
|  | 
 | ||
|  | 				throw new Error( 'PMREMNode: Undefined image in Texture. Use onLoad callback or async loader' ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			cacheTexture = _generator.fromEquirectangular( texture, cacheTexture ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		cacheTexture.pmremVersion = texture.pmremVersion; | ||
|  | 
 | ||
|  | 		_cache.set( texture, cacheTexture ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return cacheTexture.texture; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | class PMREMNode extends TempNode { | ||
|  | 
 | ||
|  | 	constructor( value, uvNode = null, levelNode = null ) { | ||
|  | 
 | ||
|  | 		super( 'vec3' ); | ||
|  | 
 | ||
|  | 		this._value = value; | ||
|  | 		this._pmrem = null; | ||
|  | 
 | ||
|  | 		this.uvNode = uvNode; | ||
|  | 		this.levelNode = levelNode; | ||
|  | 
 | ||
|  | 		this._generator = null; | ||
|  | 		this._texture = texture( null ); | ||
|  | 		this._width = uniform( 0 ); | ||
|  | 		this._height = uniform( 0 ); | ||
|  | 		this._maxMip = uniform( 0 ); | ||
|  | 
 | ||
|  | 		this.updateBeforeType = NodeUpdateType.RENDER; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	set value( value ) { | ||
|  | 
 | ||
|  | 		this._value = value; | ||
|  | 		this._pmrem = null; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	get value() { | ||
|  | 
 | ||
|  | 		return this._value; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	updateFromTexture( texture ) { | ||
|  | 
 | ||
|  | 		const cubeUVSize = _generateCubeUVSize( texture.image.height ); | ||
|  | 
 | ||
|  | 		this._texture.value = texture; | ||
|  | 		this._width.value = cubeUVSize.texelWidth; | ||
|  | 		this._height.value = cubeUVSize.texelHeight; | ||
|  | 		this._maxMip.value = cubeUVSize.maxMip; | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	updateBefore() { | ||
|  | 
 | ||
|  | 		let pmrem = this._pmrem; | ||
|  | 
 | ||
|  | 		const pmremVersion = pmrem ? pmrem.pmremVersion : - 1; | ||
|  | 		const texture = this._value; | ||
|  | 
 | ||
|  | 		if ( pmremVersion !== texture.pmremVersion ) { | ||
|  | 
 | ||
|  | 			if ( texture.isPMREMTexture === true ) { | ||
|  | 
 | ||
|  | 				pmrem = texture; | ||
|  | 
 | ||
|  | 			} else { | ||
|  | 
 | ||
|  | 				pmrem = _getPMREMFromTexture( texture ); | ||
|  | 
 | ||
|  | 			} | ||
|  | 
 | ||
|  | 			this._pmrem = pmrem; | ||
|  | 
 | ||
|  | 			this.updateFromTexture( pmrem ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	setup( builder ) { | ||
|  | 
 | ||
|  | 		if ( _generator === null ) { | ||
|  | 
 | ||
|  | 			_generator = builder.createPMREMGenerator(); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		//
 | ||
|  | 
 | ||
|  | 		this.updateBefore( builder ); | ||
|  | 
 | ||
|  | 		//
 | ||
|  | 
 | ||
|  | 		let uvNode = this.uvNode; | ||
|  | 
 | ||
|  | 		if ( uvNode === null && builder.context.getUV ) { | ||
|  | 
 | ||
|  | 			uvNode = builder.context.getUV( this ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		//
 | ||
|  | 
 | ||
|  | 		const texture = this.value; | ||
|  | 
 | ||
|  | 		if ( builder.renderer.coordinateSystem === WebGLCoordinateSystem && texture.isPMREMTexture !== true && texture.isRenderTargetTexture === true ) { | ||
|  | 
 | ||
|  | 			uvNode = vec3( uvNode.x.negate(), uvNode.yz ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		//
 | ||
|  | 
 | ||
|  | 		let levelNode = this.levelNode; | ||
|  | 
 | ||
|  | 		if ( levelNode === null && builder.context.getTextureLevel ) { | ||
|  | 
 | ||
|  | 			levelNode = builder.context.getTextureLevel( this ); | ||
|  | 
 | ||
|  | 		} | ||
|  | 
 | ||
|  | 		//
 | ||
|  | 
 | ||
|  | 		return textureCubeUV( this._texture, uvNode, levelNode, this._width, this._height, this._maxMip ); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | export const pmremTexture = nodeProxy( PMREMNode ); | ||
|  | 
 | ||
|  | addNodeClass( 'PMREMNode', PMREMNode ); | ||
|  | 
 | ||
|  | export default PMREMNode; |