three
Version:
JavaScript 3D library
178 lines (123 loc) • 3.84 kB
JavaScript
import InputNode from './InputNode.js';
import { objectGroup } from './UniformGroupNode.js';
import { nodeObject, getConstNodeType } from '../tsl/TSLCore.js';
/**
* Class for representing a uniform.
*
* @augments InputNode
*/
class UniformNode extends InputNode {
static get type() {
return 'UniformNode';
}
/**
* Constructs a new uniform node.
*
* @param {any} value - The value of this node. Usually a JS primitive or three.js object (vector, matrix, color, texture).
* @param {?string} nodeType - The node type. If no explicit type is defined, the node tries to derive the type from its value.
*/
constructor( value, nodeType = null ) {
super( value, nodeType );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isUniformNode = true;
/**
* The name or label of the uniform.
*
* @type {string}
* @default ''
*/
this.name = '';
/**
* The uniform group of this uniform. By default, uniforms are
* managed per object but they might belong to a shared group
* which is updated per frame or render call.
*
* @type {UniformGroupNode}
*/
this.groupNode = objectGroup;
}
/**
* Sets the {@link UniformNode#name} property.
*
* @param {string} name - The name of the uniform.
* @return {UniformNode} A reference to this node.
*/
label( name ) {
this.name = name;
return this;
}
/**
* Sets the {@link UniformNode#groupNode} property.
*
* @param {UniformGroupNode} group - The uniform group.
* @return {UniformNode} A reference to this node.
*/
setGroup( group ) {
this.groupNode = group;
return this;
}
/**
* Returns the {@link UniformNode#groupNode}.
*
* @return {UniformGroupNode} The uniform group.
*/
getGroup() {
return this.groupNode;
}
/**
* By default, this method returns the result of {@link Node#getHash} but derived
* classes might overwrite this method with a different implementation.
*
* @param {NodeBuilder} builder - The current node builder.
* @return {string} The uniform hash.
*/
getUniformHash( builder ) {
return this.getHash( builder );
}
onUpdate( callback, updateType ) {
const self = this.getSelf();
callback = callback.bind( self );
return super.onUpdate( ( frame ) => {
const value = callback( frame, self );
if ( value !== undefined ) {
this.value = value;
}
}, updateType );
}
generate( builder, output ) {
const type = this.getNodeType( builder );
const hash = this.getUniformHash( builder );
let sharedNode = builder.getNodeFromHash( hash );
if ( sharedNode === undefined ) {
builder.setHashNode( this, hash );
sharedNode = this;
}
const sharedNodeType = sharedNode.getInputType( builder );
const nodeUniform = builder.getUniformFromNode( sharedNode, sharedNodeType, builder.shaderStage, this.name || builder.context.label );
const propertyName = builder.getPropertyName( nodeUniform );
if ( builder.context.label !== undefined ) delete builder.context.label;
return builder.format( propertyName, type, output );
}
}
export default UniformNode;
/**
* TSL function for creating a uniform node.
*
* @tsl
* @function
* @param {any} arg1 - The value of this node. Usually a JS primitive or three.js object (vector, matrix, color, texture).
* @param {string} [arg2] - The node type. If no explicit type is defined, the node tries to derive the type from its value.
* @returns {UniformNode}
*/
export const uniform = ( arg1, arg2 ) => {
const nodeType = getConstNodeType( arg2 || arg1 );
// @TODO: get ConstNode from .traverse() in the future
const value = ( arg1 && arg1.isNode === true ) ? ( arg1.node && arg1.node.value ) || arg1.value : arg1;
return nodeObject( new UniformNode( value, nodeType ) );
};