three
Version:
JavaScript 3D library
206 lines (141 loc) • 4.57 kB
JavaScript
import Node from './Node.js';
import { NodeShaderStage } from './constants.js';
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
/**
* Class for representing shader varyings as nodes. Varyings are create from
* existing nodes like the following:
*
* ```js
* const positionLocal = positionGeometry.toVarying( 'vPositionLocal' );
* ```
*
* @augments Node
*/
class VaryingNode extends Node {
static get type() {
return 'VaryingNode';
}
/**
* Constructs a new varying node.
*
* @param {Node} node - The node for which a varying should be created.
* @param {?string} name - The name of the varying in the shader.
*/
constructor( node, name = null ) {
super();
/**
* The node for which a varying should be created.
*
* @type {Node}
*/
this.node = node;
/**
* The name of the varying in the shader. If no name is defined,
* the node system auto-generates one.
*
* @type {?string}
* @default null
*/
this.name = name;
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isVaryingNode = true;
}
/**
* The method is overwritten so it always returns `true`.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {boolean} Whether this node is global or not.
*/
isGlobal( /*builder*/ ) {
return true;
}
getHash( builder ) {
return this.name || super.getHash( builder );
}
getNodeType( builder ) {
// VaryingNode is auto type
return this.node.getNodeType( builder );
}
/**
* This method performs the setup of a varying node with the current node builder.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {NodeVarying} The node varying from the node builder.
*/
setupVarying( builder ) {
const properties = builder.getNodeProperties( this );
let varying = properties.varying;
if ( varying === undefined ) {
const name = this.name;
const type = this.getNodeType( builder );
properties.varying = varying = builder.getVaryingFromNode( this, name, type );
properties.node = this.node;
}
// this property can be used to check if the varying can be optimized for a variable
varying.needsInterpolation || ( varying.needsInterpolation = ( builder.shaderStage === 'fragment' ) );
return varying;
}
setup( builder ) {
this.setupVarying( builder );
}
analyze( builder ) {
this.setupVarying( builder );
return this.node.analyze( builder );
}
generate( builder ) {
const properties = builder.getNodeProperties( this );
const varying = this.setupVarying( builder );
const needsReassign = builder.shaderStage === 'fragment' && properties.reassignPosition === true && builder.context.needsPositionReassign;
if ( properties.propertyName === undefined || needsReassign ) {
const type = this.getNodeType( builder );
const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX );
// force node run in vertex stage
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName );
properties.propertyName = propertyName;
if ( needsReassign ) {
// once reassign varying in fragment stage
properties.reassignPosition = false;
} else if ( properties.reassignPosition === undefined && builder.context.isPositionNodeInput ) {
properties.reassignPosition = true;
}
}
return builder.getPropertyName( varying );
}
}
export default VaryingNode;
/**
* TSL function for creating a varying node.
*
* @tsl
* @function
* @param {Node} node - The node for which a varying should be created.
* @param {?string} name - The name of the varying in the shader.
* @returns {VaryingNode}
*/
export const varying = /*@__PURE__*/ nodeProxy( VaryingNode ).setParameterLength( 1, 2 );
/**
* Computes a node in the vertex stage.
*
* @tsl
* @function
* @param {Node} node - The node which should be executed in the vertex stage.
* @returns {VaryingNode}
*/
export const vertexStage = ( node ) => varying( node );
addMethodChaining( 'toVarying', varying );
addMethodChaining( 'toVertexStage', vertexStage );
// Deprecated
addMethodChaining( 'varying', ( ...params ) => { // @deprecated, r173
console.warn( 'THREE.TSL: .varying() has been renamed to .toVarying().' );
return varying( ...params );
} );
addMethodChaining( 'vertexStage', ( ...params ) => { // @deprecated, r173
console.warn( 'THREE.TSL: .vertexStage() has been renamed to .toVertexStage().' );
return varying( ...params );
} );