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;
							 |