diff --git a/src/materials/nodes/MeshMatcapNodeMaterial.js b/src/materials/nodes/MeshMatcapNodeMaterial.js index f355c0b17d0ce8..258f20417a5c6a 100644 --- a/src/materials/nodes/MeshMatcapNodeMaterial.js +++ b/src/materials/nodes/MeshMatcapNodeMaterial.js @@ -3,7 +3,7 @@ import { materialReference } from '../../nodes/accessors/MaterialReferenceNode.j import { diffuseColor } from '../../nodes/core/PropertyNode.js'; import { vec3 } from '../../nodes/tsl/TSLBase.js'; import { mix } from '../../nodes/math/MathNode.js'; -import { matcapUV } from '../../nodes/utils/MatcapUVNode.js'; +import { matcapUV } from '../../nodes/utils/MatcapUV.js'; import { MeshMatcapMaterial } from '../MeshMatcapMaterial.js'; diff --git a/src/nodes/Nodes.js b/src/nodes/Nodes.js index 303b3a045390a4..94b4ad874b833d 100644 --- a/src/nodes/Nodes.js +++ b/src/nodes/Nodes.js @@ -41,11 +41,9 @@ export { NodeUtils }; // utils export { default as ArrayElementNode } from './utils/ArrayElementNode.js'; export { default as ConvertNode } from './utils/ConvertNode.js'; -export { default as EquirectUVNode } from './utils/EquirectUVNode.js'; export { default as FunctionOverloadingNode } from './utils/FunctionOverloadingNode.js'; export { default as JoinNode } from './utils/JoinNode.js'; export { default as LoopNode } from './utils/LoopNode.js'; -export { default as MatcapUVNode } from './utils/MatcapUVNode.js'; export { default as MaxMipLevelNode } from './utils/MaxMipLevelNode.js'; export { default as RemapNode } from './utils/RemapNode.js'; export { default as RotateNode } from './utils/RotateNode.js'; @@ -53,7 +51,6 @@ export { default as SetNode } from './utils/SetNode.js'; export { default as SplitNode } from './utils/SplitNode.js'; export { default as SpriteSheetUVNode } from './utils/SpriteSheetUVNode.js'; export { default as StorageArrayElementNode } from './utils/StorageArrayElementNode.js'; -export { default as TriplanarTexturesNode } from './utils/TriplanarTexturesNode.js'; export { default as ReflectorNode } from './utils/ReflectorNode.js'; export { default as RTTNode } from './utils/RTTNode.js'; export { default as MemberNode } from './utils/MemberNode.js'; diff --git a/src/nodes/TSL.js b/src/nodes/TSL.js index 70f798b9b6caf4..531cb18a2ca13a 100644 --- a/src/nodes/TSL.js +++ b/src/nodes/TSL.js @@ -24,10 +24,10 @@ export * from './math/MathUtils.js'; export * from './math/TriNoise3D.js'; // utils -export * from './utils/EquirectUVNode.js'; +export * from './utils/EquirectUV.js'; export * from './utils/FunctionOverloadingNode.js'; export * from './utils/LoopNode.js'; -export * from './utils/MatcapUVNode.js'; +export * from './utils/MatcapUV.js'; export * from './utils/MaxMipLevelNode.js'; export * from './utils/Oscillators.js'; export * from './utils/Packing.js'; @@ -38,7 +38,7 @@ export * from './utils/ViewportUtils.js'; export * from './utils/RotateNode.js'; export * from './utils/SpriteSheetUVNode.js'; export * from './utils/Timer.js'; -export * from './utils/TriplanarTexturesNode.js'; +export * from './utils/TriplanarTextures.js'; export * from './utils/ReflectorNode.js'; export * from './utils/RTTNode.js'; export * from './utils/PostProcessingUtils.js'; diff --git a/src/nodes/utils/EquirectUV.js b/src/nodes/utils/EquirectUV.js new file mode 100644 index 00000000000000..5ce3fe0195e0c1 --- /dev/null +++ b/src/nodes/utils/EquirectUV.js @@ -0,0 +1,27 @@ +import { positionWorldDirection } from '../accessors/Position.js'; +import { Fn, vec2 } from '../tsl/TSLBase.js'; + +/** + * TSL function for creating an equirect uv node. + * + * Can be used to compute texture coordinates for projecting an + * equirectangular texture onto a mesh for using it as the scene's + * background. + * + * ```js + * scene.backgroundNode = texture( equirectTexture, equirectUV() ); + * ``` + * + * @tsl + * @function + * @param {?Node} [dirNode=positionWorldDirection] - A direction vector for sampling which is by default `positionWorldDirection`. + * @returns {Node} + */ +export const equirectUV = /*@__PURE__*/ Fn( ( [ dir = positionWorldDirection ] ) => { + + const u = dir.z.atan( dir.x ).mul( 1 / ( Math.PI * 2 ) ).add( 0.5 ); + const v = dir.y.clamp( - 1.0, 1.0 ).asin().mul( 1 / Math.PI ).add( 0.5 ); + + return vec2( u, v ); + +} ); diff --git a/src/nodes/utils/EquirectUVNode.js b/src/nodes/utils/EquirectUVNode.js deleted file mode 100644 index 85670c08f567f7..00000000000000 --- a/src/nodes/utils/EquirectUVNode.js +++ /dev/null @@ -1,65 +0,0 @@ -import TempNode from '../core/TempNode.js'; -import { positionWorldDirection } from '../accessors/Position.js'; -import { nodeProxy, vec2 } from '../tsl/TSLBase.js'; - -/** - * Can be used to compute texture coordinates for projecting an - * equirectangular texture onto a mesh for using it as the scene's - * background. - * - * ```js - * scene.backgroundNode = texture( equirectTexture, equirectUV() ); - * ``` - * - * @augments TempNode - */ -class EquirectUVNode extends TempNode { - - static get type() { - - return 'EquirectUVNode'; - - } - - /** - * Constructs a new equirect uv node. - * - * @param {Node} [dirNode=positionWorldDirection] - A direction vector for sampling which is by default `positionWorldDirection`. - */ - constructor( dirNode = positionWorldDirection ) { - - super( 'vec2' ); - - /** - * A direction vector for sampling why is by default `positionWorldDirection`. - * - * @type {Node} - */ - this.dirNode = dirNode; - - } - - setup() { - - const dir = this.dirNode; - - const u = dir.z.atan( dir.x ).mul( 1 / ( Math.PI * 2 ) ).add( 0.5 ); - const v = dir.y.clamp( - 1.0, 1.0 ).asin().mul( 1 / Math.PI ).add( 0.5 ); - - return vec2( u, v ); - - } - -} - -export default EquirectUVNode; - -/** - * TSL function for creating an equirect uv node. - * - * @tsl - * @function - * @param {?Node} [dirNode=positionWorldDirection] - A direction vector for sampling which is by default `positionWorldDirection`. - * @returns {EquirectUVNode} - */ -export const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ).setParameterLength( 0, 1 ); diff --git a/src/nodes/utils/MatcapUV.js b/src/nodes/utils/MatcapUV.js new file mode 100644 index 00000000000000..45b4b5f5b9b2fb --- /dev/null +++ b/src/nodes/utils/MatcapUV.js @@ -0,0 +1,22 @@ +import { normalView } from '../accessors/Normal.js'; +import { positionViewDirection } from '../accessors/Position.js'; +import { Fn, vec2, vec3 } from '../tsl/TSLBase.js'; + +/** + * TSL function for creating a matcap uv node. + * + * Can be used to compute texture coordinates for projecting a + * matcap onto a mesh. Used by {@link MeshMatcapNodeMaterial}. + * + * @tsl + * @function + * @returns {Node} The matcap UV coordinates. + */ +export const matcapUV = /*@__PURE__*/ Fn( () => { + + const x = vec3( positionViewDirection.z, 0, positionViewDirection.x.negate() ).normalize(); + const y = positionViewDirection.cross( x ); + + return vec2( x.dot( normalView ), y.dot( normalView ) ).mul( 0.495 ).add( 0.5 ); // 0.495 to remove artifacts caused by undersized matcap disks + +} ).once( [ 'NORMAL', 'VERTEX' ] )().toVar( 'matcapUV' ); diff --git a/src/nodes/utils/MatcapUVNode.js b/src/nodes/utils/MatcapUVNode.js deleted file mode 100644 index 8f51dc992c7c59..00000000000000 --- a/src/nodes/utils/MatcapUVNode.js +++ /dev/null @@ -1,49 +0,0 @@ -import TempNode from '../core/TempNode.js'; -import { normalView } from '../accessors/Normal.js'; -import { positionViewDirection } from '../accessors/Position.js'; -import { nodeImmutable, vec2, vec3 } from '../tsl/TSLBase.js'; - -/** - * Can be used to compute texture coordinates for projecting a - * matcap onto a mesh. Used by {@link MeshMatcapNodeMaterial}. - * - * @augments TempNode - */ -class MatcapUVNode extends TempNode { - - static get type() { - - return 'MatcapUVNode'; - - } - - /** - * Constructs a new matcap uv node. - */ - constructor() { - - super( 'vec2' ); - - } - - setup() { - - const x = vec3( positionViewDirection.z, 0, positionViewDirection.x.negate() ).normalize(); - const y = positionViewDirection.cross( x ); - - return vec2( x.dot( normalView ), y.dot( normalView ) ).mul( 0.495 ).add( 0.5 ); // 0.495 to remove artifacts caused by undersized matcap disks - - } - -} - -export default MatcapUVNode; - -/** - * TSL function for creating a matcap uv node. - * - * @tsl - * @function - * @returns {MatcapUVNode} - */ -export const matcapUV = /*@__PURE__*/ nodeImmutable( MatcapUVNode ); diff --git a/src/nodes/utils/TriplanarTextures.js b/src/nodes/utils/TriplanarTextures.js new file mode 100644 index 00000000000000..4808a458549344 --- /dev/null +++ b/src/nodes/utils/TriplanarTextures.js @@ -0,0 +1,65 @@ +import { add } from '../math/OperatorNode.js'; +import { normalLocal } from '../accessors/Normal.js'; +import { positionLocal } from '../accessors/Position.js'; +import { texture } from '../accessors/TextureNode.js'; +import { float, vec3, Fn } from '../tsl/TSLBase.js'; + +/** + * TSL function for creating a triplanar textures node. + * + * Can be used for triplanar texture mapping. + * + * ```js + * material.colorNode = triplanarTexture( texture( diffuseMap ) ); + * ``` + * + * @tsl + * @function + * @param {Node} textureXNode - First texture node. + * @param {?Node} [textureYNode=null] - Second texture node. When not set, the shader will sample from `textureXNode` instead. + * @param {?Node} [textureZNode=null] - Third texture node. When not set, the shader will sample from `textureXNode` instead. + * @param {?Node} [scaleNode=float(1)] - The scale node. + * @param {?Node} [positionNode=positionLocal] - Vertex positions in local space. + * @param {?Node} [normalNode=normalLocal] - Normals in local space. + * @returns {Node} + */ +export const triplanarTextures = /*@__PURE__*/ Fn( ( [ textureXNode, textureYNode = null, textureZNode = null, scaleNode = float( 1 ), positionNode = positionLocal, normalNode = normalLocal ] ) => { + + // Reference: https://github.com/keijiro/StandardTriplanar + + // Blending factor of triplanar mapping + let bf = normalNode.abs().normalize(); + bf = bf.div( bf.dot( vec3( 1.0 ) ) ); + + // Triplanar mapping + const tx = positionNode.yz.mul( scaleNode ); + const ty = positionNode.zx.mul( scaleNode ); + const tz = positionNode.xy.mul( scaleNode ); + + // Base color + const textureX = textureXNode.value; + const textureY = textureYNode !== null ? textureYNode.value : textureX; + const textureZ = textureZNode !== null ? textureZNode.value : textureX; + + const cx = texture( textureX, tx ).mul( bf.x ); + const cy = texture( textureY, ty ).mul( bf.y ); + const cz = texture( textureZ, tz ).mul( bf.z ); + + return add( cx, cy, cz ); + +} ); + +/** + * TSL function for creating a triplanar textures node. + * + * @tsl + * @function + * @param {Node} textureXNode - First texture node. + * @param {?Node} [textureYNode=null] - Second texture node. When not set, the shader will sample from `textureXNode` instead. + * @param {?Node} [textureZNode=null] - Third texture node. When not set, the shader will sample from `textureXNode` instead. + * @param {?Node} [scaleNode=float(1)] - The scale node. + * @param {?Node} [positionNode=positionLocal] - Vertex positions in local space. + * @param {?Node} [normalNode=normalLocal] - Normals in local space. + * @returns {Node} + */ +export const triplanarTexture = ( ...params ) => triplanarTextures( ...params ); diff --git a/src/nodes/utils/TriplanarTexturesNode.js b/src/nodes/utils/TriplanarTexturesNode.js deleted file mode 100644 index 9e7a866168328a..00000000000000 --- a/src/nodes/utils/TriplanarTexturesNode.js +++ /dev/null @@ -1,148 +0,0 @@ -import Node from '../core/Node.js'; -import { add } from '../math/OperatorNode.js'; -import { normalLocal } from '../accessors/Normal.js'; -import { positionLocal } from '../accessors/Position.js'; -import { texture } from '../accessors/TextureNode.js'; -import { nodeProxy, float, vec3 } from '../tsl/TSLBase.js'; - -/** - * Can be used for triplanar texture mapping. - * - * ```js - * material.colorNode = triplanarTexture( texture( diffuseMap ) ); - * ``` - * - * @augments Node - */ -class TriplanarTexturesNode extends Node { - - static get type() { - - return 'TriplanarTexturesNode'; - - } - - /** - * Constructs a new triplanar textures node. - * - * @param {Node} textureXNode - First texture node. - * @param {?Node} [textureYNode=null] - Second texture node. When not set, the shader will sample from `textureXNode` instead. - * @param {?Node} [textureZNode=null] - Third texture node. When not set, the shader will sample from `textureXNode` instead. - * @param {?Node} [scaleNode=float(1)] - The scale node. - * @param {?Node} [positionNode=positionLocal] - Vertex positions in local space. - * @param {?Node} [normalNode=normalLocal] - Normals in local space. - */ - constructor( textureXNode, textureYNode = null, textureZNode = null, scaleNode = float( 1 ), positionNode = positionLocal, normalNode = normalLocal ) { - - super( 'vec4' ); - - /** - * First texture node. - * - * @type {Node} - */ - this.textureXNode = textureXNode; - - /** - * Second texture node. When not set, the shader will sample from `textureXNode` instead. - * - * @type {?Node} - * @default null - */ - this.textureYNode = textureYNode; - - /** - * Third texture node. When not set, the shader will sample from `textureXNode` instead. - * - * @type {?Node} - * @default null - */ - this.textureZNode = textureZNode; - - /** - * The scale node. - * - * @type {Node} - * @default float(1) - */ - this.scaleNode = scaleNode; - - /** - * Vertex positions in local space. - * - * @type {Node} - * @default positionLocal - */ - this.positionNode = positionNode; - - /** - * Normals in local space. - * - * @type {Node} - * @default normalLocal - */ - this.normalNode = normalNode; - - } - - setup() { - - const { textureXNode, textureYNode, textureZNode, scaleNode, positionNode, normalNode } = this; - - // Ref: https://github.com/keijiro/StandardTriplanar - - // Blending factor of triplanar mapping - let bf = normalNode.abs().normalize(); - bf = bf.div( bf.dot( vec3( 1.0 ) ) ); - - // Triplanar mapping - const tx = positionNode.yz.mul( scaleNode ); - const ty = positionNode.zx.mul( scaleNode ); - const tz = positionNode.xy.mul( scaleNode ); - - // Base color - const textureX = textureXNode.value; - const textureY = textureYNode !== null ? textureYNode.value : textureX; - const textureZ = textureZNode !== null ? textureZNode.value : textureX; - - const cx = texture( textureX, tx ).mul( bf.x ); - const cy = texture( textureY, ty ).mul( bf.y ); - const cz = texture( textureZ, tz ).mul( bf.z ); - - return add( cx, cy, cz ); - - } - -} - -export default TriplanarTexturesNode; - -/** - * TSL function for creating a triplanar textures node. - * - * @tsl - * @function - * @param {Node} textureXNode - First texture node. - * @param {?Node} [textureYNode=null] - Second texture node. When not set, the shader will sample from `textureXNode` instead. - * @param {?Node} [textureZNode=null] - Third texture node. When not set, the shader will sample from `textureXNode` instead. - * @param {?Node} [scaleNode=float(1)] - The scale node. - * @param {?Node} [positionNode=positionLocal] - Vertex positions in local space. - * @param {?Node} [normalNode=normalLocal] - Normals in local space. - * @returns {TriplanarTexturesNode} - */ -export const triplanarTextures = /*@__PURE__*/ nodeProxy( TriplanarTexturesNode ).setParameterLength( 1, 6 ); - -/** - * TSL function for creating a triplanar textures node. - * - * @tsl - * @function - * @param {Node} textureXNode - First texture node. - * @param {?Node} [textureYNode=null] - Second texture node. When not set, the shader will sample from `textureXNode` instead. - * @param {?Node} [textureZNode=null] - Third texture node. When not set, the shader will sample from `textureXNode` instead. - * @param {?Node} [scaleNode=float(1)] - The scale node. - * @param {?Node} [positionNode=positionLocal] - Vertex positions in local space. - * @param {?Node} [normalNode=normalLocal] - Normals in local space. - * @returns {TriplanarTexturesNode} - */ -export const triplanarTexture = ( ...params ) => triplanarTextures( ...params ); diff --git a/src/renderers/common/CubeRenderTarget.js b/src/renderers/common/CubeRenderTarget.js index 16620c4d1c63d3..e8931de831400b 100644 --- a/src/renderers/common/CubeRenderTarget.js +++ b/src/renderers/common/CubeRenderTarget.js @@ -1,4 +1,4 @@ -import { equirectUV } from '../../nodes/utils/EquirectUVNode.js'; +import { equirectUV } from '../../nodes/utils/EquirectUV.js'; import { texture as TSL_Texture } from '../../nodes/accessors/TextureNode.js'; import { positionWorldDirection } from '../../nodes/accessors/Position.js'; import NodeMaterial from '../../materials/nodes/NodeMaterial.js'; diff --git a/src/renderers/common/extras/PMREMGenerator.js b/src/renderers/common/extras/PMREMGenerator.js index ac7448e904c8f3..f3c0bcbca49a37 100644 --- a/src/renderers/common/extras/PMREMGenerator.js +++ b/src/renderers/common/extras/PMREMGenerator.js @@ -1,6 +1,6 @@ import NodeMaterial from '../../../materials/nodes/NodeMaterial.js'; import { getDirection, blur } from '../../../nodes/pmrem/PMREMUtils.js'; -import { equirectUV } from '../../../nodes/utils/EquirectUVNode.js'; +import { equirectUV } from '../../../nodes/utils/EquirectUV.js'; import { uniform } from '../../../nodes/core/UniformNode.js'; import { uniformArray } from '../../../nodes/accessors/UniformArrayNode.js'; import { texture } from '../../../nodes/accessors/TextureNode.js';