import { TempNode } from '../core/TempNode.js'; import { FunctionNode } from '../core/FunctionNode.js'; import { FloatNode } from '../inputs/FloatNode.js'; import { PositionNode } from '../accessors/PositionNode.js'; class CameraNode extends TempNode { constructor( scope, camera ) { super( 'v3' ); this.setScope( scope || CameraNode.POSITION ); this.setCamera( camera ); } setCamera( camera ) { this.camera = camera; this.updateFrame = camera !== undefined ? this.onUpdateFrame : undefined; } setScope( scope ) { switch ( this.scope ) { case CameraNode.DEPTH: delete this.near; delete this.far; break; } this.scope = scope; switch ( scope ) { case CameraNode.DEPTH: const camera = this.camera; this.near = new FloatNode( camera ? camera.near : 1 ); this.far = new FloatNode( camera ? camera.far : 1200 ); break; } } getType( /* builder */ ) { switch ( this.scope ) { case CameraNode.DEPTH: return 'f'; } return this.type; } getUnique( /* builder */ ) { switch ( this.scope ) { case CameraNode.DEPTH: case CameraNode.TO_VERTEX: return true; } return false; } getShared( /* builder */ ) { switch ( this.scope ) { case CameraNode.POSITION: return false; } return true; } generate( builder, output ) { let result; switch ( this.scope ) { case CameraNode.POSITION: result = 'cameraPosition'; break; case CameraNode.DEPTH: const depthColor = builder.include( CameraNode.Nodes.depthColor ); result = depthColor + '( ' + this.near.build( builder, 'f' ) + ', ' + this.far.build( builder, 'f' ) + ' )'; break; case CameraNode.TO_VERTEX: result = 'normalize( ' + new PositionNode( PositionNode.WORLD ).build( builder, 'v3' ) + ' - cameraPosition )'; break; } return builder.format( result, this.getType( builder ), output ); } onUpdateFrame( /* frame */ ) { switch ( this.scope ) { case CameraNode.DEPTH: const camera = this.camera; this.near.value = camera.near; this.far.value = camera.far; break; } } copy( source ) { super.copy( source ); this.setScope( source.scope ); if ( source.camera ) { this.setCamera( source.camera ); } switch ( source.scope ) { case CameraNode.DEPTH: this.near.number = source.near; this.far.number = source.far; break; } return this; } toJSON( meta ) { let data = this.getJSONNode( meta ); if ( ! data ) { data = this.createJSONNode( meta ); data.scope = this.scope; if ( this.camera ) data.camera = this.camera.uuid; switch ( this.scope ) { case CameraNode.DEPTH: data.near = this.near.value; data.far = this.far.value; break; } } return data; } } CameraNode.Nodes = ( function () { const depthColor = new FunctionNode( /* glsl */` float depthColor( float mNear, float mFar ) { #ifdef USE_LOGDEPTHBUF_EXT float depth = gl_FragDepthEXT / gl_FragCoord.w; #else float depth = gl_FragCoord.z / gl_FragCoord.w; #endif return 1.0 - smoothstep( mNear, mFar, depth ); }` ); return { depthColor: depthColor }; } )(); CameraNode.POSITION = 'position'; CameraNode.DEPTH = 'depth'; CameraNode.TO_VERTEX = 'toVertex'; CameraNode.prototype.nodeType = 'Camera'; export { CameraNode };