three
Version:
JavaScript 3D library
132 lines (95 loc) • 3.04 kB
JavaScript
import Node from '../core/Node.js';
import { nodeImmutable, float, Fn } from '../tsl/TSLBase.js';
import { warnOnce } from '../../utils.js';
import { BackSide, DoubleSide } from '../../constants.js';
/**
* This node can be used to evaluate whether a primitive is front or back facing.
*
* @augments Node
*/
class FrontFacingNode extends Node {
static get type() {
return 'FrontFacingNode';
}
/**
* Constructs a new front facing node.
*/
constructor() {
super( 'bool' );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isFrontFacingNode = true;
}
generate( builder ) {
if ( builder.shaderStage !== 'fragment' ) return 'true';
//
const { material } = builder;
if ( material.side === BackSide ) {
return 'false';
}
return builder.getFrontFacing();
}
}
export default FrontFacingNode;
/**
* TSL object that represents whether a primitive is front or back facing
*
* @tsl
* @type {FrontFacingNode<bool>}
*/
export const frontFacing = /*@__PURE__*/ nodeImmutable( FrontFacingNode );
/**
* TSL object that represents the front facing status as a number instead of a bool.
* `1` means front facing, `-1` means back facing.
*
* @tsl
* @type {Node<float>}
*/
export const faceDirection = /*@__PURE__*/ float( frontFacing ).mul( 2.0 ).sub( 1.0 );
/**
* Negates a vector if the rendering occurs on the back side of a face,
* based on the material's side configuration.
*
* - If the material's side is `BackSide`, the vector is inverted (negated).
* - If the material's side is `DoubleSide`, the vector is multiplied by `faceDirection`
* (negated only for back-facing fragments).
* - If the material's side is `FrontSide` (default), the vector remains unchanged.
*
* @tsl
* @function
* @param {Node<vec3>} vector - The vector to process.
* @returns {Node<vec3>} The processed vector.
*/
export const negateOnBackSide = /*@__PURE__*/ Fn( ( [ vector ], { material } ) => {
const side = material.side;
if ( side === BackSide ) {
vector = vector.mul( - 1.0 );
} else if ( side === DoubleSide ) {
vector = vector.mul( faceDirection );
}
return vector;
} );
/**
* Negates a vector if the rendering occurs on the back side of a face,
* based on the material's side configuration.
*
* - If the material's side is `BackSide`, the vector is inverted (negated).
* - If the material's side is `DoubleSide`, the vector is multiplied by `faceDirection`
* (negated only for back-facing fragments).
* - If the material's side is `FrontSide` (default), the vector remains unchanged.
*
* @tsl
* @function
* @deprecated since r185. Use {@link negateOnBackSide} instead.
* @param {Node<vec3>} vector - The vector to convert.
* @returns {Node<vec3>} The converted vector.
*/
export const directionToFaceDirection = ( vector ) => {
warnOnce( 'TSL: "directionToFaceDirection()" has been renamed to "negateOnBackSide()".' ); // @deprecated r185
return negateOnBackSide( vector );
};