first app vibe
This commit is contained in:
144
app/node_modules/three/src/nodes/Nodes.js
generated
vendored
Normal file
144
app/node_modules/three/src/nodes/Nodes.js
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
// constants
|
||||
export * from './core/constants.js';
|
||||
|
||||
// core
|
||||
export { default as ArrayNode } from './core/ArrayNode.js';
|
||||
export { default as AssignNode } from './core/AssignNode.js';
|
||||
export { default as AttributeNode } from './core/AttributeNode.js';
|
||||
export { default as BypassNode } from './core/BypassNode.js';
|
||||
export { default as CacheNode } from './core/CacheNode.js';
|
||||
export { default as ConstNode } from './core/ConstNode.js';
|
||||
export { default as ContextNode } from './core/ContextNode.js';
|
||||
export { default as IndexNode } from './core/IndexNode.js';
|
||||
export { default as LightingModel } from './core/LightingModel.js';
|
||||
export { default as Node } from './core/Node.js';
|
||||
export { default as VarNode } from './core/VarNode.js';
|
||||
export { default as NodeAttribute } from './core/NodeAttribute.js';
|
||||
export { default as NodeBuilder } from './core/NodeBuilder.js';
|
||||
export { default as NodeCache } from './core/NodeCache.js';
|
||||
export { default as NodeCode } from './core/NodeCode.js';
|
||||
export { default as NodeFrame } from './core/NodeFrame.js';
|
||||
export { default as NodeFunctionInput } from './core/NodeFunctionInput.js';
|
||||
export { default as NodeUniform } from './core/NodeUniform.js';
|
||||
export { default as NodeVar } from './core/NodeVar.js';
|
||||
export { default as NodeVarying } from './core/NodeVarying.js';
|
||||
export { default as ParameterNode } from './core/ParameterNode.js';
|
||||
export { default as PropertyNode } from './core/PropertyNode.js';
|
||||
export { default as StackNode } from './core/StackNode.js';
|
||||
export { default as TempNode } from './core/TempNode.js';
|
||||
export { default as UniformGroupNode } from './core/UniformGroupNode.js';
|
||||
export { default as UniformNode } from './core/UniformNode.js';
|
||||
export { default as VaryingNode } from './core/VaryingNode.js';
|
||||
export { default as StructNode } from './core/StructNode.js';
|
||||
export { default as StructTypeNode } from './core/StructTypeNode.js';
|
||||
export { default as OutputStructNode } from './core/OutputStructNode.js';
|
||||
export { default as MRTNode } from './core/MRTNode.js';
|
||||
export { default as SubBuildNode } from './core/SubBuildNode.js';
|
||||
|
||||
import * as NodeUtils from './core/NodeUtils.js';
|
||||
export { NodeUtils };
|
||||
|
||||
// utils
|
||||
export { default as ArrayElementNode } from './utils/ArrayElementNode.js';
|
||||
export { default as ConvertNode } from './utils/ConvertNode.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 MaxMipLevelNode } from './utils/MaxMipLevelNode.js';
|
||||
export { default as RemapNode } from './utils/RemapNode.js';
|
||||
export { default as RotateNode } from './utils/RotateNode.js';
|
||||
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 ReflectorNode } from './utils/ReflectorNode.js';
|
||||
export { default as RTTNode } from './utils/RTTNode.js';
|
||||
export { default as MemberNode } from './utils/MemberNode.js';
|
||||
export { default as DebugNode } from './utils/DebugNode.js';
|
||||
|
||||
// accessors
|
||||
export { default as UniformArrayNode } from './accessors/UniformArrayNode.js';
|
||||
export { default as BufferAttributeNode } from './accessors/BufferAttributeNode.js';
|
||||
export { default as BufferNode } from './accessors/BufferNode.js';
|
||||
export { default as VertexColorNode } from './accessors/VertexColorNode.js';
|
||||
export { default as CubeTextureNode } from './accessors/CubeTextureNode.js';
|
||||
export { default as InstanceNode } from './accessors/InstanceNode.js';
|
||||
export { default as InstancedMeshNode } from './accessors/InstancedMeshNode.js';
|
||||
export { default as BatchNode } from './accessors/BatchNode.js';
|
||||
export { default as MaterialNode } from './accessors/MaterialNode.js';
|
||||
export { default as MaterialReferenceNode } from './accessors/MaterialReferenceNode.js';
|
||||
export { default as RendererReferenceNode } from './accessors/RendererReferenceNode.js';
|
||||
export { default as MorphNode } from './accessors/MorphNode.js';
|
||||
export { default as ModelNode } from './accessors/ModelNode.js';
|
||||
export { default as Object3DNode } from './accessors/Object3DNode.js';
|
||||
export { default as PointUVNode } from './accessors/PointUVNode.js';
|
||||
export { default as ReferenceNode } from './accessors/ReferenceNode.js';
|
||||
export { default as SkinningNode } from './accessors/SkinningNode.js';
|
||||
export { default as SceneNode } from './accessors/SceneNode.js';
|
||||
export { default as StorageBufferNode } from './accessors/StorageBufferNode.js';
|
||||
export { default as TextureNode } from './accessors/TextureNode.js';
|
||||
export { default as TextureSizeNode } from './accessors/TextureSizeNode.js';
|
||||
export { default as StorageTextureNode } from './accessors/StorageTextureNode.js';
|
||||
export { default as Texture3DNode } from './accessors/Texture3DNode.js';
|
||||
export { default as UserDataNode } from './accessors/UserDataNode.js';
|
||||
|
||||
// display
|
||||
export { default as BumpMapNode } from './display/BumpMapNode.js';
|
||||
export { default as ColorSpaceNode } from './display/ColorSpaceNode.js';
|
||||
export { default as FrontFacingNode } from './display/FrontFacingNode.js';
|
||||
export { default as NormalMapNode } from './display/NormalMapNode.js';
|
||||
export { default as PosterizeNode } from './display/PosterizeNode.js';
|
||||
export { default as ToneMappingNode } from './display/ToneMappingNode.js';
|
||||
export { default as ScreenNode } from './display/ScreenNode.js';
|
||||
export { default as ViewportTextureNode } from './display/ViewportTextureNode.js';
|
||||
export { default as ViewportSharedTextureNode } from './display/ViewportSharedTextureNode.js';
|
||||
export { default as ViewportDepthTextureNode } from './display/ViewportDepthTextureNode.js';
|
||||
export { default as ViewportDepthNode } from './display/ViewportDepthNode.js';
|
||||
export { default as RenderOutputNode } from './display/RenderOutputNode.js';
|
||||
export { default as PassNode } from './display/PassNode.js';
|
||||
export { default as ToonOutlinePassNode } from './display/ToonOutlinePassNode.js';
|
||||
|
||||
// code
|
||||
export { default as ExpressionNode } from './code/ExpressionNode.js';
|
||||
export { default as CodeNode } from './code/CodeNode.js';
|
||||
export { default as FunctionCallNode } from './code/FunctionCallNode.js';
|
||||
export { default as FunctionNode } from './code/FunctionNode.js';
|
||||
export { default as ScriptableNode } from './code/ScriptableNode.js';
|
||||
export { default as ScriptableValueNode } from './code/ScriptableValueNode.js';
|
||||
|
||||
// geometry
|
||||
export { default as RangeNode } from './geometry/RangeNode.js';
|
||||
|
||||
// gpgpu
|
||||
export { default as ComputeNode } from './gpgpu/ComputeNode.js';
|
||||
|
||||
// lighting
|
||||
export { default as PointLightNode } from './lighting/PointLightNode.js';
|
||||
export { default as DirectionalLightNode } from './lighting/DirectionalLightNode.js';
|
||||
export { default as RectAreaLightNode } from './lighting/RectAreaLightNode.js';
|
||||
export { default as SpotLightNode } from './lighting/SpotLightNode.js';
|
||||
export { default as IESSpotLightNode } from './lighting/IESSpotLightNode.js';
|
||||
export { default as ProjectorLightNode } from './lighting/ProjectorLightNode.js';
|
||||
export { default as AmbientLightNode } from './lighting/AmbientLightNode.js';
|
||||
export { default as LightsNode } from './lighting/LightsNode.js';
|
||||
export { default as LightingNode } from './lighting/LightingNode.js';
|
||||
export { default as LightingContextNode } from './lighting/LightingContextNode.js';
|
||||
export { default as HemisphereLightNode } from './lighting/HemisphereLightNode.js';
|
||||
export { default as LightProbeNode } from './lighting/LightProbeNode.js';
|
||||
export { default as EnvironmentNode } from './lighting/EnvironmentNode.js';
|
||||
export { default as BasicEnvironmentNode } from './lighting/BasicEnvironmentNode.js';
|
||||
export { default as IrradianceNode } from './lighting/IrradianceNode.js';
|
||||
export { default as AONode } from './lighting/AONode.js';
|
||||
export { default as AnalyticLightNode } from './lighting/AnalyticLightNode.js';
|
||||
export { default as ShadowBaseNode } from './lighting/ShadowBaseNode.js';
|
||||
export { default as ShadowNode } from './lighting/ShadowNode.js';
|
||||
|
||||
// pmrem
|
||||
export { default as PMREMNode } from './pmrem/PMREMNode.js';
|
||||
|
||||
// parsers
|
||||
export { default as GLSLNodeParser } from './parsers/GLSLNodeParser.js'; // @TODO: Move to jsm/renderers/webgl.
|
||||
|
||||
// lighting models
|
||||
export { default as PhongLightingModel } from './functions/PhongLightingModel.js';
|
||||
export { default as PhysicalLightingModel } from './functions/PhysicalLightingModel.js';
|
||||
169
app/node_modules/three/src/nodes/TSL.js
generated
vendored
Normal file
169
app/node_modules/three/src/nodes/TSL.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
// constants
|
||||
export * from './core/constants.js';
|
||||
|
||||
// core
|
||||
export * from './core/AssignNode.js';
|
||||
export * from './core/AttributeNode.js';
|
||||
export * from './core/BypassNode.js';
|
||||
export * from './core/CacheNode.js';
|
||||
export * from './core/ContextNode.js';
|
||||
export * from './core/IndexNode.js';
|
||||
export * from './core/ParameterNode.js';
|
||||
export * from './core/PropertyNode.js';
|
||||
export * from './core/StackNode.js';
|
||||
export * from './core/StructNode.js';
|
||||
export * from './core/UniformGroupNode.js';
|
||||
export * from './core/UniformNode.js';
|
||||
export * from './core/VaryingNode.js';
|
||||
export * from './core/OutputStructNode.js';
|
||||
export * from './core/MRTNode.js';
|
||||
|
||||
// math
|
||||
export * from './math/Hash.js';
|
||||
export * from './math/MathUtils.js';
|
||||
export * from './math/TriNoise3D.js';
|
||||
|
||||
// utils
|
||||
export * from './utils/EquirectUV.js';
|
||||
export * from './utils/FunctionOverloadingNode.js';
|
||||
export * from './utils/LoopNode.js';
|
||||
export * from './utils/MatcapUV.js';
|
||||
export * from './utils/MaxMipLevelNode.js';
|
||||
export * from './utils/Oscillators.js';
|
||||
export * from './utils/Packing.js';
|
||||
export * from './utils/RemapNode.js';
|
||||
export * from './utils/UVUtils.js';
|
||||
export * from './utils/SpriteUtils.js';
|
||||
export * from './utils/ViewportUtils.js';
|
||||
export * from './utils/RotateNode.js';
|
||||
export * from './utils/SpriteSheetUVNode.js';
|
||||
export * from './utils/Timer.js';
|
||||
export * from './utils/TriplanarTextures.js';
|
||||
export * from './utils/ReflectorNode.js';
|
||||
export * from './utils/RTTNode.js';
|
||||
export * from './utils/PostProcessingUtils.js';
|
||||
export * from './utils/SampleNode.js';
|
||||
|
||||
// three.js shading language
|
||||
export * from './tsl/TSLBase.js';
|
||||
|
||||
// accessors
|
||||
export * from './accessors/AccessorsUtils.js';
|
||||
export * from './accessors/Arrays.js';
|
||||
export * from './accessors/UniformArrayNode.js';
|
||||
export * from './accessors/Bitangent.js';
|
||||
export * from './accessors/BufferAttributeNode.js';
|
||||
export * from './accessors/BufferNode.js';
|
||||
export * from './accessors/Camera.js';
|
||||
export * from './accessors/VertexColorNode.js';
|
||||
export * from './accessors/CubeTextureNode.js';
|
||||
export * from './accessors/InstanceNode.js';
|
||||
export * from './accessors/InstancedMeshNode.js';
|
||||
export * from './accessors/BatchNode.js';
|
||||
export * from './accessors/MaterialNode.js';
|
||||
export * from './accessors/MaterialProperties.js';
|
||||
export * from './accessors/MaterialReferenceNode.js';
|
||||
export * from './accessors/RendererReferenceNode.js';
|
||||
export * from './accessors/MorphNode.js';
|
||||
export * from './accessors/TextureBicubic.js';
|
||||
export * from './accessors/ModelNode.js';
|
||||
export * from './accessors/ModelViewProjectionNode.js';
|
||||
export * from './accessors/Normal.js';
|
||||
export * from './accessors/Object3DNode.js';
|
||||
export * from './accessors/PointUVNode.js';
|
||||
export * from './accessors/Position.js';
|
||||
export * from './accessors/ReferenceNode.js';
|
||||
export * from './accessors/ReflectVector.js';
|
||||
export * from './accessors/SkinningNode.js';
|
||||
export * from './accessors/SceneNode.js';
|
||||
export * from './accessors/StorageBufferNode.js';
|
||||
export * from './accessors/Tangent.js';
|
||||
export * from './accessors/TextureNode.js';
|
||||
export * from './accessors/TextureSizeNode.js';
|
||||
export * from './accessors/StorageTextureNode.js';
|
||||
export * from './accessors/Texture3DNode.js';
|
||||
export * from './accessors/UV.js';
|
||||
export * from './accessors/UserDataNode.js';
|
||||
export * from './accessors/VelocityNode.js';
|
||||
|
||||
// display
|
||||
export * from './display/BlendModes.js';
|
||||
export * from './display/BumpMapNode.js';
|
||||
export * from './display/ColorAdjustment.js';
|
||||
export * from './display/ColorSpaceNode.js';
|
||||
export * from './display/FrontFacingNode.js';
|
||||
export * from './display/NormalMapNode.js';
|
||||
export * from './display/PosterizeNode.js';
|
||||
export * from './display/ToneMappingNode.js';
|
||||
export * from './display/ScreenNode.js';
|
||||
export * from './display/ViewportTextureNode.js';
|
||||
export * from './display/ViewportSharedTextureNode.js';
|
||||
export * from './display/ViewportDepthTextureNode.js';
|
||||
export * from './display/ViewportDepthNode.js';
|
||||
export * from './display/RenderOutputNode.js';
|
||||
export * from './display/ToonOutlinePassNode.js';
|
||||
|
||||
export * from './display/PassNode.js';
|
||||
|
||||
export * from './display/ColorSpaceFunctions.js';
|
||||
export * from './display/ToneMappingFunctions.js';
|
||||
|
||||
// code
|
||||
export * from './code/ExpressionNode.js';
|
||||
export * from './code/CodeNode.js';
|
||||
export * from './code/FunctionCallNode.js';
|
||||
export * from './code/FunctionNode.js';
|
||||
export * from './code/ScriptableNode.js';
|
||||
export * from './code/ScriptableValueNode.js';
|
||||
|
||||
// fog
|
||||
export * from './fog/Fog.js';
|
||||
|
||||
// geometry
|
||||
export * from './geometry/RangeNode.js';
|
||||
|
||||
// gpgpu
|
||||
export * from './gpgpu/ComputeNode.js';
|
||||
export * from './gpgpu/ComputeBuiltinNode.js';
|
||||
export * from './gpgpu/BarrierNode.js';
|
||||
export * from './gpgpu/WorkgroupInfoNode.js';
|
||||
export * from './gpgpu/AtomicFunctionNode.js';
|
||||
|
||||
// lighting
|
||||
export * from './accessors/Lights.js';
|
||||
export * from './lighting/LightsNode.js';
|
||||
export * from './lighting/LightingContextNode.js';
|
||||
export * from './lighting/ShadowBaseNode.js';
|
||||
export * from './lighting/ShadowNode.js';
|
||||
export * from './lighting/ShadowFilterNode.js';
|
||||
export * from './lighting/PointShadowNode.js';
|
||||
export * from './lighting/PointLightNode.js';
|
||||
|
||||
// pmrem
|
||||
export * from './pmrem/PMREMNode.js';
|
||||
export * from './pmrem/PMREMUtils.js';
|
||||
|
||||
// procedural
|
||||
export * from './procedural/Checker.js';
|
||||
|
||||
// shapes
|
||||
export * from './shapes/Shapes.js';
|
||||
|
||||
// materialX
|
||||
export * from './materialx/MaterialXNodes.js';
|
||||
|
||||
// functions
|
||||
export { default as BRDF_GGX } from './functions/BSDF/BRDF_GGX.js';
|
||||
export { default as BRDF_Lambert } from './functions/BSDF/BRDF_Lambert.js';
|
||||
export { default as D_GGX } from './functions/BSDF/D_GGX.js';
|
||||
export { default as DFGApprox } from './functions/BSDF/DFGApprox.js';
|
||||
export { default as F_Schlick } from './functions/BSDF/F_Schlick.js';
|
||||
export { default as Schlick_to_F0 } from './functions/BSDF/Schlick_to_F0.js';
|
||||
export { default as V_GGX_SmithCorrelated } from './functions/BSDF/V_GGX_SmithCorrelated.js';
|
||||
|
||||
export * from './lighting/LightUtils.js';
|
||||
|
||||
export { default as getGeometryRoughness } from './functions/material/getGeometryRoughness.js';
|
||||
export { default as getParallaxCorrectNormal } from './functions/material/getParallaxCorrectNormal.js';
|
||||
export { default as getRoughness } from './functions/material/getRoughness.js';
|
||||
export { default as getShIrradianceAt } from './functions/material/getShIrradianceAt.js';
|
||||
53
app/node_modules/three/src/nodes/accessors/AccessorsUtils.js
generated
vendored
Normal file
53
app/node_modules/three/src/nodes/accessors/AccessorsUtils.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import { normalView } from './Normal.js';
|
||||
import { tangentView } from './Tangent.js';
|
||||
import { bitangentView } from './Bitangent.js';
|
||||
import { Fn, mat3 } from '../tsl/TSLBase.js';
|
||||
import { mix } from '../math/MathNode.js';
|
||||
import { anisotropy, anisotropyB, roughness } from '../core/PropertyNode.js';
|
||||
import { positionViewDirection } from './Position.js';
|
||||
|
||||
/**
|
||||
* TSL object that represents the TBN matrix in view space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat3>}
|
||||
*/
|
||||
export const TBNViewMatrix = /*@__PURE__*/ mat3( tangentView, bitangentView, normalView ).toVar( 'TBNViewMatrix' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the parallax direction.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat3>}
|
||||
*/
|
||||
export const parallaxDirection = /*@__PURE__*/ positionViewDirection.mul( TBNViewMatrix )/*.normalize()*/;
|
||||
|
||||
/**
|
||||
* TSL function for computing parallax uv coordinates.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec2>} uv - A uv node.
|
||||
* @param {Node<vec2>} scale - A scale node.
|
||||
* @returns {Node<vec2>} Parallax uv coordinates.
|
||||
*/
|
||||
export const parallaxUV = ( uv, scale ) => uv.sub( parallaxDirection.mul( scale ) );
|
||||
|
||||
/**
|
||||
* TSL function for computing bent normals.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @returns {Node<vec3>} Bent normals.
|
||||
*/
|
||||
export const bentNormalView = /*@__PURE__*/ ( Fn( () => {
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/anisotropy
|
||||
|
||||
let bentNormal = anisotropyB.cross( positionViewDirection );
|
||||
bentNormal = bentNormal.cross( anisotropyB ).normalize();
|
||||
bentNormal = mix( bentNormal, normalView, anisotropy.mul( roughness.oneMinus() ).oneMinus().pow2().pow2() ).normalize();
|
||||
|
||||
return bentNormal;
|
||||
|
||||
} ).once() )();
|
||||
68
app/node_modules/three/src/nodes/accessors/Arrays.js
generated
vendored
Normal file
68
app/node_modules/three/src/nodes/accessors/Arrays.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import StorageInstancedBufferAttribute from '../../renderers/common/StorageInstancedBufferAttribute.js';
|
||||
import StorageBufferAttribute from '../../renderers/common/StorageBufferAttribute.js';
|
||||
import { storage } from './StorageBufferNode.js';
|
||||
import { getLengthFromType, getTypedArrayFromType } from '../core/NodeUtils.js';
|
||||
|
||||
/**
|
||||
* TSL function for creating a storage buffer node with a configured `StorageBufferAttribute`.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {number|TypedArray} count - The data count. It is also valid to pass a typed array as an argument.
|
||||
* @param {string|Struct} [type='float'] - The data type.
|
||||
* @returns {StorageBufferNode}
|
||||
*/
|
||||
export const attributeArray = ( count, type = 'float' ) => {
|
||||
|
||||
let itemSize, typedArray;
|
||||
|
||||
if ( type.isStruct === true ) {
|
||||
|
||||
itemSize = type.layout.getLength();
|
||||
typedArray = getTypedArrayFromType( 'float' );
|
||||
|
||||
} else {
|
||||
|
||||
itemSize = getLengthFromType( type );
|
||||
typedArray = getTypedArrayFromType( type );
|
||||
|
||||
}
|
||||
|
||||
const buffer = new StorageBufferAttribute( count, itemSize, typedArray );
|
||||
const node = storage( buffer, type, count );
|
||||
|
||||
return node;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* TSL function for creating a storage buffer node with a configured `StorageInstancedBufferAttribute`.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {number|TypedArray} count - The data count. It is also valid to pass a typed array as an argument.
|
||||
* @param {string|Struct} [type='float'] - The data type.
|
||||
* @returns {StorageBufferNode}
|
||||
*/
|
||||
export const instancedArray = ( count, type = 'float' ) => {
|
||||
|
||||
let itemSize, typedArray;
|
||||
|
||||
if ( type.isStruct === true ) {
|
||||
|
||||
itemSize = type.layout.getLength();
|
||||
typedArray = getTypedArrayFromType( 'float' );
|
||||
|
||||
} else {
|
||||
|
||||
itemSize = getLengthFromType( type );
|
||||
typedArray = getTypedArrayFromType( type );
|
||||
|
||||
}
|
||||
|
||||
const buffer = new StorageInstancedBufferAttribute( count, itemSize, typedArray );
|
||||
const node = storage( buffer, type, count );
|
||||
|
||||
return node;
|
||||
|
||||
};
|
||||
163
app/node_modules/three/src/nodes/accessors/BatchNode.js
generated
vendored
Normal file
163
app/node_modules/three/src/nodes/accessors/BatchNode.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { normalLocal } from './Normal.js';
|
||||
import { positionLocal } from './Position.js';
|
||||
import { nodeProxy, vec3, mat3, mat4, int, ivec2, float, Fn } from '../tsl/TSLBase.js';
|
||||
import { textureLoad } from './TextureNode.js';
|
||||
import { textureSize } from './TextureSizeNode.js';
|
||||
import { tangentLocal } from './Tangent.js';
|
||||
import { instanceIndex, drawIndex } from '../core/IndexNode.js';
|
||||
import { varyingProperty } from '../core/PropertyNode.js';
|
||||
|
||||
/**
|
||||
* This node implements the vertex shader logic which is required
|
||||
* when rendering 3D objects via batching. `BatchNode` must be used
|
||||
* with instances of {@link BatchedMesh}.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class BatchNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'BatchNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new batch node.
|
||||
*
|
||||
* @param {BatchedMesh} batchMesh - A reference to batched mesh.
|
||||
*/
|
||||
constructor( batchMesh ) {
|
||||
|
||||
super( 'void' );
|
||||
|
||||
/**
|
||||
* A reference to batched mesh.
|
||||
*
|
||||
* @type {BatchedMesh}
|
||||
*/
|
||||
this.batchMesh = batchMesh;
|
||||
|
||||
/**
|
||||
* The batching index node.
|
||||
*
|
||||
* @type {?IndexNode}
|
||||
* @default null
|
||||
*/
|
||||
this.batchingIdNode = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the internal buffers and nodes and assigns the transformed vertex data
|
||||
* to predefined node variables for accumulation. That follows the same patterns
|
||||
* like with morph and skinning nodes.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
if ( this.batchingIdNode === null ) {
|
||||
|
||||
if ( builder.getDrawIndex() === null ) {
|
||||
|
||||
this.batchingIdNode = instanceIndex;
|
||||
|
||||
} else {
|
||||
|
||||
this.batchingIdNode = drawIndex;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const getIndirectIndex = Fn( ( [ id ] ) => {
|
||||
|
||||
const size = int( textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ).x );
|
||||
const x = int( id ).mod( size );
|
||||
const y = int( id ).div( size );
|
||||
return textureLoad( this.batchMesh._indirectTexture, ivec2( x, y ) ).x;
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'getIndirectIndex',
|
||||
type: 'uint',
|
||||
inputs: [
|
||||
{ name: 'id', type: 'int' }
|
||||
]
|
||||
} );
|
||||
|
||||
const indirectId = getIndirectIndex( int( this.batchingIdNode ) );
|
||||
|
||||
const matricesTexture = this.batchMesh._matricesTexture;
|
||||
|
||||
const size = int( textureSize( textureLoad( matricesTexture ), 0 ).x );
|
||||
const j = float( indirectId ).mul( 4 ).toInt().toVar();
|
||||
|
||||
const x = j.mod( size );
|
||||
const y = j.div( size );
|
||||
const batchingMatrix = mat4(
|
||||
textureLoad( matricesTexture, ivec2( x, y ) ),
|
||||
textureLoad( matricesTexture, ivec2( x.add( 1 ), y ) ),
|
||||
textureLoad( matricesTexture, ivec2( x.add( 2 ), y ) ),
|
||||
textureLoad( matricesTexture, ivec2( x.add( 3 ), y ) )
|
||||
);
|
||||
|
||||
|
||||
const colorsTexture = this.batchMesh._colorsTexture;
|
||||
|
||||
if ( colorsTexture !== null ) {
|
||||
|
||||
const getBatchingColor = Fn( ( [ id ] ) => {
|
||||
|
||||
const size = int( textureSize( textureLoad( colorsTexture ), 0 ).x );
|
||||
const j = id;
|
||||
const x = j.mod( size );
|
||||
const y = j.div( size );
|
||||
return textureLoad( colorsTexture, ivec2( x, y ) ).rgb;
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'getBatchingColor',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'id', type: 'int' }
|
||||
]
|
||||
} );
|
||||
|
||||
const color = getBatchingColor( indirectId );
|
||||
|
||||
varyingProperty( 'vec3', 'vBatchColor' ).assign( color );
|
||||
|
||||
}
|
||||
|
||||
const bm = mat3( batchingMatrix );
|
||||
|
||||
positionLocal.assign( batchingMatrix.mul( positionLocal ) );
|
||||
|
||||
const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) );
|
||||
|
||||
const batchingNormal = bm.mul( transformedNormal ).xyz;
|
||||
|
||||
normalLocal.assign( batchingNormal );
|
||||
|
||||
if ( builder.hasGeometryAttribute( 'tangent' ) ) {
|
||||
|
||||
tangentLocal.mulAssign( bm );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BatchNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a batch node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {BatchedMesh} batchMesh - A reference to batched mesh.
|
||||
* @returns {BatchNode}
|
||||
*/
|
||||
export const batch = /*@__PURE__*/ nodeProxy( BatchNode ).setParameterLength( 1 );
|
||||
82
app/node_modules/three/src/nodes/accessors/Bitangent.js
generated
vendored
Normal file
82
app/node_modules/three/src/nodes/accessors/Bitangent.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Fn } from '../tsl/TSLCore.js';
|
||||
import { normalGeometry, normalLocal, normalView, normalWorld } from './Normal.js';
|
||||
import { tangentGeometry, tangentLocal, tangentView, tangentWorld } from './Tangent.js';
|
||||
import { bitangentViewFrame } from './TangentUtils.js';
|
||||
import { directionToFaceDirection } from '../display/FrontFacingNode.js';
|
||||
|
||||
/**
|
||||
* Returns the bitangent node and assigns it to a varying if the material is not flat shaded.
|
||||
*
|
||||
* @tsl
|
||||
* @private
|
||||
* @param {Node<vec3>} crossNormalTangent - The cross product of the normal and tangent vectors.
|
||||
* @param {string} varyingName - The name of the varying to assign the bitangent to.
|
||||
* @returns {Node<vec3>} The bitangent node.
|
||||
*/
|
||||
const getBitangent = /*@__PURE__*/ Fn( ( [ crossNormalTangent, varyingName ], { subBuildFn, material } ) => {
|
||||
|
||||
let bitangent = crossNormalTangent.mul( tangentGeometry.w ).xyz;
|
||||
|
||||
if ( subBuildFn === 'NORMAL' && material.flatShading !== true ) {
|
||||
|
||||
bitangent = bitangent.toVarying( varyingName );
|
||||
|
||||
}
|
||||
|
||||
return bitangent;
|
||||
|
||||
} ).once( [ 'NORMAL' ] );
|
||||
|
||||
/**
|
||||
* TSL object that represents the bitangent attribute of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const bitangentGeometry = /*@__PURE__*/ getBitangent( normalGeometry.cross( tangentGeometry ), 'v_bitangentGeometry' ).normalize().toVar( 'bitangentGeometry' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex bitangent in local space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const bitangentLocal = /*@__PURE__*/ getBitangent( normalLocal.cross( tangentLocal ), 'v_bitangentLocal' ).normalize().toVar( 'bitangentLocal' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex bitangent in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const bitangentView = /*@__PURE__*/ ( Fn( ( { subBuildFn, geometry, material } ) => {
|
||||
|
||||
let node;
|
||||
|
||||
if ( subBuildFn === 'VERTEX' || geometry.hasAttribute( 'tangent' ) ) {
|
||||
|
||||
node = getBitangent( normalView.cross( tangentView ), 'v_bitangentView' ).normalize();
|
||||
|
||||
} else {
|
||||
|
||||
node = bitangentViewFrame;
|
||||
|
||||
}
|
||||
|
||||
if ( material.flatShading !== true ) {
|
||||
|
||||
node = directionToFaceDirection( node );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}, 'vec3' ).once( [ 'NORMAL', 'VERTEX' ] ) )().toVar( 'bitangentView' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex bitangent in world space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const bitangentWorld = /*@__PURE__*/ getBitangent( normalWorld.cross( tangentWorld ), 'v_bitangentWorld' ).normalize().toVar( 'bitangentWorld' );
|
||||
340
app/node_modules/three/src/nodes/accessors/BufferAttributeNode.js
generated
vendored
Normal file
340
app/node_modules/three/src/nodes/accessors/BufferAttributeNode.js
generated
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
import InputNode from '../core/InputNode.js';
|
||||
import { nodeObject, addMethodChaining } from '../tsl/TSLCore.js';
|
||||
import { varying } from '../core/VaryingNode.js';
|
||||
|
||||
import { InterleavedBufferAttribute } from '../../core/InterleavedBufferAttribute.js';
|
||||
import { InterleavedBuffer } from '../../core/InterleavedBuffer.js';
|
||||
import { StaticDrawUsage, DynamicDrawUsage } from '../../constants.js';
|
||||
|
||||
/**
|
||||
* In earlier `three.js` versions it was only possible to define attribute data
|
||||
* on geometry level. With `BufferAttributeNode`, it is also possible to do this
|
||||
* on the node level.
|
||||
* ```js
|
||||
* const geometry = new THREE.PlaneGeometry();
|
||||
* const positionAttribute = geometry.getAttribute( 'position' );
|
||||
*
|
||||
* const colors = [];
|
||||
* for ( let i = 0; i < position.count; i ++ ) {
|
||||
* colors.push( 1, 0, 0 );
|
||||
* }
|
||||
*
|
||||
* material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) );
|
||||
* ```
|
||||
* This new approach is especially interesting when geometry data are generated via
|
||||
* compute shaders. The below line converts a storage buffer into an attribute node.
|
||||
* ```js
|
||||
* material.positionNode = positionBuffer.toAttribute();
|
||||
* ```
|
||||
* @augments InputNode
|
||||
*/
|
||||
class BufferAttributeNode extends InputNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'BufferAttributeNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new buffer attribute node.
|
||||
*
|
||||
* @param {BufferAttribute|InterleavedBuffer|TypedArray} value - The attribute data.
|
||||
* @param {?string} [bufferType=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [bufferStride=0] - The buffer stride.
|
||||
* @param {number} [bufferOffset=0] - The buffer offset.
|
||||
*/
|
||||
constructor( value, bufferType = null, bufferStride = 0, bufferOffset = 0 ) {
|
||||
|
||||
super( value, bufferType );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isBufferNode = true;
|
||||
|
||||
/**
|
||||
* The buffer type (e.g. `'vec3'`).
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.bufferType = bufferType;
|
||||
|
||||
/**
|
||||
* The buffer stride.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.bufferStride = bufferStride;
|
||||
|
||||
/**
|
||||
* The buffer offset.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.bufferOffset = bufferOffset;
|
||||
|
||||
/**
|
||||
* The usage property. Set this to `THREE.DynamicDrawUsage` via `.setUsage()`,
|
||||
* if you are planning to update the attribute data per frame.
|
||||
*
|
||||
* @type {number}
|
||||
* @default StaticDrawUsage
|
||||
*/
|
||||
this.usage = StaticDrawUsage;
|
||||
|
||||
/**
|
||||
* Whether the attribute is instanced or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.instanced = false;
|
||||
|
||||
/**
|
||||
* A reference to the buffer attribute.
|
||||
*
|
||||
* @type {?BufferAttribute}
|
||||
* @default null
|
||||
*/
|
||||
this.attribute = null;
|
||||
|
||||
/**
|
||||
* `BufferAttributeNode` sets this property to `true` by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
if ( value && value.isBufferAttribute === true ) {
|
||||
|
||||
this.attribute = value;
|
||||
this.usage = value.usage;
|
||||
this.instanced = value.isInstancedBufferAttribute;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the attribute data might be shared
|
||||
* and thus the hash should be shared as well.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The hash.
|
||||
*/
|
||||
getHash( builder ) {
|
||||
|
||||
if ( this.bufferStride === 0 && this.bufferOffset === 0 ) {
|
||||
|
||||
let bufferData = builder.globalCache.getData( this.value );
|
||||
|
||||
if ( bufferData === undefined ) {
|
||||
|
||||
bufferData = {
|
||||
node: this
|
||||
};
|
||||
|
||||
builder.globalCache.setData( this.value, bufferData );
|
||||
|
||||
}
|
||||
|
||||
return bufferData.node.uuid;
|
||||
|
||||
}
|
||||
|
||||
return this.uuid;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type is inferred from
|
||||
* the buffer attribute.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
if ( this.bufferType === null ) {
|
||||
|
||||
this.bufferType = builder.getTypeFromAttribute( this.attribute );
|
||||
|
||||
}
|
||||
|
||||
return this.bufferType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on which value was passed to the node, `setup()` behaves
|
||||
* differently. If no instance of `BufferAttribute` was passed, the method
|
||||
* creates an internal attribute and configures it respectively.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
if ( this.attribute !== null ) return;
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
const array = this.value;
|
||||
const itemSize = builder.getTypeLength( type );
|
||||
const stride = this.bufferStride || itemSize;
|
||||
const offset = this.bufferOffset;
|
||||
|
||||
const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride );
|
||||
const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset );
|
||||
|
||||
buffer.setUsage( this.usage );
|
||||
|
||||
this.attribute = bufferAttribute;
|
||||
this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the buffer attribute node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( builder ) {
|
||||
|
||||
const nodeType = this.getNodeType( builder );
|
||||
|
||||
const nodeAttribute = builder.getBufferAttributeFromNode( this, nodeType );
|
||||
const propertyName = builder.getPropertyName( nodeAttribute );
|
||||
|
||||
let output = null;
|
||||
|
||||
if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) {
|
||||
|
||||
this.name = propertyName;
|
||||
|
||||
output = propertyName;
|
||||
|
||||
} else {
|
||||
|
||||
const nodeVarying = varying( this );
|
||||
|
||||
output = nodeVarying.build( builder, nodeType );
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'bufferAttribute'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return 'bufferAttribute';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `usage` property to the given value.
|
||||
*
|
||||
* @param {number} value - The usage to set.
|
||||
* @return {BufferAttributeNode} A reference to this node.
|
||||
*/
|
||||
setUsage( value ) {
|
||||
|
||||
this.usage = value;
|
||||
|
||||
if ( this.attribute && this.attribute.isBufferAttribute === true ) {
|
||||
|
||||
this.attribute.usage = value;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `instanced` property to the given value.
|
||||
*
|
||||
* @param {boolean} value - The value to set.
|
||||
* @return {BufferAttributeNode} A reference to this node.
|
||||
*/
|
||||
setInstanced( value ) {
|
||||
|
||||
this.instanced = value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BufferAttributeNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a buffer attribute node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
|
||||
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [stride=0] - The buffer stride.
|
||||
* @param {number} [offset=0] - The buffer offset.
|
||||
* @returns {BufferAttributeNode}
|
||||
*/
|
||||
export const bufferAttribute = ( array, type = null, stride = 0, offset = 0 ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) );
|
||||
|
||||
/**
|
||||
* TSL function for creating a buffer attribute node but with dynamic draw usage.
|
||||
* Use this function if attribute data are updated per frame.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
|
||||
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [stride=0] - The buffer stride.
|
||||
* @param {number} [offset=0] - The buffer offset.
|
||||
* @returns {BufferAttributeNode}
|
||||
*/
|
||||
export const dynamicBufferAttribute = ( array, type = null, stride = 0, offset = 0 ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage );
|
||||
|
||||
/**
|
||||
* TSL function for creating a buffer attribute node but with enabled instancing
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
|
||||
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [stride=0] - The buffer stride.
|
||||
* @param {number} [offset=0] - The buffer offset.
|
||||
* @returns {BufferAttributeNode}
|
||||
*/
|
||||
export const instancedBufferAttribute = ( array, type = null, stride = 0, offset = 0 ) => bufferAttribute( array, type, stride, offset ).setInstanced( true );
|
||||
|
||||
/**
|
||||
* TSL function for creating a buffer attribute node but with dynamic draw usage and enabled instancing
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {BufferAttribute|InterleavedBuffer|TypedArray} array - The attribute data.
|
||||
* @param {?string} [type=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [stride=0] - The buffer stride.
|
||||
* @param {number} [offset=0] - The buffer offset.
|
||||
* @returns {BufferAttributeNode}
|
||||
*/
|
||||
export const instancedDynamicBufferAttribute = ( array, type = null, stride = 0, offset = 0 ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true );
|
||||
|
||||
addMethodChaining( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) );
|
||||
101
app/node_modules/three/src/nodes/accessors/BufferNode.js
generated
vendored
Normal file
101
app/node_modules/three/src/nodes/accessors/BufferNode.js
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
import UniformNode from '../core/UniformNode.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* A special type of uniform node which represents array-like data
|
||||
* as uniform buffers. The access usually happens via `element()`
|
||||
* which returns an instance of {@link ArrayElementNode}. For example:
|
||||
*
|
||||
* ```js
|
||||
* const bufferNode = buffer( array, 'mat4', count );
|
||||
* const matrixNode = bufferNode.element( index ); // access a matrix from the buffer
|
||||
* ```
|
||||
* In general, it is recommended to use the more managed {@link UniformArrayNode}
|
||||
* since it handles more input types and automatically cares about buffer paddings.
|
||||
*
|
||||
* @augments UniformNode
|
||||
*/
|
||||
class BufferNode extends UniformNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'BufferNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new buffer node.
|
||||
*
|
||||
* @param {Array<number>} value - Array-like buffer data.
|
||||
* @param {string} bufferType - The data type of the buffer.
|
||||
* @param {number} [bufferCount=0] - The count of buffer elements.
|
||||
*/
|
||||
constructor( value, bufferType, bufferCount = 0 ) {
|
||||
|
||||
super( value, bufferType );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isBufferNode = true;
|
||||
|
||||
/**
|
||||
* The data type of the buffer.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.bufferType = bufferType;
|
||||
|
||||
/**
|
||||
* The uniform node that holds the value of the reference node.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.bufferCount = bufferCount;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The data type of the buffer elements.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The element type.
|
||||
*/
|
||||
getElementType( builder ) {
|
||||
|
||||
return this.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'buffer'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return 'buffer';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BufferNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a buffer node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Array} value - Array-like buffer data.
|
||||
* @param {string} type - The data type of a buffer element.
|
||||
* @param {number} count - The count of buffer elements.
|
||||
* @returns {BufferNode}
|
||||
*/
|
||||
export const buffer = ( value, type, count ) => nodeObject( new BufferNode( value, type, count ) );
|
||||
63
app/node_modules/three/src/nodes/accessors/BuiltinNode.js
generated
vendored
Normal file
63
app/node_modules/three/src/nodes/accessors/BuiltinNode.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* The node allows to set values for built-in shader variables. That is
|
||||
* required for features like hardware-accelerated vertex clipping.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class BuiltinNode extends Node {
|
||||
|
||||
/**
|
||||
* Constructs a new builtin node.
|
||||
*
|
||||
* @param {string} name - The name of the built-in shader variable.
|
||||
*/
|
||||
constructor( name ) {
|
||||
|
||||
super( 'float' );
|
||||
|
||||
/**
|
||||
* The name of the built-in shader variable.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isBuiltinNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the builtin node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( /* builder */ ) {
|
||||
|
||||
return this.name;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BuiltinNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a builtin node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the built-in shader variable.
|
||||
* @returns {BuiltinNode}
|
||||
*/
|
||||
export const builtin = nodeProxy( BuiltinNode ).setParameterLength( 1 );
|
||||
156
app/node_modules/three/src/nodes/accessors/Camera.js
generated
vendored
Normal file
156
app/node_modules/three/src/nodes/accessors/Camera.js
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { renderGroup, sharedUniformGroup } from '../core/UniformGroupNode.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { Fn } from '../tsl/TSLBase.js';
|
||||
import { uniformArray } from './UniformArrayNode.js';
|
||||
import { builtin } from './BuiltinNode.js';
|
||||
|
||||
/**
|
||||
* TSL object that represents the current `index` value of the camera if used ArrayCamera.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<uint>}
|
||||
*/
|
||||
export const cameraIndex = /*@__PURE__*/ uniform( 0, 'uint' ).label( 'u_cameraIndex' ).setGroup( sharedUniformGroup( 'cameraIndex' ) ).toVarying( 'v_cameraIndex' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the `near` value of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<float>}
|
||||
*/
|
||||
export const cameraNear = /*@__PURE__*/ uniform( 'float' ).label( 'cameraNear' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.near );
|
||||
|
||||
/**
|
||||
* TSL object that represents the `far` value of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<float>}
|
||||
*/
|
||||
export const cameraFar = /*@__PURE__*/ uniform( 'float' ).label( 'cameraFar' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.far );
|
||||
|
||||
/**
|
||||
* TSL object that represents the projection matrix of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat4>}
|
||||
*/
|
||||
export const cameraProjectionMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
|
||||
|
||||
let cameraProjectionMatrix;
|
||||
|
||||
if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
|
||||
|
||||
const matrices = [];
|
||||
|
||||
for ( const subCamera of camera.cameras ) {
|
||||
|
||||
matrices.push( subCamera.projectionMatrix );
|
||||
|
||||
}
|
||||
|
||||
const cameraProjectionMatrices = uniformArray( matrices ).setGroup( renderGroup ).label( 'cameraProjectionMatrices' );
|
||||
|
||||
cameraProjectionMatrix = cameraProjectionMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toVar( 'cameraProjectionMatrix' );
|
||||
|
||||
} else {
|
||||
|
||||
cameraProjectionMatrix = uniform( 'mat4' ).label( 'cameraProjectionMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrix );
|
||||
|
||||
}
|
||||
|
||||
return cameraProjectionMatrix;
|
||||
|
||||
} ).once() )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the inverse projection matrix of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat4>}
|
||||
*/
|
||||
export const cameraProjectionMatrixInverse = /*@__PURE__*/ ( Fn( ( { camera } ) => {
|
||||
|
||||
let cameraProjectionMatrixInverse;
|
||||
|
||||
if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
|
||||
|
||||
const matrices = [];
|
||||
|
||||
for ( const subCamera of camera.cameras ) {
|
||||
|
||||
matrices.push( subCamera.projectionMatrixInverse );
|
||||
|
||||
}
|
||||
|
||||
const cameraProjectionMatricesInverse = uniformArray( matrices ).setGroup( renderGroup ).label( 'cameraProjectionMatricesInverse' );
|
||||
|
||||
cameraProjectionMatrixInverse = cameraProjectionMatricesInverse.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toVar( 'cameraProjectionMatrixInverse' );
|
||||
|
||||
} else {
|
||||
|
||||
cameraProjectionMatrixInverse = uniform( 'mat4' ).label( 'cameraProjectionMatrixInverse' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrixInverse );
|
||||
|
||||
}
|
||||
|
||||
return cameraProjectionMatrixInverse;
|
||||
|
||||
} ).once() )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the view matrix of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat4>}
|
||||
*/
|
||||
export const cameraViewMatrix = /*@__PURE__*/ ( Fn( ( { camera } ) => {
|
||||
|
||||
let cameraViewMatrix;
|
||||
|
||||
if ( camera.isArrayCamera && camera.cameras.length > 0 ) {
|
||||
|
||||
const matrices = [];
|
||||
|
||||
for ( const subCamera of camera.cameras ) {
|
||||
|
||||
matrices.push( subCamera.matrixWorldInverse );
|
||||
|
||||
}
|
||||
|
||||
const cameraViewMatrices = uniformArray( matrices ).setGroup( renderGroup ).label( 'cameraViewMatrices' );
|
||||
|
||||
cameraViewMatrix = cameraViewMatrices.element( camera.isMultiViewCamera ? builtin( 'gl_ViewID_OVR' ) : cameraIndex ).toVar( 'cameraViewMatrix' );
|
||||
|
||||
} else {
|
||||
|
||||
cameraViewMatrix = uniform( 'mat4' ).label( 'cameraViewMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorldInverse );
|
||||
|
||||
}
|
||||
|
||||
return cameraViewMatrix;
|
||||
|
||||
} ).once() )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the world matrix of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat4>}
|
||||
*/
|
||||
export const cameraWorldMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraWorldMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorld );
|
||||
|
||||
/**
|
||||
* TSL object that represents the normal matrix of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat3>}
|
||||
*/
|
||||
export const cameraNormalMatrix = /*@__PURE__*/ uniform( 'mat3' ).label( 'cameraNormalMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.normalMatrix );
|
||||
|
||||
/**
|
||||
* TSL object that represents the position in world space of the camera used for the current render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<vec3>}
|
||||
*/
|
||||
export const cameraPosition = /*@__PURE__*/ uniform( new Vector3() ).label( 'cameraPosition' ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => self.value.setFromMatrixPosition( camera.matrixWorld ) );
|
||||
254
app/node_modules/three/src/nodes/accessors/ClippingNode.js
generated
vendored
Normal file
254
app/node_modules/three/src/nodes/accessors/ClippingNode.js
generated
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeObject, Fn, bool, float } from '../tsl/TSLBase.js';
|
||||
import { positionView } from './Position.js';
|
||||
import { diffuseColor } from '../core/PropertyNode.js';
|
||||
import { Loop } from '../utils/LoopNode.js';
|
||||
import { smoothstep } from '../math/MathNode.js';
|
||||
import { uniformArray } from './UniformArrayNode.js';
|
||||
import { builtin } from './BuiltinNode.js';
|
||||
|
||||
/**
|
||||
* This node is used in {@link NodeMaterial} to setup the clipping
|
||||
* which can happen hardware-accelerated (if supported) and optionally
|
||||
* use alpha-to-coverage for anti-aliasing clipped edges.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ClippingNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ClippingNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new clipping node.
|
||||
*
|
||||
* @param {('default'|'hardware'|'alphaToCoverage')} [scope='default'] - The node's scope. Similar to other nodes,
|
||||
* the selected scope influences the behavior of the node and what type of code is generated.
|
||||
*/
|
||||
constructor( scope = ClippingNode.DEFAULT ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The node's scope. Similar to other nodes, the selected scope influences
|
||||
* the behavior of the node and what type of code is generated.
|
||||
*
|
||||
* @type {('default'|'hardware'|'alphaToCoverage')}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the node depending on the selected scope.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node} The result node.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
super.setup( builder );
|
||||
|
||||
const clippingContext = builder.clippingContext;
|
||||
const { intersectionPlanes, unionPlanes } = clippingContext;
|
||||
|
||||
this.hardwareClipping = builder.material.hardwareClipping;
|
||||
|
||||
if ( this.scope === ClippingNode.ALPHA_TO_COVERAGE ) {
|
||||
|
||||
return this.setupAlphaToCoverage( intersectionPlanes, unionPlanes );
|
||||
|
||||
} else if ( this.scope === ClippingNode.HARDWARE ) {
|
||||
|
||||
return this.setupHardwareClipping( unionPlanes, builder );
|
||||
|
||||
} else {
|
||||
|
||||
return this.setupDefault( intersectionPlanes, unionPlanes );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups alpha to coverage.
|
||||
*
|
||||
* @param {Array<Vector4>} intersectionPlanes - The intersection planes.
|
||||
* @param {Array<Vector4>} unionPlanes - The union planes.
|
||||
* @return {Node} The result node.
|
||||
*/
|
||||
setupAlphaToCoverage( intersectionPlanes, unionPlanes ) {
|
||||
|
||||
return Fn( () => {
|
||||
|
||||
const distanceToPlane = float().toVar( 'distanceToPlane' );
|
||||
const distanceGradient = float().toVar( 'distanceToGradient' );
|
||||
|
||||
const clipOpacity = float( 1 ).toVar( 'clipOpacity' );
|
||||
|
||||
const numUnionPlanes = unionPlanes.length;
|
||||
|
||||
if ( this.hardwareClipping === false && numUnionPlanes > 0 ) {
|
||||
|
||||
const clippingPlanes = uniformArray( unionPlanes );
|
||||
|
||||
Loop( numUnionPlanes, ( { i } ) => {
|
||||
|
||||
const plane = clippingPlanes.element( i );
|
||||
|
||||
distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) );
|
||||
distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) );
|
||||
|
||||
clipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ) );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
const numIntersectionPlanes = intersectionPlanes.length;
|
||||
|
||||
if ( numIntersectionPlanes > 0 ) {
|
||||
|
||||
const clippingPlanes = uniformArray( intersectionPlanes );
|
||||
const intersectionClipOpacity = float( 1 ).toVar( 'intersectionClipOpacity' );
|
||||
|
||||
Loop( numIntersectionPlanes, ( { i } ) => {
|
||||
|
||||
const plane = clippingPlanes.element( i );
|
||||
|
||||
distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) );
|
||||
distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) );
|
||||
|
||||
intersectionClipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ).oneMinus() );
|
||||
|
||||
} );
|
||||
|
||||
clipOpacity.mulAssign( intersectionClipOpacity.oneMinus() );
|
||||
|
||||
}
|
||||
|
||||
diffuseColor.a.mulAssign( clipOpacity );
|
||||
|
||||
diffuseColor.a.equal( 0.0 ).discard();
|
||||
|
||||
} )();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the default clipping.
|
||||
*
|
||||
* @param {Array<Vector4>} intersectionPlanes - The intersection planes.
|
||||
* @param {Array<Vector4>} unionPlanes - The union planes.
|
||||
* @return {Node} The result node.
|
||||
*/
|
||||
setupDefault( intersectionPlanes, unionPlanes ) {
|
||||
|
||||
return Fn( () => {
|
||||
|
||||
const numUnionPlanes = unionPlanes.length;
|
||||
|
||||
if ( this.hardwareClipping === false && numUnionPlanes > 0 ) {
|
||||
|
||||
const clippingPlanes = uniformArray( unionPlanes );
|
||||
|
||||
Loop( numUnionPlanes, ( { i } ) => {
|
||||
|
||||
const plane = clippingPlanes.element( i );
|
||||
positionView.dot( plane.xyz ).greaterThan( plane.w ).discard();
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
const numIntersectionPlanes = intersectionPlanes.length;
|
||||
|
||||
if ( numIntersectionPlanes > 0 ) {
|
||||
|
||||
const clippingPlanes = uniformArray( intersectionPlanes );
|
||||
const clipped = bool( true ).toVar( 'clipped' );
|
||||
|
||||
Loop( numIntersectionPlanes, ( { i } ) => {
|
||||
|
||||
const plane = clippingPlanes.element( i );
|
||||
clipped.assign( positionView.dot( plane.xyz ).greaterThan( plane.w ).and( clipped ) );
|
||||
|
||||
} );
|
||||
|
||||
clipped.discard();
|
||||
|
||||
}
|
||||
|
||||
} )();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups hardware clipping.
|
||||
*
|
||||
* @param {Array<Vector4>} unionPlanes - The union planes.
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node} The result node.
|
||||
*/
|
||||
setupHardwareClipping( unionPlanes, builder ) {
|
||||
|
||||
const numUnionPlanes = unionPlanes.length;
|
||||
|
||||
builder.enableHardwareClipping( numUnionPlanes );
|
||||
|
||||
return Fn( () => {
|
||||
|
||||
const clippingPlanes = uniformArray( unionPlanes );
|
||||
const hw_clip_distances = builtin( builder.getClipDistance() );
|
||||
|
||||
Loop( numUnionPlanes, ( { i } ) => {
|
||||
|
||||
const plane = clippingPlanes.element( i );
|
||||
|
||||
const distance = positionView.dot( plane.xyz ).sub( plane.w ).negate();
|
||||
hw_clip_distances.element( i ).assign( distance );
|
||||
|
||||
} );
|
||||
|
||||
} )();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ClippingNode.ALPHA_TO_COVERAGE = 'alphaToCoverage';
|
||||
ClippingNode.DEFAULT = 'default';
|
||||
ClippingNode.HARDWARE = 'hardware';
|
||||
|
||||
export default ClippingNode;
|
||||
|
||||
/**
|
||||
* TSL function for setting up the default clipping logic.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @returns {ClippingNode}
|
||||
*/
|
||||
export const clipping = () => nodeObject( new ClippingNode() );
|
||||
|
||||
/**
|
||||
* TSL function for setting up alpha to coverage.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @returns {ClippingNode}
|
||||
*/
|
||||
export const clippingAlpha = () => nodeObject( new ClippingNode( ClippingNode.ALPHA_TO_COVERAGE ) );
|
||||
|
||||
/**
|
||||
* TSL function for setting up hardware-based clipping.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @returns {ClippingNode}
|
||||
*/
|
||||
export const hardwareClipping = () => nodeObject( new ClippingNode( ClippingNode.HARDWARE ) );
|
||||
189
app/node_modules/three/src/nodes/accessors/CubeTextureNode.js
generated
vendored
Normal file
189
app/node_modules/three/src/nodes/accessors/CubeTextureNode.js
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
import TextureNode from './TextureNode.js';
|
||||
import { reflectVector, refractVector } from './ReflectVector.js';
|
||||
import { nodeObject, nodeProxy, vec3 } from '../tsl/TSLBase.js';
|
||||
|
||||
import { CubeReflectionMapping, CubeRefractionMapping, WebGPUCoordinateSystem } from '../../constants.js';
|
||||
import { materialEnvRotation } from './MaterialProperties.js';
|
||||
|
||||
import { CubeTexture } from '../../textures/CubeTexture.js';
|
||||
|
||||
const EmptyTexture = /*@__PURE__*/ new CubeTexture();
|
||||
|
||||
/**
|
||||
* This type of uniform node represents a cube texture.
|
||||
*
|
||||
* @augments TextureNode
|
||||
*/
|
||||
class CubeTextureNode extends TextureNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'CubeTextureNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new cube texture node.
|
||||
*
|
||||
* @param {CubeTexture} value - The cube texture.
|
||||
* @param {?Node<vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
*/
|
||||
constructor( value, uvNode = null, levelNode = null, biasNode = null ) {
|
||||
|
||||
super( value, uvNode, levelNode, biasNode );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isCubeTextureNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'cubeTexture'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return 'cubeTexture';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a default uvs based on the mapping type of the cube texture.
|
||||
*
|
||||
* @return {Node<vec3>} The default uv attribute.
|
||||
*/
|
||||
getDefaultUV() {
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
if ( texture.mapping === CubeReflectionMapping ) {
|
||||
|
||||
return reflectVector;
|
||||
|
||||
} else if ( texture.mapping === CubeRefractionMapping ) {
|
||||
|
||||
return refractVector;
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'THREE.CubeTextureNode: Mapping "%s" not supported.', texture.mapping );
|
||||
|
||||
return vec3( 0, 0, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten with an empty implementation since the `updateMatrix` flag is ignored
|
||||
* for cube textures. The uv transformation matrix is not applied to cube textures.
|
||||
*
|
||||
* @param {boolean} value - The update toggle.
|
||||
*/
|
||||
setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for CubeTextureNode
|
||||
|
||||
/**
|
||||
* Setups the uv node. Depending on the backend as well as the texture type, it might be necessary
|
||||
* to modify the uv node for correct sampling.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {Node} uvNode - The uv node to setup.
|
||||
* @return {Node} The updated uv node.
|
||||
*/
|
||||
setupUV( builder, uvNode ) {
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) {
|
||||
|
||||
uvNode = vec3( uvNode.x.negate(), uvNode.yz );
|
||||
|
||||
}
|
||||
|
||||
return materialEnvRotation.mul( uvNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the uv code snippet.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {Node} cubeUV - The uv node to generate code for.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generateUV( builder, cubeUV ) {
|
||||
|
||||
return cubeUV.build( builder, 'vec3' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CubeTextureNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a cube texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {CubeTexture} value - The cube texture.
|
||||
* @param {?Node<vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
* @returns {CubeTextureNode}
|
||||
*/
|
||||
export const cubeTextureBase = /*@__PURE__*/ nodeProxy( CubeTextureNode ).setParameterLength( 1, 4 ).setName( 'cubeTexture' );
|
||||
|
||||
/**
|
||||
* TSL function for creating a cube texture uniform node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?CubeTexture|CubeTextureNode} [value=EmptyTexture] - The cube texture.
|
||||
* @param {?Node<vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
* @returns {CubeTextureNode}
|
||||
*/
|
||||
export const cubeTexture = ( value = EmptyTexture, uvNode = null, levelNode = null, biasNode = null ) => {
|
||||
|
||||
let textureNode;
|
||||
|
||||
if ( value && value.isCubeTextureNode === true ) {
|
||||
|
||||
textureNode = nodeObject( value.clone() );
|
||||
textureNode.referenceNode = value.getSelf(); // Ensure the reference is set to the original node
|
||||
|
||||
if ( uvNode !== null ) textureNode.uvNode = nodeObject( uvNode );
|
||||
if ( levelNode !== null ) textureNode.levelNode = nodeObject( levelNode );
|
||||
if ( biasNode !== null ) textureNode.biasNode = nodeObject( biasNode );
|
||||
|
||||
} else {
|
||||
|
||||
textureNode = cubeTextureBase( value, uvNode, levelNode, biasNode );
|
||||
|
||||
}
|
||||
|
||||
return textureNode;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* TSL function for creating a uniform cube texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?CubeTexture} [value=EmptyTexture] - The cube texture.
|
||||
* @returns {CubeTextureNode}
|
||||
*/
|
||||
export const uniformCubeTexture = ( value = EmptyTexture ) => cubeTextureBase( value );
|
||||
224
app/node_modules/three/src/nodes/accessors/InstanceNode.js
generated
vendored
Normal file
224
app/node_modules/three/src/nodes/accessors/InstanceNode.js
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { varyingProperty } from '../core/PropertyNode.js';
|
||||
import { instancedBufferAttribute, instancedDynamicBufferAttribute } from './BufferAttributeNode.js';
|
||||
import { normalLocal, transformNormal } from './Normal.js';
|
||||
import { positionLocal } from './Position.js';
|
||||
import { nodeProxy, vec3, mat4 } from '../tsl/TSLBase.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { buffer } from '../accessors/BufferNode.js';
|
||||
import { instanceIndex } from '../core/IndexNode.js';
|
||||
|
||||
import { InstancedInterleavedBuffer } from '../../core/InstancedInterleavedBuffer.js';
|
||||
import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js';
|
||||
import { DynamicDrawUsage } from '../../constants.js';
|
||||
|
||||
/**
|
||||
* This node implements the vertex shader logic which is required
|
||||
* when rendering 3D objects via instancing. The code makes sure
|
||||
* vertex positions, normals and colors can be modified via instanced
|
||||
* data.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class InstanceNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'InstanceNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance node.
|
||||
*
|
||||
* @param {number} count - The number of instances.
|
||||
* @param {InstancedBufferAttribute} instanceMatrix - Instanced buffer attribute representing the instance transformations.
|
||||
* @param {?InstancedBufferAttribute} instanceColor - Instanced buffer attribute representing the instance colors.
|
||||
*/
|
||||
constructor( count, instanceMatrix, instanceColor = null ) {
|
||||
|
||||
super( 'void' );
|
||||
|
||||
/**
|
||||
* The number of instances.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
this.count = count;
|
||||
|
||||
/**
|
||||
* Instanced buffer attribute representing the transformation of instances.
|
||||
*
|
||||
* @type {InstancedBufferAttribute}
|
||||
*/
|
||||
this.instanceMatrix = instanceMatrix;
|
||||
|
||||
/**
|
||||
* Instanced buffer attribute representing the color of instances.
|
||||
*
|
||||
* @type {InstancedBufferAttribute}
|
||||
*/
|
||||
this.instanceColor = instanceColor;
|
||||
|
||||
/**
|
||||
* The node that represents the instance matrix data.
|
||||
*
|
||||
* @type {?Node}
|
||||
*/
|
||||
this.instanceMatrixNode = null;
|
||||
|
||||
/**
|
||||
* The node that represents the instance color data.
|
||||
*
|
||||
* @type {?Node}
|
||||
* @default null
|
||||
*/
|
||||
this.instanceColorNode = null;
|
||||
|
||||
/**
|
||||
* The update type is set to `frame` since an update
|
||||
* of instanced buffer data must be checked per frame.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'frame'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.FRAME;
|
||||
|
||||
/**
|
||||
* A reference to a buffer that is used by `instanceMatrixNode`.
|
||||
*
|
||||
* @type {?InstancedInterleavedBuffer}
|
||||
*/
|
||||
this.buffer = null;
|
||||
|
||||
/**
|
||||
* A reference to a buffer that is used by `instanceColorNode`.
|
||||
*
|
||||
* @type {?InstancedBufferAttribute}
|
||||
*/
|
||||
this.bufferColor = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the internal buffers and nodes and assigns the transformed vertex data
|
||||
* to predefined node variables for accumulation. That follows the same patterns
|
||||
* like with morph and skinning nodes.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const { count, instanceMatrix, instanceColor } = this;
|
||||
|
||||
let { instanceMatrixNode, instanceColorNode } = this;
|
||||
|
||||
if ( instanceMatrixNode === null ) {
|
||||
|
||||
// Both WebGPU and WebGL backends have UBO max limited to 64kb. Matrix count number bigger than 1000 ( 16 * 4 * 1000 = 64kb ) will fallback to attribute.
|
||||
|
||||
if ( count <= 1000 ) {
|
||||
|
||||
instanceMatrixNode = buffer( instanceMatrix.array, 'mat4', Math.max( count, 1 ) ).element( instanceIndex );
|
||||
|
||||
} else {
|
||||
|
||||
const buffer = new InstancedInterleavedBuffer( instanceMatrix.array, 16, 1 );
|
||||
|
||||
this.buffer = buffer;
|
||||
|
||||
const bufferFn = instanceMatrix.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
|
||||
|
||||
const instanceBuffers = [
|
||||
// F.Signature -> bufferAttribute( array, type, stride, offset )
|
||||
bufferFn( buffer, 'vec4', 16, 0 ),
|
||||
bufferFn( buffer, 'vec4', 16, 4 ),
|
||||
bufferFn( buffer, 'vec4', 16, 8 ),
|
||||
bufferFn( buffer, 'vec4', 16, 12 )
|
||||
];
|
||||
|
||||
instanceMatrixNode = mat4( ...instanceBuffers );
|
||||
|
||||
}
|
||||
|
||||
this.instanceMatrixNode = instanceMatrixNode;
|
||||
|
||||
}
|
||||
|
||||
if ( instanceColor && instanceColorNode === null ) {
|
||||
|
||||
const buffer = new InstancedBufferAttribute( instanceColor.array, 3 );
|
||||
|
||||
const bufferFn = instanceColor.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
|
||||
|
||||
this.bufferColor = buffer;
|
||||
|
||||
instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) );
|
||||
|
||||
this.instanceColorNode = instanceColorNode;
|
||||
|
||||
}
|
||||
|
||||
// POSITION
|
||||
|
||||
const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz;
|
||||
positionLocal.assign( instancePosition );
|
||||
|
||||
// NORMAL
|
||||
|
||||
if ( builder.hasGeometryAttribute( 'normal' ) ) {
|
||||
|
||||
const instanceNormal = transformNormal( normalLocal, instanceMatrixNode );
|
||||
|
||||
// ASSIGNS
|
||||
|
||||
normalLocal.assign( instanceNormal );
|
||||
|
||||
}
|
||||
|
||||
// COLOR
|
||||
|
||||
if ( this.instanceColorNode !== null ) {
|
||||
|
||||
varyingProperty( 'vec3', 'vInstanceColor' ).assign( this.instanceColorNode );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the internal buffers required an update.
|
||||
*
|
||||
* @param {NodeFrame} frame - The current node frame.
|
||||
*/
|
||||
update( /*frame*/ ) {
|
||||
|
||||
if ( this.instanceMatrix.usage !== DynamicDrawUsage && this.buffer !== null && this.instanceMatrix.version !== this.buffer.version ) {
|
||||
|
||||
this.buffer.version = this.instanceMatrix.version;
|
||||
|
||||
}
|
||||
|
||||
if ( this.instanceColor && this.instanceColor.usage !== DynamicDrawUsage && this.bufferColor !== null && this.instanceColor.version !== this.bufferColor.version ) {
|
||||
|
||||
this.bufferColor.version = this.instanceColor.version;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default InstanceNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an instance node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {number} count - The number of instances.
|
||||
* @param {InstancedBufferAttribute} instanceMatrix - Instanced buffer attribute representing the instance transformations.
|
||||
* @param {?InstancedBufferAttribute} instanceColor - Instanced buffer attribute representing the instance colors.
|
||||
* @returns {InstanceNode}
|
||||
*/
|
||||
export const instance = /*@__PURE__*/ nodeProxy( InstanceNode ).setParameterLength( 2, 3 );
|
||||
50
app/node_modules/three/src/nodes/accessors/InstancedMeshNode.js
generated
vendored
Normal file
50
app/node_modules/three/src/nodes/accessors/InstancedMeshNode.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import InstanceNode from './InstanceNode.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* This is a special version of `InstanceNode` which requires the usage of {@link InstancedMesh}.
|
||||
* It allows an easier setup of the instance node.
|
||||
*
|
||||
* @augments InstanceNode
|
||||
*/
|
||||
class InstancedMeshNode extends InstanceNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'InstancedMeshNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instanced mesh node.
|
||||
*
|
||||
* @param {InstancedMesh} instancedMesh - The instanced mesh.
|
||||
*/
|
||||
constructor( instancedMesh ) {
|
||||
|
||||
const { count, instanceMatrix, instanceColor } = instancedMesh;
|
||||
|
||||
super( count, instanceMatrix, instanceColor );
|
||||
|
||||
/**
|
||||
* A reference to the instanced mesh.
|
||||
*
|
||||
* @type {InstancedMesh}
|
||||
*/
|
||||
this.instancedMesh = instancedMesh;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default InstancedMeshNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an instanced mesh node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {InstancedMesh} instancedMesh - The instancedMesh.
|
||||
* @returns {InstancedMeshNode}
|
||||
*/
|
||||
export const instancedMesh = /*@__PURE__*/ nodeProxy( InstancedMeshNode ).setParameterLength( 1 );
|
||||
129
app/node_modules/three/src/nodes/accessors/Lights.js
generated
vendored
Normal file
129
app/node_modules/three/src/nodes/accessors/Lights.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { renderGroup } from '../core/UniformGroupNode.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { cameraViewMatrix } from './Camera.js';
|
||||
import { positionWorld } from './Position.js';
|
||||
|
||||
let uniformsLib;
|
||||
|
||||
function getLightData( light ) {
|
||||
|
||||
uniformsLib = uniformsLib || new WeakMap();
|
||||
|
||||
let uniforms = uniformsLib.get( light );
|
||||
|
||||
if ( uniforms === undefined ) uniformsLib.set( light, uniforms = {} );
|
||||
|
||||
return uniforms;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TSL function for getting a shadow matrix uniform node for the given light.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Light} light -The light source.
|
||||
* @returns {UniformNode<mat4>} The shadow matrix uniform node.
|
||||
*/
|
||||
export function lightShadowMatrix( light ) {
|
||||
|
||||
const data = getLightData( light );
|
||||
|
||||
return data.shadowMatrix || ( data.shadowMatrix = uniform( 'mat4' ).setGroup( renderGroup ).onRenderUpdate( ( frame ) => {
|
||||
|
||||
if ( light.castShadow !== true || frame.renderer.shadowMap.enabled === false ) {
|
||||
|
||||
light.shadow.updateMatrices( light );
|
||||
|
||||
}
|
||||
|
||||
return light.shadow.matrix;
|
||||
|
||||
} ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TSL function for getting projected uv coordinates for the given light.
|
||||
* Relevant when using maps with spot lights.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Light} light -The light source.
|
||||
* @param {Node<vec3>} [position=positionWorld] -The position to project.
|
||||
* @returns {Node<vec3>} The projected uvs.
|
||||
*/
|
||||
export function lightProjectionUV( light, position = positionWorld ) {
|
||||
|
||||
const spotLightCoord = lightShadowMatrix( light ).mul( position );
|
||||
const projectionUV = spotLightCoord.xyz.div( spotLightCoord.w );
|
||||
|
||||
return projectionUV;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TSL function for getting the position in world space for the given light.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Light} light -The light source.
|
||||
* @returns {UniformNode<vec3>} The light's position in world space.
|
||||
*/
|
||||
export function lightPosition( light ) {
|
||||
|
||||
const data = getLightData( light );
|
||||
|
||||
return data.position || ( data.position = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( _, self ) => self.value.setFromMatrixPosition( light.matrixWorld ) ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TSL function for getting the light target position in world space for the given light.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Light} light -The light source.
|
||||
* @returns {UniformNode<vec3>} The light target position in world space.
|
||||
*/
|
||||
export function lightTargetPosition( light ) {
|
||||
|
||||
const data = getLightData( light );
|
||||
|
||||
return data.targetPosition || ( data.targetPosition = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( _, self ) => self.value.setFromMatrixPosition( light.target.matrixWorld ) ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TSL function for getting the position in view space for the given light.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Light} light - The light source.
|
||||
* @returns {UniformNode<vec3>} The light's position in view space.
|
||||
*/
|
||||
export function lightViewPosition( light ) {
|
||||
|
||||
const data = getLightData( light );
|
||||
|
||||
return data.viewPosition || ( data.viewPosition = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => {
|
||||
|
||||
self.value = self.value || new Vector3();
|
||||
self.value.setFromMatrixPosition( light.matrixWorld );
|
||||
|
||||
self.value.applyMatrix4( camera.matrixWorldInverse );
|
||||
|
||||
} ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TSL function for getting the light target direction for the given light.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Light} light -The light source.
|
||||
* @returns {Node<vec3>} The light's target direction.
|
||||
*/
|
||||
export const lightTargetDirection = ( light ) => cameraViewMatrix.transformDirection( lightPosition( light ).sub( lightTargetPosition( light ) ) );
|
||||
775
app/node_modules/three/src/nodes/accessors/MaterialNode.js
generated
vendored
Normal file
775
app/node_modules/three/src/nodes/accessors/MaterialNode.js
generated
vendored
Normal file
@@ -0,0 +1,775 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { reference } from './ReferenceNode.js';
|
||||
import { materialReference } from './MaterialReferenceNode.js';
|
||||
import { normalView } from './Normal.js';
|
||||
import { nodeImmutable, float, vec2, vec3, mat2 } from '../tsl/TSLBase.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { normalMap } from '../display/NormalMapNode.js';
|
||||
import { bumpMap } from '../display/BumpMapNode.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
|
||||
const _propertyCache = new Map();
|
||||
|
||||
/**
|
||||
* This class should simplify the node access to material properties.
|
||||
* It internal uses reference nodes to make sure changes to material
|
||||
* properties are automatically reflected to predefined TSL objects
|
||||
* like e.g. `materialColor`.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class MaterialNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'MaterialNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new material node.
|
||||
*
|
||||
* @param {string} scope - The scope defines what kind of material property is referred by the node.
|
||||
*/
|
||||
constructor( scope ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scope defines what material property is referred by the node.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cached reference node for the given property and type.
|
||||
*
|
||||
* @param {string} property - The name of the material property.
|
||||
* @param {string} type - The uniform type of the property.
|
||||
* @return {MaterialReferenceNode} A material reference node representing the property access.
|
||||
*/
|
||||
getCache( property, type ) {
|
||||
|
||||
let node = _propertyCache.get( property );
|
||||
|
||||
if ( node === undefined ) {
|
||||
|
||||
node = materialReference( property, type );
|
||||
|
||||
_propertyCache.set( property, node );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a float-typed material reference node for the given property name.
|
||||
*
|
||||
* @param {string} property - The name of the material property.
|
||||
* @return {MaterialReferenceNode<float>} A material reference node representing the property access.
|
||||
*/
|
||||
getFloat( property ) {
|
||||
|
||||
return this.getCache( property, 'float' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a color-typed material reference node for the given property name.
|
||||
*
|
||||
* @param {string} property - The name of the material property.
|
||||
* @return {MaterialReferenceNode<color>} A material reference node representing the property access.
|
||||
*/
|
||||
getColor( property ) {
|
||||
|
||||
return this.getCache( property, 'color' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a texture-typed material reference node for the given property name.
|
||||
*
|
||||
* @param {string} property - The name of the material property.
|
||||
* @return {MaterialReferenceNode} A material reference node representing the property access.
|
||||
*/
|
||||
getTexture( property ) {
|
||||
|
||||
return this.getCache( property === 'map' ? 'map' : property + 'Map', 'texture' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The node setup is done depending on the selected scope. Multiple material properties
|
||||
* might be grouped into a single node composition if they logically belong together.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node} The node representing the selected scope.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const material = builder.context.material;
|
||||
const scope = this.scope;
|
||||
|
||||
let node = null;
|
||||
|
||||
if ( scope === MaterialNode.COLOR ) {
|
||||
|
||||
const colorNode = material.color !== undefined ? this.getColor( scope ) : vec3();
|
||||
|
||||
if ( material.map && material.map.isTexture === true ) {
|
||||
|
||||
node = colorNode.mul( this.getTexture( 'map' ) );
|
||||
|
||||
} else {
|
||||
|
||||
node = colorNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.OPACITY ) {
|
||||
|
||||
const opacityNode = this.getFloat( scope );
|
||||
|
||||
if ( material.alphaMap && material.alphaMap.isTexture === true ) {
|
||||
|
||||
node = opacityNode.mul( this.getTexture( 'alpha' ) );
|
||||
|
||||
} else {
|
||||
|
||||
node = opacityNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.SPECULAR_STRENGTH ) {
|
||||
|
||||
if ( material.specularMap && material.specularMap.isTexture === true ) {
|
||||
|
||||
node = this.getTexture( 'specular' ).r;
|
||||
|
||||
} else {
|
||||
|
||||
node = float( 1 );
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.SPECULAR_INTENSITY ) {
|
||||
|
||||
const specularIntensityNode = this.getFloat( scope );
|
||||
|
||||
if ( material.specularIntensityMap && material.specularIntensityMap.isTexture === true ) {
|
||||
|
||||
node = specularIntensityNode.mul( this.getTexture( scope ).a );
|
||||
|
||||
} else {
|
||||
|
||||
node = specularIntensityNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.SPECULAR_COLOR ) {
|
||||
|
||||
const specularColorNode = this.getColor( scope );
|
||||
|
||||
if ( material.specularColorMap && material.specularColorMap.isTexture === true ) {
|
||||
|
||||
node = specularColorNode.mul( this.getTexture( scope ).rgb );
|
||||
|
||||
} else {
|
||||
|
||||
node = specularColorNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.ROUGHNESS ) { // TODO: cleanup similar branches
|
||||
|
||||
const roughnessNode = this.getFloat( scope );
|
||||
|
||||
if ( material.roughnessMap && material.roughnessMap.isTexture === true ) {
|
||||
|
||||
node = roughnessNode.mul( this.getTexture( scope ).g );
|
||||
|
||||
} else {
|
||||
|
||||
node = roughnessNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.METALNESS ) {
|
||||
|
||||
const metalnessNode = this.getFloat( scope );
|
||||
|
||||
if ( material.metalnessMap && material.metalnessMap.isTexture === true ) {
|
||||
|
||||
node = metalnessNode.mul( this.getTexture( scope ).b );
|
||||
|
||||
} else {
|
||||
|
||||
node = metalnessNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.EMISSIVE ) {
|
||||
|
||||
const emissiveIntensityNode = this.getFloat( 'emissiveIntensity' );
|
||||
const emissiveNode = this.getColor( scope ).mul( emissiveIntensityNode );
|
||||
|
||||
if ( material.emissiveMap && material.emissiveMap.isTexture === true ) {
|
||||
|
||||
node = emissiveNode.mul( this.getTexture( scope ) );
|
||||
|
||||
} else {
|
||||
|
||||
node = emissiveNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.NORMAL ) {
|
||||
|
||||
if ( material.normalMap ) {
|
||||
|
||||
node = normalMap( this.getTexture( 'normal' ), this.getCache( 'normalScale', 'vec2' ) );
|
||||
node.normalMapType = material.normalMapType;
|
||||
|
||||
} else if ( material.bumpMap ) {
|
||||
|
||||
node = bumpMap( this.getTexture( 'bump' ).r, this.getFloat( 'bumpScale' ) );
|
||||
|
||||
} else {
|
||||
|
||||
node = normalView;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.CLEARCOAT ) {
|
||||
|
||||
const clearcoatNode = this.getFloat( scope );
|
||||
|
||||
if ( material.clearcoatMap && material.clearcoatMap.isTexture === true ) {
|
||||
|
||||
node = clearcoatNode.mul( this.getTexture( scope ).r );
|
||||
|
||||
} else {
|
||||
|
||||
node = clearcoatNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.CLEARCOAT_ROUGHNESS ) {
|
||||
|
||||
const clearcoatRoughnessNode = this.getFloat( scope );
|
||||
|
||||
if ( material.clearcoatRoughnessMap && material.clearcoatRoughnessMap.isTexture === true ) {
|
||||
|
||||
node = clearcoatRoughnessNode.mul( this.getTexture( scope ).r );
|
||||
|
||||
} else {
|
||||
|
||||
node = clearcoatRoughnessNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.CLEARCOAT_NORMAL ) {
|
||||
|
||||
if ( material.clearcoatNormalMap ) {
|
||||
|
||||
node = normalMap( this.getTexture( scope ), this.getCache( scope + 'Scale', 'vec2' ) );
|
||||
|
||||
} else {
|
||||
|
||||
node = normalView;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.SHEEN ) {
|
||||
|
||||
const sheenNode = this.getColor( 'sheenColor' ).mul( this.getFloat( 'sheen' ) ); // Move this mul() to CPU
|
||||
|
||||
if ( material.sheenColorMap && material.sheenColorMap.isTexture === true ) {
|
||||
|
||||
node = sheenNode.mul( this.getTexture( 'sheenColor' ).rgb );
|
||||
|
||||
} else {
|
||||
|
||||
node = sheenNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.SHEEN_ROUGHNESS ) {
|
||||
|
||||
const sheenRoughnessNode = this.getFloat( scope );
|
||||
|
||||
if ( material.sheenRoughnessMap && material.sheenRoughnessMap.isTexture === true ) {
|
||||
|
||||
node = sheenRoughnessNode.mul( this.getTexture( scope ).a );
|
||||
|
||||
} else {
|
||||
|
||||
node = sheenRoughnessNode;
|
||||
|
||||
}
|
||||
|
||||
node = node.clamp( 0.07, 1.0 );
|
||||
|
||||
} else if ( scope === MaterialNode.ANISOTROPY ) {
|
||||
|
||||
if ( material.anisotropyMap && material.anisotropyMap.isTexture === true ) {
|
||||
|
||||
const anisotropyPolar = this.getTexture( scope );
|
||||
const anisotropyMat = mat2( materialAnisotropyVector.x, materialAnisotropyVector.y, materialAnisotropyVector.y.negate(), materialAnisotropyVector.x );
|
||||
|
||||
node = anisotropyMat.mul( anisotropyPolar.rg.mul( 2.0 ).sub( vec2( 1.0 ) ).normalize().mul( anisotropyPolar.b ) );
|
||||
|
||||
} else {
|
||||
|
||||
node = materialAnisotropyVector;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) {
|
||||
|
||||
const iridescenceThicknessMaximum = reference( '1', 'float', material.iridescenceThicknessRange );
|
||||
|
||||
if ( material.iridescenceThicknessMap ) {
|
||||
|
||||
const iridescenceThicknessMinimum = reference( '0', 'float', material.iridescenceThicknessRange );
|
||||
|
||||
node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( scope ).g ).add( iridescenceThicknessMinimum );
|
||||
|
||||
} else {
|
||||
|
||||
node = iridescenceThicknessMaximum;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.TRANSMISSION ) {
|
||||
|
||||
const transmissionNode = this.getFloat( scope );
|
||||
|
||||
if ( material.transmissionMap ) {
|
||||
|
||||
node = transmissionNode.mul( this.getTexture( scope ).r );
|
||||
|
||||
} else {
|
||||
|
||||
node = transmissionNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.THICKNESS ) {
|
||||
|
||||
const thicknessNode = this.getFloat( scope );
|
||||
|
||||
if ( material.thicknessMap ) {
|
||||
|
||||
node = thicknessNode.mul( this.getTexture( scope ).g );
|
||||
|
||||
} else {
|
||||
|
||||
node = thicknessNode;
|
||||
|
||||
}
|
||||
|
||||
} else if ( scope === MaterialNode.IOR ) {
|
||||
|
||||
node = this.getFloat( scope );
|
||||
|
||||
} else if ( scope === MaterialNode.LIGHT_MAP ) {
|
||||
|
||||
node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) );
|
||||
|
||||
} else if ( scope === MaterialNode.AO ) {
|
||||
|
||||
node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 );
|
||||
|
||||
} else if ( scope === MaterialNode.LINE_DASH_OFFSET ) {
|
||||
|
||||
node = ( material.dashOffset ) ? this.getFloat( scope ) : float( 0 );
|
||||
|
||||
} else {
|
||||
|
||||
const outputType = this.getNodeType( builder );
|
||||
|
||||
node = this.getCache( scope, outputType );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MaterialNode.ALPHA_TEST = 'alphaTest';
|
||||
MaterialNode.COLOR = 'color';
|
||||
MaterialNode.OPACITY = 'opacity';
|
||||
MaterialNode.SHININESS = 'shininess';
|
||||
MaterialNode.SPECULAR = 'specular';
|
||||
MaterialNode.SPECULAR_STRENGTH = 'specularStrength';
|
||||
MaterialNode.SPECULAR_INTENSITY = 'specularIntensity';
|
||||
MaterialNode.SPECULAR_COLOR = 'specularColor';
|
||||
MaterialNode.REFLECTIVITY = 'reflectivity';
|
||||
MaterialNode.ROUGHNESS = 'roughness';
|
||||
MaterialNode.METALNESS = 'metalness';
|
||||
MaterialNode.NORMAL = 'normal';
|
||||
MaterialNode.CLEARCOAT = 'clearcoat';
|
||||
MaterialNode.CLEARCOAT_ROUGHNESS = 'clearcoatRoughness';
|
||||
MaterialNode.CLEARCOAT_NORMAL = 'clearcoatNormal';
|
||||
MaterialNode.EMISSIVE = 'emissive';
|
||||
MaterialNode.ROTATION = 'rotation';
|
||||
MaterialNode.SHEEN = 'sheen';
|
||||
MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness';
|
||||
MaterialNode.ANISOTROPY = 'anisotropy';
|
||||
MaterialNode.IRIDESCENCE = 'iridescence';
|
||||
MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR';
|
||||
MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness';
|
||||
MaterialNode.IOR = 'ior';
|
||||
MaterialNode.TRANSMISSION = 'transmission';
|
||||
MaterialNode.THICKNESS = 'thickness';
|
||||
MaterialNode.ATTENUATION_DISTANCE = 'attenuationDistance';
|
||||
MaterialNode.ATTENUATION_COLOR = 'attenuationColor';
|
||||
MaterialNode.LINE_SCALE = 'scale';
|
||||
MaterialNode.LINE_DASH_SIZE = 'dashSize';
|
||||
MaterialNode.LINE_GAP_SIZE = 'gapSize';
|
||||
MaterialNode.LINE_WIDTH = 'linewidth';
|
||||
MaterialNode.LINE_DASH_OFFSET = 'dashOffset';
|
||||
MaterialNode.POINT_SIZE = 'size';
|
||||
MaterialNode.DISPERSION = 'dispersion';
|
||||
MaterialNode.LIGHT_MAP = 'light';
|
||||
MaterialNode.AO = 'ao';
|
||||
|
||||
export default MaterialNode;
|
||||
|
||||
/**
|
||||
* TSL object that represents alpha test of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialAlphaTest = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ALPHA_TEST );
|
||||
|
||||
/**
|
||||
* TSL object that represents the diffuse color of the current material.
|
||||
* The value is composed via `color` * `map`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.COLOR );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shininess of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialShininess = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHININESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the emissive color of the current material.
|
||||
* The value is composed via `emissive` * `emissiveIntensity` * `emissiveMap`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialEmissive = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.EMISSIVE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the opacity of the current material.
|
||||
* The value is composed via `opacity` * `alphaMap`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialOpacity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.OPACITY );
|
||||
|
||||
/**
|
||||
* TSL object that represents the specular of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialSpecular = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR );
|
||||
|
||||
/**
|
||||
* TSL object that represents the specular intensity of the current material.
|
||||
* The value is composed via `specularIntensity` * `specularMap.a`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_INTENSITY );
|
||||
|
||||
/**
|
||||
* TSL object that represents the specular color of the current material.
|
||||
* The value is composed via `specularColor` * `specularMap.rgb`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR );
|
||||
|
||||
/**
|
||||
* TSL object that represents the specular strength of the current material.
|
||||
* The value is composed via `specularMap.r`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialSpecularStrength = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH );
|
||||
|
||||
/**
|
||||
* TSL object that represents the reflectivity of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY );
|
||||
|
||||
/**
|
||||
* TSL object that represents the roughness of the current material.
|
||||
* The value is composed via `roughness` * `roughnessMap.g`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the metalness of the current material.
|
||||
* The value is composed via `metalness` * `metalnessMap.b`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.METALNESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the normal of the current material.
|
||||
* The value will be either `normalMap` * `normalScale`, `bumpMap` * `bumpScale` or `normalView`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL );
|
||||
|
||||
/**
|
||||
* TSL object that represents the clearcoat of the current material.
|
||||
* The value is composed via `clearcoat` * `clearcoatMap.r`
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT );
|
||||
|
||||
/**
|
||||
* TSL object that represents the clearcoat roughness of the current material.
|
||||
* The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_ROUGHNESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the clearcoat normal of the current material.
|
||||
* The value will be either `clearcoatNormalMap` or `normalView`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL );
|
||||
|
||||
/**
|
||||
* TSL object that represents the rotation of the current sprite material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialRotation = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROTATION );
|
||||
|
||||
/**
|
||||
* TSL object that represents the sheen color of the current material.
|
||||
* The value is composed via `sheen` * `sheenColor` * `sheenColorMap`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN );
|
||||
|
||||
/**
|
||||
* TSL object that represents the sheen roughness of the current material.
|
||||
* The value is composed via `sheenRoughness` * `sheenRoughnessMap.a`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialSheenRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the anisotropy of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec2>}
|
||||
*/
|
||||
export const materialAnisotropy = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ANISOTROPY );
|
||||
|
||||
/**
|
||||
* TSL object that represents the iridescence of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialIridescence = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the iridescence IOR of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialIridescenceIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR );
|
||||
|
||||
/**
|
||||
* TSL object that represents the iridescence thickness of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialIridescenceThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the transmission of the current material.
|
||||
* The value is composed via `transmission` * `transmissionMap.r`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialTransmission = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.TRANSMISSION );
|
||||
|
||||
/**
|
||||
* TSL object that represents the thickness of the current material.
|
||||
* The value is composed via `thickness` * `thicknessMap.g`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.THICKNESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the IOR of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IOR );
|
||||
|
||||
/**
|
||||
* TSL object that represents the attenuation distance of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialAttenuationDistance = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_DISTANCE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the attenuation color of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialAttenuationColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_COLOR );
|
||||
|
||||
/**
|
||||
* TSL object that represents the scale of the current dashed line material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialLineScale = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_SCALE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the dash size of the current dashed line material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialLineDashSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_SIZE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the gap size of the current dashed line material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialLineGapSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_GAP_SIZE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the line width of the current line material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialLineWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_WIDTH );
|
||||
|
||||
/**
|
||||
* TSL object that represents the dash offset of the current line material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialLineDashOffset = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_OFFSET );
|
||||
|
||||
/**
|
||||
* TSL object that represents the point size of the current points material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialPointSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.POINT_SIZE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the dispersion of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialDispersion = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.DISPERSION );
|
||||
|
||||
/**
|
||||
* TSL object that represents the light map of the current material.
|
||||
* The value is composed via `lightMapIntensity` * `lightMap.rgb`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LIGHT_MAP );
|
||||
|
||||
/**
|
||||
* TSL object that represents the ambient occlusion map of the current material.
|
||||
* The value is composed via `aoMap.r` - 1 * `aoMapIntensity` + 1.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialAO = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO );
|
||||
|
||||
/**
|
||||
* TSL object that represents the anisotropy vector of the current material.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec2>}
|
||||
*/
|
||||
export const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).onReference( function ( frame ) {
|
||||
|
||||
return frame.material;
|
||||
|
||||
} ).onRenderUpdate( function ( { material } ) {
|
||||
|
||||
this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) );
|
||||
|
||||
} );
|
||||
59
app/node_modules/three/src/nodes/accessors/MaterialProperties.js
generated
vendored
Normal file
59
app/node_modules/three/src/nodes/accessors/MaterialProperties.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Euler } from '../../math/Euler.js';
|
||||
import { Matrix4 } from '../../math/Matrix4.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
|
||||
const _e1 = /*@__PURE__*/ new Euler();
|
||||
const _m1 = /*@__PURE__*/ new Matrix4();
|
||||
|
||||
/**
|
||||
* TSL object that represents the refraction ratio of the material used for rendering the current object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<float>}
|
||||
*/
|
||||
export const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onObjectUpdate( ( { material } ) => material.refractionRatio );
|
||||
|
||||
/**
|
||||
* TSL object that represents the intensity of environment maps of PBR materials.
|
||||
* When `material.envMap` is set, the value is `material.envMapIntensity` otherwise `scene.environmentIntensity`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
export const materialEnvIntensity = /*@__PURE__*/ uniform( 1 ).onReference( ( { material } ) => material ).onObjectUpdate( function ( { material, scene } ) {
|
||||
|
||||
return material.envMap ? material.envMapIntensity : scene.environmentIntensity;
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* TSL object that represents the rotation of environment maps.
|
||||
* When `material.envMap` is set, the value is `material.envMapRotation`. `scene.environmentRotation` controls the
|
||||
* rotation of `scene.environment` instead.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat4>}
|
||||
*/
|
||||
export const materialEnvRotation = /*@__PURE__*/ uniform( new Matrix4() ).onReference( function ( frame ) {
|
||||
|
||||
return frame.material;
|
||||
|
||||
} ).onObjectUpdate( function ( { material, scene } ) {
|
||||
|
||||
const rotation = ( scene.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation;
|
||||
|
||||
if ( rotation ) {
|
||||
|
||||
_e1.copy( rotation );
|
||||
|
||||
_m1.makeRotationFromEuler( _e1 );
|
||||
|
||||
} else {
|
||||
|
||||
_m1.identity();
|
||||
|
||||
}
|
||||
|
||||
return _m1;
|
||||
|
||||
} );
|
||||
85
app/node_modules/three/src/nodes/accessors/MaterialReferenceNode.js
generated
vendored
Normal file
85
app/node_modules/three/src/nodes/accessors/MaterialReferenceNode.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
import ReferenceNode from './ReferenceNode.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* This node is a special type of reference node which is intended
|
||||
* for linking material properties with node values.
|
||||
* ```js
|
||||
* const opacityNode = materialReference( 'opacity', 'float', material );
|
||||
* ```
|
||||
* When changing `material.opacity`, the node value of `opacityNode` will
|
||||
* automatically be updated.
|
||||
*
|
||||
* @augments ReferenceNode
|
||||
*/
|
||||
class MaterialReferenceNode extends ReferenceNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'MaterialReferenceNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new material reference node.
|
||||
*
|
||||
* @param {string} property - The name of the property the node refers to.
|
||||
* @param {string} inputType - The uniform type that should be used to represent the property value.
|
||||
* @param {?Material} [material=null] - The material the property belongs to. When no material is set,
|
||||
* the node refers to the material of the current rendered object.
|
||||
*/
|
||||
constructor( property, inputType, material = null ) {
|
||||
|
||||
super( property, inputType, material );
|
||||
|
||||
/**
|
||||
* The material the property belongs to. When no material is set,
|
||||
* the node refers to the material of the current rendered object.
|
||||
*
|
||||
* @type {?Material}
|
||||
* @default null
|
||||
*/
|
||||
this.material = material;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isMaterialReferenceNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the reference based on the given state. The state is only evaluated
|
||||
* {@link MaterialReferenceNode#material} is not set.
|
||||
*
|
||||
* @param {(NodeFrame|NodeBuilder)} state - The current state.
|
||||
* @return {Object} The updated reference.
|
||||
*/
|
||||
updateReference( state ) {
|
||||
|
||||
this.reference = this.material !== null ? this.material : state.material;
|
||||
|
||||
return this.reference;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MaterialReferenceNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a material reference node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the property the node refers to.
|
||||
* @param {string} type - The uniform type that should be used to represent the property value.
|
||||
* @param {?Material} [material=null] - The material the property belongs to.
|
||||
* When no material is set, the node refers to the material of the current rendered object.
|
||||
* @returns {MaterialReferenceNode}
|
||||
*/
|
||||
export const materialReference = ( name, type, material = null ) => nodeObject( new MaterialReferenceNode( name, type, material ) );
|
||||
184
app/node_modules/three/src/nodes/accessors/ModelNode.js
generated
vendored
Normal file
184
app/node_modules/three/src/nodes/accessors/ModelNode.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
import Object3DNode from './Object3DNode.js';
|
||||
import { Fn, nodeImmutable } from '../tsl/TSLBase.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
|
||||
import { Matrix4 } from '../../math/Matrix4.js';
|
||||
import { cameraViewMatrix } from './Camera.js';
|
||||
import { Matrix3 } from '../../math/Matrix3.js';
|
||||
|
||||
/**
|
||||
* This type of node is a specialized version of `Object3DNode`
|
||||
* with larger set of model related metrics. Unlike `Object3DNode`,
|
||||
* `ModelNode` extracts the reference to the 3D object from the
|
||||
* current node frame state.
|
||||
*
|
||||
* @augments Object3DNode
|
||||
*/
|
||||
class ModelNode extends Object3DNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ModelNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new object model node.
|
||||
*
|
||||
* @param {('position'|'viewPosition'|'direction'|'scale'|'worldMatrix')} scope - The node represents a different type of transformation depending on the scope.
|
||||
*/
|
||||
constructor( scope ) {
|
||||
|
||||
super( scope );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the model reference from the frame state and then
|
||||
* updates the uniform value depending on the scope.
|
||||
*
|
||||
* @param {NodeFrame} frame - The current node frame.
|
||||
*/
|
||||
update( frame ) {
|
||||
|
||||
this.object3d = frame.object;
|
||||
|
||||
super.update( frame );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ModelNode;
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's direction in world space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ModelNode<vec3>}
|
||||
*/
|
||||
export const modelDirection = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.DIRECTION );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's world matrix.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ModelNode<mat4>}
|
||||
*/
|
||||
export const modelWorldMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's position in world space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ModelNode<vec3>}
|
||||
*/
|
||||
export const modelPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.POSITION );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's scale in world space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ModelNode<vec3>}
|
||||
*/
|
||||
export const modelScale = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.SCALE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's position in view/camera space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ModelNode<vec3>}
|
||||
*/
|
||||
export const modelViewPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_POSITION );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's radius.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ModelNode<float>}
|
||||
*/
|
||||
export const modelRadius = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.RADIUS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's normal matrix.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat3>}
|
||||
*/
|
||||
export const modelNormalMatrix = /*@__PURE__*/ uniform( new Matrix3() ).onObjectUpdate( ( { object }, self ) => self.value.getNormalMatrix( object.matrixWorld ) );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's inverse world matrix.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformNode<mat4>}
|
||||
*/
|
||||
export const modelWorldMatrixInverse = /*@__PURE__*/ uniform( new Matrix4() ).onObjectUpdate( ( { object }, self ) => self.value.copy( object.matrixWorld ).invert() );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's model view matrix.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat4>}
|
||||
*/
|
||||
export const modelViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
return builder.renderer.overrideNodes.modelViewMatrix || mediumpModelViewMatrix;
|
||||
|
||||
} ).once() )().toVar( 'modelViewMatrix' );
|
||||
|
||||
// GPU Precision
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's model view in `mediump` precision.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat4>}
|
||||
*/
|
||||
export const mediumpModelViewMatrix = /*@__PURE__*/ cameraViewMatrix.mul( modelWorldMatrix );
|
||||
|
||||
// CPU Precision
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's model view in `highp` precision
|
||||
* which is achieved by computing the matrix in JS and not in the shader.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat4>}
|
||||
*/
|
||||
export const highpModelViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
builder.context.isHighPrecisionModelViewMatrix = true;
|
||||
|
||||
return uniform( 'mat4' ).onObjectUpdate( ( { object, camera } ) => {
|
||||
|
||||
return object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
|
||||
|
||||
} );
|
||||
|
||||
} ).once() )().toVar( 'highpModelViewMatrix' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the object's model normal view in `highp` precision
|
||||
* which is achieved by computing the matrix in JS and not in the shader.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<mat3>}
|
||||
*/
|
||||
export const highpModelNormalViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
const isHighPrecisionModelViewMatrix = builder.context.isHighPrecisionModelViewMatrix;
|
||||
|
||||
return uniform( 'mat3' ).onObjectUpdate( ( { object, camera } ) => {
|
||||
|
||||
if ( isHighPrecisionModelViewMatrix !== true ) {
|
||||
|
||||
object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
|
||||
|
||||
}
|
||||
|
||||
return object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
|
||||
|
||||
} );
|
||||
|
||||
} ).once() )().toVar( 'highpModelNormalViewMatrix' );
|
||||
13
app/node_modules/three/src/nodes/accessors/ModelViewProjectionNode.js
generated
vendored
Normal file
13
app/node_modules/three/src/nodes/accessors/ModelViewProjectionNode.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Fn } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* TSL object that represents the position in clip space after the model-view-projection transform of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {VaryingNode<vec4>}
|
||||
*/
|
||||
export const modelViewProjection = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
return builder.context.setupModelViewProjection();
|
||||
|
||||
}, 'vec4' ).once() )().toVarying( 'v_modelViewProjection' );
|
||||
310
app/node_modules/three/src/nodes/accessors/MorphNode.js
generated
vendored
Normal file
310
app/node_modules/three/src/nodes/accessors/MorphNode.js
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { float, nodeProxy, Fn, ivec2, int, If } from '../tsl/TSLBase.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { reference } from './ReferenceNode.js';
|
||||
import { positionLocal } from './Position.js';
|
||||
import { normalLocal } from './Normal.js';
|
||||
import { textureLoad } from './TextureNode.js';
|
||||
import { instanceIndex, vertexIndex } from '../core/IndexNode.js';
|
||||
import { Loop } from '../utils/LoopNode.js';
|
||||
|
||||
import { DataArrayTexture } from '../../textures/DataArrayTexture.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
import { FloatType } from '../../constants.js';
|
||||
|
||||
const _morphTextures = /*@__PURE__*/ new WeakMap();
|
||||
const _morphVec4 = /*@__PURE__*/ new Vector4();
|
||||
|
||||
const getMorph = /*@__PURE__*/ Fn( ( { bufferMap, influence, stride, width, depth, offset } ) => {
|
||||
|
||||
const texelIndex = int( vertexIndex ).mul( stride ).add( offset );
|
||||
|
||||
const y = texelIndex.div( width );
|
||||
const x = texelIndex.sub( y.mul( width ) );
|
||||
|
||||
const bufferAttrib = textureLoad( bufferMap, ivec2( x, y ) ).depth( depth ).xyz;
|
||||
|
||||
return bufferAttrib.mul( influence );
|
||||
|
||||
} );
|
||||
|
||||
function getEntry( geometry ) {
|
||||
|
||||
const hasMorphPosition = geometry.morphAttributes.position !== undefined;
|
||||
const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
|
||||
const hasMorphColors = geometry.morphAttributes.color !== undefined;
|
||||
|
||||
// instead of using attributes, the WebGL 2 code path encodes morph targets
|
||||
// into an array of data textures. Each layer represents a single morph target.
|
||||
|
||||
const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
|
||||
const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
|
||||
|
||||
let entry = _morphTextures.get( geometry );
|
||||
|
||||
if ( entry === undefined || entry.count !== morphTargetsCount ) {
|
||||
|
||||
if ( entry !== undefined ) entry.texture.dispose();
|
||||
|
||||
const morphTargets = geometry.morphAttributes.position || [];
|
||||
const morphNormals = geometry.morphAttributes.normal || [];
|
||||
const morphColors = geometry.morphAttributes.color || [];
|
||||
|
||||
let vertexDataCount = 0;
|
||||
|
||||
if ( hasMorphPosition === true ) vertexDataCount = 1;
|
||||
if ( hasMorphNormals === true ) vertexDataCount = 2;
|
||||
if ( hasMorphColors === true ) vertexDataCount = 3;
|
||||
|
||||
let width = geometry.attributes.position.count * vertexDataCount;
|
||||
let height = 1;
|
||||
|
||||
const maxTextureSize = 4096; // @TODO: Use 'capabilities.maxTextureSize'
|
||||
|
||||
if ( width > maxTextureSize ) {
|
||||
|
||||
height = Math.ceil( width / maxTextureSize );
|
||||
width = maxTextureSize;
|
||||
|
||||
}
|
||||
|
||||
const buffer = new Float32Array( width * height * 4 * morphTargetsCount );
|
||||
|
||||
const bufferTexture = new DataArrayTexture( buffer, width, height, morphTargetsCount );
|
||||
bufferTexture.type = FloatType;
|
||||
bufferTexture.needsUpdate = true;
|
||||
|
||||
// fill buffer
|
||||
|
||||
const vertexDataStride = vertexDataCount * 4;
|
||||
|
||||
for ( let i = 0; i < morphTargetsCount; i ++ ) {
|
||||
|
||||
const morphTarget = morphTargets[ i ];
|
||||
const morphNormal = morphNormals[ i ];
|
||||
const morphColor = morphColors[ i ];
|
||||
|
||||
const offset = width * height * 4 * i;
|
||||
|
||||
for ( let j = 0; j < morphTarget.count; j ++ ) {
|
||||
|
||||
const stride = j * vertexDataStride;
|
||||
|
||||
if ( hasMorphPosition === true ) {
|
||||
|
||||
_morphVec4.fromBufferAttribute( morphTarget, j );
|
||||
|
||||
buffer[ offset + stride + 0 ] = _morphVec4.x;
|
||||
buffer[ offset + stride + 1 ] = _morphVec4.y;
|
||||
buffer[ offset + stride + 2 ] = _morphVec4.z;
|
||||
buffer[ offset + stride + 3 ] = 0;
|
||||
|
||||
}
|
||||
|
||||
if ( hasMorphNormals === true ) {
|
||||
|
||||
_morphVec4.fromBufferAttribute( morphNormal, j );
|
||||
|
||||
buffer[ offset + stride + 4 ] = _morphVec4.x;
|
||||
buffer[ offset + stride + 5 ] = _morphVec4.y;
|
||||
buffer[ offset + stride + 6 ] = _morphVec4.z;
|
||||
buffer[ offset + stride + 7 ] = 0;
|
||||
|
||||
}
|
||||
|
||||
if ( hasMorphColors === true ) {
|
||||
|
||||
_morphVec4.fromBufferAttribute( morphColor, j );
|
||||
|
||||
buffer[ offset + stride + 8 ] = _morphVec4.x;
|
||||
buffer[ offset + stride + 9 ] = _morphVec4.y;
|
||||
buffer[ offset + stride + 10 ] = _morphVec4.z;
|
||||
buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? _morphVec4.w : 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
entry = {
|
||||
count: morphTargetsCount,
|
||||
texture: bufferTexture,
|
||||
stride: vertexDataCount,
|
||||
size: new Vector2( width, height )
|
||||
};
|
||||
|
||||
_morphTextures.set( geometry, entry );
|
||||
|
||||
function disposeTexture() {
|
||||
|
||||
bufferTexture.dispose();
|
||||
|
||||
_morphTextures.delete( geometry );
|
||||
|
||||
geometry.removeEventListener( 'dispose', disposeTexture );
|
||||
|
||||
}
|
||||
|
||||
geometry.addEventListener( 'dispose', disposeTexture );
|
||||
|
||||
}
|
||||
|
||||
return entry;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This node implements the vertex transformation shader logic which is required
|
||||
* for morph target animation.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class MorphNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'MorphNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new morph node.
|
||||
*
|
||||
* @param {Mesh} mesh - The mesh holding the morph targets.
|
||||
*/
|
||||
constructor( mesh ) {
|
||||
|
||||
super( 'void' );
|
||||
|
||||
/**
|
||||
* The mesh holding the morph targets.
|
||||
*
|
||||
* @type {Mesh}
|
||||
*/
|
||||
this.mesh = mesh;
|
||||
|
||||
/**
|
||||
* A uniform node which represents the morph base influence value.
|
||||
*
|
||||
* @type {UniformNode<float>}
|
||||
*/
|
||||
this.morphBaseInfluence = uniform( 1 );
|
||||
|
||||
/**
|
||||
* The update type overwritten since morph nodes are updated per object.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.updateType = NodeUpdateType.OBJECT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the morph node by assigning the transformed vertex data to predefined node variables.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const { geometry } = builder;
|
||||
|
||||
const hasMorphPosition = geometry.morphAttributes.position !== undefined;
|
||||
const hasMorphNormals = geometry.hasAttribute( 'normal' ) && geometry.morphAttributes.normal !== undefined;
|
||||
|
||||
const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
|
||||
const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
|
||||
|
||||
// nodes
|
||||
|
||||
const { texture: bufferMap, stride, size } = getEntry( geometry );
|
||||
|
||||
if ( hasMorphPosition === true ) positionLocal.mulAssign( this.morphBaseInfluence );
|
||||
if ( hasMorphNormals === true ) normalLocal.mulAssign( this.morphBaseInfluence );
|
||||
|
||||
const width = int( size.width );
|
||||
|
||||
Loop( morphTargetsCount, ( { i } ) => {
|
||||
|
||||
const influence = float( 0 ).toVar();
|
||||
|
||||
if ( this.mesh.count > 1 && ( this.mesh.morphTexture !== null && this.mesh.morphTexture !== undefined ) ) {
|
||||
|
||||
influence.assign( textureLoad( this.mesh.morphTexture, ivec2( int( i ).add( 1 ), int( instanceIndex ) ) ).r );
|
||||
|
||||
} else {
|
||||
|
||||
influence.assign( reference( 'morphTargetInfluences', 'float' ).element( i ).toVar() );
|
||||
|
||||
}
|
||||
|
||||
If( influence.notEqual( 0 ), () => {
|
||||
|
||||
if ( hasMorphPosition === true ) {
|
||||
|
||||
positionLocal.addAssign( getMorph( {
|
||||
bufferMap,
|
||||
influence,
|
||||
stride,
|
||||
width,
|
||||
depth: i,
|
||||
offset: int( 0 )
|
||||
} ) );
|
||||
|
||||
}
|
||||
|
||||
if ( hasMorphNormals === true ) {
|
||||
|
||||
normalLocal.addAssign( getMorph( {
|
||||
bufferMap,
|
||||
influence,
|
||||
stride,
|
||||
width,
|
||||
depth: i,
|
||||
offset: int( 1 )
|
||||
} ) );
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the morphed mesh by updating the base influence.
|
||||
*
|
||||
* @param {NodeFrame} frame - The current node frame.
|
||||
*/
|
||||
update( /*frame*/ ) {
|
||||
|
||||
const morphBaseInfluence = this.morphBaseInfluence;
|
||||
|
||||
if ( this.mesh.geometry.morphTargetsRelative ) {
|
||||
|
||||
morphBaseInfluence.value = 1;
|
||||
|
||||
} else {
|
||||
|
||||
morphBaseInfluence.value = 1 - this.mesh.morphTargetInfluences.reduce( ( a, b ) => a + b, 0 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MorphNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a morph node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Mesh} mesh - The mesh holding the morph targets.
|
||||
* @returns {MorphNode}
|
||||
*/
|
||||
export const morphReference = /*@__PURE__*/ nodeProxy( MorphNode ).setParameterLength( 1 );
|
||||
242
app/node_modules/three/src/nodes/accessors/Normal.js
generated
vendored
Normal file
242
app/node_modules/three/src/nodes/accessors/Normal.js
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { cameraViewMatrix } from './Camera.js';
|
||||
import { modelNormalMatrix, modelWorldMatrix } from './ModelNode.js';
|
||||
import { mat3, vec3, Fn } from '../tsl/TSLBase.js';
|
||||
import { positionView } from './Position.js';
|
||||
import { directionToFaceDirection } from '../display/FrontFacingNode.js';
|
||||
|
||||
/**
|
||||
* TSL object that represents the normal attribute of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalGeometry = /*@__PURE__*/ attribute( 'normal', 'vec3' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex normal in local space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalLocal = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
if ( builder.geometry.hasAttribute( 'normal' ) === false ) {
|
||||
|
||||
console.warn( 'THREE.TSL: Vertex attribute "normal" not found on geometry.' );
|
||||
|
||||
return vec3( 0, 1, 0 );
|
||||
|
||||
}
|
||||
|
||||
return normalGeometry;
|
||||
|
||||
}, 'vec3' ).once() )().toVar( 'normalLocal' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the flat vertex normal in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalFlat = /*@__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex normal in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalViewGeometry = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
let node;
|
||||
|
||||
if ( builder.material.flatShading === true ) {
|
||||
|
||||
node = normalFlat;
|
||||
|
||||
} else {
|
||||
|
||||
node = transformNormalToView( normalLocal ).toVarying( 'v_normalViewGeometry' ).normalize();
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}, 'vec3' ).once() )().toVar( 'normalViewGeometry' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex normal in world space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalWorldGeometry = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
let normal = normalViewGeometry.transformDirection( cameraViewMatrix );
|
||||
|
||||
if ( builder.material.flatShading !== true ) {
|
||||
|
||||
normal = normal.toVarying( 'v_normalWorldGeometry' );
|
||||
|
||||
}
|
||||
|
||||
return normal.normalize().toVar( 'normalWorldGeometry' );
|
||||
|
||||
}, 'vec3' ).once() )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the transformed vertex normal in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalView = /*@__PURE__*/ ( Fn( ( { subBuildFn, material, context } ) => {
|
||||
|
||||
let node;
|
||||
|
||||
if ( subBuildFn === 'NORMAL' || subBuildFn === 'VERTEX' ) {
|
||||
|
||||
node = normalViewGeometry;
|
||||
|
||||
if ( material.flatShading !== true ) {
|
||||
|
||||
node = directionToFaceDirection( node );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode)
|
||||
|
||||
node = context.setupNormal().context( { getUV: null } );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}, 'vec3' ).once( [ 'NORMAL', 'VERTEX' ] ) )().toVar( 'normalView' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the transformed vertex normal in world space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const normalWorld = /*@__PURE__*/ normalView.transformDirection( cameraViewMatrix ).toVar( 'normalWorld' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the transformed clearcoat vertex normal in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const clearcoatNormalView = /*@__PURE__*/ ( Fn( ( { subBuildFn, context } ) => {
|
||||
|
||||
let node;
|
||||
|
||||
if ( subBuildFn === 'NORMAL' || subBuildFn === 'VERTEX' ) {
|
||||
|
||||
node = normalView;
|
||||
|
||||
} else {
|
||||
|
||||
// Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode)
|
||||
|
||||
node = context.setupClearcoatNormal().context( { getUV: null } );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}, 'vec3' ).once( [ 'NORMAL', 'VERTEX' ] ) )().toVar( 'clearcoatNormalView' );
|
||||
|
||||
/**
|
||||
* Transforms the normal with the given matrix.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} normal - The normal.
|
||||
* @param {Node<mat3>} [matrix=modelWorldMatrix] - The matrix.
|
||||
* @return {Node<vec3>} The transformed normal.
|
||||
*/
|
||||
export const transformNormal = /*@__PURE__*/ Fn( ( [ normal, matrix = modelWorldMatrix ] ) => {
|
||||
|
||||
const m = mat3( matrix );
|
||||
|
||||
const transformedNormal = normal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) );
|
||||
|
||||
return m.mul( transformedNormal ).xyz;
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Transforms the given normal from local to view space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} normal - The normal.
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node<vec3>} The transformed normal.
|
||||
*/
|
||||
export const transformNormalToView = /*@__PURE__*/ Fn( ( [ normal ], builder ) => {
|
||||
|
||||
const modelNormalViewMatrix = builder.renderer.overrideNodes.modelNormalViewMatrix;
|
||||
|
||||
if ( modelNormalViewMatrix !== null ) {
|
||||
|
||||
return modelNormalViewMatrix.transformDirection( normal );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const transformedNormal = modelNormalMatrix.mul( normal );
|
||||
|
||||
return cameraViewMatrix.transformDirection( transformedNormal );
|
||||
|
||||
} );
|
||||
|
||||
// Deprecated
|
||||
|
||||
/**
|
||||
* TSL object that represents the transformed vertex normal in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
* @deprecated since r178. Use `normalView` instead.
|
||||
*/
|
||||
export const transformedNormalView = ( Fn( () => { // @deprecated, r177
|
||||
|
||||
console.warn( 'THREE.TSL: "transformedNormalView" is deprecated. Use "normalView" instead.' );
|
||||
return normalView;
|
||||
|
||||
} ).once( [ 'NORMAL', 'VERTEX' ] ) )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the transformed vertex normal in world space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
* @deprecated since r178. Use `normalWorld` instead.
|
||||
*/
|
||||
export const transformedNormalWorld = ( Fn( () => { // @deprecated, r177
|
||||
|
||||
console.warn( 'THREE.TSL: "transformedNormalWorld" is deprecated. Use "normalWorld" instead.' );
|
||||
return normalWorld;
|
||||
|
||||
} ).once( [ 'NORMAL', 'VERTEX' ] ) )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the transformed clearcoat vertex normal in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
* @deprecated since r178. Use `clearcoatNormalView` instead.
|
||||
*/
|
||||
export const transformedClearcoatNormalView = ( Fn( () => { // @deprecated, r177
|
||||
|
||||
console.warn( 'THREE.TSL: "transformedClearcoatNormalView" is deprecated. Use "clearcoatNormalView" instead.' );
|
||||
return clearcoatNormalView;
|
||||
|
||||
} ).once( [ 'NORMAL', 'VERTEX' ] ) )();
|
||||
268
app/node_modules/three/src/nodes/accessors/Object3DNode.js
generated
vendored
Normal file
268
app/node_modules/three/src/nodes/accessors/Object3DNode.js
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import UniformNode from '../core/UniformNode.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { Sphere } from '../../math/Sphere.js';
|
||||
|
||||
const _sphere = /*@__PURE__*/ new Sphere();
|
||||
|
||||
/**
|
||||
* This node can be used to access transformation related metrics of 3D objects.
|
||||
* Depending on the selected scope, a different metric is represented as a uniform
|
||||
* in the shader. The following scopes are supported:
|
||||
*
|
||||
* - `POSITION`: The object's position in world space.
|
||||
* - `VIEW_POSITION`: The object's position in view/camera space.
|
||||
* - `DIRECTION`: The object's direction in world space.
|
||||
* - `SCALE`: The object's scale in world space.
|
||||
* - `WORLD_MATRIX`: The object's matrix in world space.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class Object3DNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'Object3DNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new object 3D node.
|
||||
*
|
||||
* @param {('position'|'viewPosition'|'direction'|'scale'|'worldMatrix')} scope - The node represents a different type of transformation depending on the scope.
|
||||
* @param {?Object3D} [object3d=null] - The 3D object.
|
||||
*/
|
||||
constructor( scope, object3d = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The node reports a different type of transformation depending on the scope.
|
||||
*
|
||||
* @type {('position'|'viewPosition'|'direction'|'scale'|'worldMatrix')}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
/**
|
||||
* The 3D object.
|
||||
*
|
||||
* @type {?Object3D}
|
||||
* @default null
|
||||
*/
|
||||
this.object3d = object3d;
|
||||
|
||||
/**
|
||||
* Overwritten since this type of node is updated per object.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'object'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.OBJECT;
|
||||
|
||||
/**
|
||||
* Holds the value of the node as a uniform.
|
||||
*
|
||||
* @type {UniformNode}
|
||||
*/
|
||||
this.uniformNode = new UniformNode( null );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten since the node type is inferred from the scope.
|
||||
*
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType() {
|
||||
|
||||
const scope = this.scope;
|
||||
|
||||
if ( scope === Object3DNode.WORLD_MATRIX ) {
|
||||
|
||||
return 'mat4';
|
||||
|
||||
} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) {
|
||||
|
||||
return 'vec3';
|
||||
|
||||
} else if ( scope === Object3DNode.RADIUS ) {
|
||||
|
||||
return 'float';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the uniform value depending on the scope.
|
||||
*
|
||||
* @param {NodeFrame} frame - The current node frame.
|
||||
*/
|
||||
update( frame ) {
|
||||
|
||||
const object = this.object3d;
|
||||
const uniformNode = this.uniformNode;
|
||||
const scope = this.scope;
|
||||
|
||||
if ( scope === Object3DNode.WORLD_MATRIX ) {
|
||||
|
||||
uniformNode.value = object.matrixWorld;
|
||||
|
||||
} else if ( scope === Object3DNode.POSITION ) {
|
||||
|
||||
uniformNode.value = uniformNode.value || new Vector3();
|
||||
|
||||
uniformNode.value.setFromMatrixPosition( object.matrixWorld );
|
||||
|
||||
} else if ( scope === Object3DNode.SCALE ) {
|
||||
|
||||
uniformNode.value = uniformNode.value || new Vector3();
|
||||
|
||||
uniformNode.value.setFromMatrixScale( object.matrixWorld );
|
||||
|
||||
} else if ( scope === Object3DNode.DIRECTION ) {
|
||||
|
||||
uniformNode.value = uniformNode.value || new Vector3();
|
||||
|
||||
object.getWorldDirection( uniformNode.value );
|
||||
|
||||
} else if ( scope === Object3DNode.VIEW_POSITION ) {
|
||||
|
||||
const camera = frame.camera;
|
||||
|
||||
uniformNode.value = uniformNode.value || new Vector3();
|
||||
uniformNode.value.setFromMatrixPosition( object.matrixWorld );
|
||||
|
||||
uniformNode.value.applyMatrix4( camera.matrixWorldInverse );
|
||||
|
||||
} else if ( scope === Object3DNode.RADIUS ) {
|
||||
|
||||
const geometry = frame.object.geometry;
|
||||
|
||||
if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
|
||||
|
||||
_sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
|
||||
|
||||
uniformNode.value = _sphere.radius;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the uniform node. The node type of the uniform
|
||||
* node also depends on the selected scope.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( builder ) {
|
||||
|
||||
const scope = this.scope;
|
||||
|
||||
if ( scope === Object3DNode.WORLD_MATRIX ) {
|
||||
|
||||
this.uniformNode.nodeType = 'mat4';
|
||||
|
||||
} else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) {
|
||||
|
||||
this.uniformNode.nodeType = 'vec3';
|
||||
|
||||
} else if ( scope === Object3DNode.RADIUS ) {
|
||||
|
||||
this.uniformNode.nodeType = 'float';
|
||||
|
||||
}
|
||||
|
||||
return this.uniformNode.build( builder );
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.scope = this.scope;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.scope = data.scope;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object3DNode.WORLD_MATRIX = 'worldMatrix';
|
||||
Object3DNode.POSITION = 'position';
|
||||
Object3DNode.SCALE = 'scale';
|
||||
Object3DNode.VIEW_POSITION = 'viewPosition';
|
||||
Object3DNode.DIRECTION = 'direction';
|
||||
Object3DNode.RADIUS = 'radius';
|
||||
|
||||
export default Object3DNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an object 3D node that represents the object's direction in world space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Object3D} [object3d] - The 3D object.
|
||||
* @returns {Object3DNode<vec3>}
|
||||
*/
|
||||
export const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION ).setParameterLength( 1 );
|
||||
|
||||
/**
|
||||
* TSL function for creating an object 3D node that represents the object's world matrix.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Object3D} [object3d] - The 3D object.
|
||||
* @returns {Object3DNode<mat4>}
|
||||
*/
|
||||
export const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ).setParameterLength( 1 );
|
||||
|
||||
/**
|
||||
* TSL function for creating an object 3D node that represents the object's position in world space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Object3D} [object3d] - The 3D object.
|
||||
* @returns {Object3DNode<vec3>}
|
||||
*/
|
||||
export const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION ).setParameterLength( 1 );
|
||||
|
||||
/**
|
||||
* TSL function for creating an object 3D node that represents the object's scale in world space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Object3D} [object3d] - The 3D object.
|
||||
* @returns {Object3DNode<vec3>}
|
||||
*/
|
||||
export const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE ).setParameterLength( 1 );
|
||||
|
||||
/**
|
||||
* TSL function for creating an object 3D node that represents the object's position in view/camera space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Object3D} [object3d] - The 3D object.
|
||||
* @returns {Object3DNode<vec3>}
|
||||
*/
|
||||
export const objectViewPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ).setParameterLength( 1 );
|
||||
|
||||
/**
|
||||
* TSL function for creating an object 3D node that represents the object's radius.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Object3D} [object3d] - The 3D object.
|
||||
* @returns {Object3DNode<float>}
|
||||
*/
|
||||
export const objectRadius = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.RADIUS ).setParameterLength( 1 );
|
||||
55
app/node_modules/three/src/nodes/accessors/PointUVNode.js
generated
vendored
Normal file
55
app/node_modules/three/src/nodes/accessors/PointUVNode.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeImmutable } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* A node for representing the uv coordinates of points.
|
||||
*
|
||||
* Can only be used with a WebGL backend. In WebGPU, point
|
||||
* primitives always have the size of one pixel and can thus
|
||||
* can't be used as sprite-like objects that display textures.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class PointUVNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PointUVNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new point uv node.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
super( 'vec2' );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isPointUVNode = true;
|
||||
|
||||
}
|
||||
|
||||
generate( /*builder*/ ) {
|
||||
|
||||
return 'vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PointUVNode;
|
||||
|
||||
/**
|
||||
* TSL object that represents the uv coordinates of points.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PointUVNode}
|
||||
*/
|
||||
export const pointUV = /*@__PURE__*/ nodeImmutable( PointUVNode );
|
||||
74
app/node_modules/three/src/nodes/accessors/Position.js
generated
vendored
Normal file
74
app/node_modules/three/src/nodes/accessors/Position.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { Fn } from '../tsl/TSLCore.js';
|
||||
import { modelWorldMatrix } from './ModelNode.js';
|
||||
|
||||
/**
|
||||
* TSL object that represents the position attribute of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {AttributeNode<vec3>}
|
||||
*/
|
||||
export const positionGeometry = /*@__PURE__*/ attribute( 'position', 'vec3' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex position in local space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {AttributeNode<vec3>}
|
||||
*/
|
||||
export const positionLocal = /*@__PURE__*/ positionGeometry.toVarying( 'positionLocal' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the previous vertex position in local space of the current rendered object.
|
||||
* Used in context of {@link VelocityNode} for rendering motion vectors.
|
||||
*
|
||||
* @tsl
|
||||
* @type {AttributeNode<vec3>}
|
||||
*/
|
||||
export const positionPrevious = /*@__PURE__*/ positionGeometry.toVarying( 'positionPrevious' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex position in world space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {VaryingNode<vec3>}
|
||||
*/
|
||||
export const positionWorld = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
return modelWorldMatrix.mul( positionLocal ).xyz.toVarying( builder.getSubBuildProperty( 'v_positionWorld' ) );
|
||||
|
||||
}, 'vec3' ).once( [ 'POSITION' ] ) )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the position world direction of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const positionWorldDirection = /*@__PURE__*/ ( Fn( () => {
|
||||
|
||||
const vertexPWD = positionLocal.transformDirection( modelWorldMatrix ).toVarying( 'v_positionWorldDirection' );
|
||||
|
||||
return vertexPWD.normalize().toVar( 'positionWorldDirection' );
|
||||
|
||||
}, 'vec3' ).once( [ 'POSITION' ] ) )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex position in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {VaryingNode<vec3>}
|
||||
*/
|
||||
export const positionView = /*@__PURE__*/ ( Fn( ( builder ) => {
|
||||
|
||||
return builder.context.setupPositionView().toVarying( 'v_positionView' );
|
||||
|
||||
}, 'vec3' ).once( [ 'POSITION' ] ) )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the position view direction of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {VaryingNode<vec3>}
|
||||
*/
|
||||
export const positionViewDirection = /*@__PURE__*/ positionView.negate().toVarying( 'v_positionViewDirection' ).normalize().toVar( 'positionViewDirection' );
|
||||
357
app/node_modules/three/src/nodes/accessors/ReferenceBaseNode.js
generated
vendored
Normal file
357
app/node_modules/three/src/nodes/accessors/ReferenceBaseNode.js
generated
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { nodeObject } from '../tsl/TSLCore.js';
|
||||
import ArrayElementNode from '../utils/ArrayElementNode.js';
|
||||
|
||||
// TODO: Avoid duplicated code and ues only ReferenceBaseNode or ReferenceNode
|
||||
|
||||
/**
|
||||
* This class is only relevant if the referenced property is array-like.
|
||||
* In this case, `ReferenceElementNode` allows to refer to a specific
|
||||
* element inside the data structure via an index.
|
||||
*
|
||||
* @augments ArrayElementNode
|
||||
*/
|
||||
class ReferenceElementNode extends ArrayElementNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ReferenceElementNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new reference element node.
|
||||
*
|
||||
* @param {ReferenceBaseNode} referenceNode - The reference node.
|
||||
* @param {Node} indexNode - The index node that defines the element access.
|
||||
*/
|
||||
constructor( referenceNode, indexNode ) {
|
||||
|
||||
super( referenceNode, indexNode );
|
||||
|
||||
/**
|
||||
* Similar to {@link ReferenceBaseNode#reference}, an additional
|
||||
* property references to the current node.
|
||||
*
|
||||
* @type {?ReferenceBaseNode}
|
||||
* @default null
|
||||
*/
|
||||
this.referenceNode = referenceNode;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isReferenceElementNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type is inferred from
|
||||
* the uniform type of the reference node.
|
||||
*
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType() {
|
||||
|
||||
return this.referenceNode.uniformType;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const snippet = super.generate( builder );
|
||||
const arrayType = this.referenceNode.getNodeType();
|
||||
const elementType = this.getNodeType();
|
||||
|
||||
return builder.format( snippet, arrayType, elementType );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for nodes which establishes a reference to a property of another object.
|
||||
* In this way, the value of the node is automatically linked to the value of
|
||||
* referenced object. Reference nodes internally represent the linked value
|
||||
* as a uniform.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ReferenceBaseNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ReferenceBaseNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new reference base node.
|
||||
*
|
||||
* @param {string} property - The name of the property the node refers to.
|
||||
* @param {string} uniformType - The uniform type that should be used to represent the property value.
|
||||
* @param {?Object} [object=null] - The object the property belongs to.
|
||||
* @param {?number} [count=null] - When the linked property is an array-like, this parameter defines its length.
|
||||
*/
|
||||
constructor( property, uniformType, object = null, count = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The name of the property the node refers to.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.property = property;
|
||||
|
||||
/**
|
||||
* The uniform type that should be used to represent the property value.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.uniformType = uniformType;
|
||||
|
||||
/**
|
||||
* The object the property belongs to.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.object = object;
|
||||
|
||||
/**
|
||||
* When the linked property is an array, this parameter defines its length.
|
||||
*
|
||||
* @type {?number}
|
||||
* @default null
|
||||
*/
|
||||
this.count = count;
|
||||
|
||||
/**
|
||||
* The property name might have dots so nested properties can be referred.
|
||||
* The hierarchy of the names is stored inside this array.
|
||||
*
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
this.properties = property.split( '.' );
|
||||
|
||||
/**
|
||||
* Points to the current referred object. This property exists next to {@link ReferenceNode#object}
|
||||
* since the final reference might be updated from calling code.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.reference = object;
|
||||
|
||||
/**
|
||||
* The uniform node that holds the value of the reference node.
|
||||
*
|
||||
* @type {UniformNode}
|
||||
* @default null
|
||||
*/
|
||||
this.node = null;
|
||||
|
||||
/**
|
||||
* The uniform group of the internal uniform.
|
||||
*
|
||||
* @type {UniformGroupNode}
|
||||
* @default null
|
||||
*/
|
||||
this.group = null;
|
||||
|
||||
/**
|
||||
* Overwritten since reference nodes are updated per object.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'object'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.OBJECT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the uniform group for this reference node.
|
||||
*
|
||||
* @param {UniformGroupNode} group - The uniform group to set.
|
||||
* @return {ReferenceBaseNode} A reference to this node.
|
||||
*/
|
||||
setGroup( group ) {
|
||||
|
||||
this.group = group;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* When the referred property is array-like, this method can be used
|
||||
* to access elements via an index node.
|
||||
*
|
||||
* @param {IndexNode} indexNode - indexNode.
|
||||
* @return {ReferenceElementNode} A reference to an element.
|
||||
*/
|
||||
element( indexNode ) {
|
||||
|
||||
return nodeObject( new ReferenceElementNode( this, nodeObject( indexNode ) ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node type which automatically defines the internal
|
||||
* uniform type.
|
||||
*
|
||||
* @param {string} uniformType - The type to set.
|
||||
*/
|
||||
setNodeType( uniformType ) {
|
||||
|
||||
const node = uniform( null, uniformType ).getSelf();
|
||||
|
||||
if ( this.group !== null ) {
|
||||
|
||||
node.setGroup( this.group );
|
||||
|
||||
}
|
||||
|
||||
this.node = node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type is inferred from
|
||||
* the type of the reference node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
if ( this.node === null ) {
|
||||
|
||||
this.updateReference( builder );
|
||||
this.updateValue();
|
||||
|
||||
}
|
||||
|
||||
return this.node.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property value from the given referred object.
|
||||
*
|
||||
* @param {Object} [object=this.reference] - The object to retrieve the property value from.
|
||||
* @return {any} The value.
|
||||
*/
|
||||
getValueFromReference( object = this.reference ) {
|
||||
|
||||
const { properties } = this;
|
||||
|
||||
let value = object[ properties[ 0 ] ];
|
||||
|
||||
for ( let i = 1; i < properties.length; i ++ ) {
|
||||
|
||||
value = value[ properties[ i ] ];
|
||||
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to update the reference based on the given state. The state is only
|
||||
* evaluated {@link ReferenceBaseNode#object} is not set.
|
||||
*
|
||||
* @param {(NodeFrame|NodeBuilder)} state - The current state.
|
||||
* @return {Object} The updated reference.
|
||||
*/
|
||||
updateReference( state ) {
|
||||
|
||||
this.reference = this.object !== null ? this.object : state.object;
|
||||
|
||||
return this.reference;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The output of the reference node is the internal uniform node.
|
||||
*
|
||||
* @return {UniformNode} The output node.
|
||||
*/
|
||||
setup() {
|
||||
|
||||
this.updateValue();
|
||||
|
||||
return this.node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to update the internal uniform value.
|
||||
*
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
*/
|
||||
update( /*frame*/ ) {
|
||||
|
||||
this.updateValue();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value from the referred object property and uses it
|
||||
* to updated the internal uniform.
|
||||
*/
|
||||
updateValue() {
|
||||
|
||||
if ( this.node === null ) this.setNodeType( this.uniformType );
|
||||
|
||||
const value = this.getValueFromReference();
|
||||
|
||||
if ( Array.isArray( value ) ) {
|
||||
|
||||
this.node.array = value;
|
||||
|
||||
} else {
|
||||
|
||||
this.node.value = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ReferenceBaseNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a reference base node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the property the node refers to.
|
||||
* @param {string} type - The uniform type that should be used to represent the property value.
|
||||
* @param {Object} object - The object the property belongs to.
|
||||
* @returns {ReferenceBaseNode}
|
||||
*/
|
||||
export const reference = ( name, type, object ) => nodeObject( new ReferenceBaseNode( name, type, object ) );
|
||||
|
||||
/**
|
||||
* TSL function for creating a reference base node. Use this function if you want need a reference
|
||||
* to an array-like property that should be represented as a uniform buffer.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the property the node refers to.
|
||||
* @param {string} type - The uniform type that should be used to represent the property value.
|
||||
* @param {number} count - The number of value inside the array-like object.
|
||||
* @param {Object} [object] - An array-like object the property belongs to.
|
||||
* @returns {ReferenceBaseNode}
|
||||
*/
|
||||
export const referenceBuffer = ( name, type, count, object ) => nodeObject( new ReferenceBaseNode( name, type, object, count ) );
|
||||
408
app/node_modules/three/src/nodes/accessors/ReferenceNode.js
generated
vendored
Normal file
408
app/node_modules/three/src/nodes/accessors/ReferenceNode.js
generated
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { texture } from './TextureNode.js';
|
||||
import { cubeTexture } from './CubeTextureNode.js';
|
||||
import { buffer } from './BufferNode.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
import { uniformArray } from './UniformArrayNode.js';
|
||||
import ArrayElementNode from '../utils/ArrayElementNode.js';
|
||||
|
||||
// TODO: Avoid duplicated code and ues only ReferenceBaseNode or ReferenceNode
|
||||
|
||||
/**
|
||||
* This class is only relevant if the referenced property is array-like.
|
||||
* In this case, `ReferenceElementNode` allows to refer to a specific
|
||||
* element inside the data structure via an index.
|
||||
*
|
||||
* @augments ArrayElementNode
|
||||
*/
|
||||
class ReferenceElementNode extends ArrayElementNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ReferenceElementNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new reference element node.
|
||||
*
|
||||
* @param {?ReferenceNode} referenceNode - The reference node.
|
||||
* @param {Node} indexNode - The index node that defines the element access.
|
||||
*/
|
||||
constructor( referenceNode, indexNode ) {
|
||||
|
||||
super( referenceNode, indexNode );
|
||||
|
||||
/**
|
||||
* Similar to {@link ReferenceNode#reference}, an additional
|
||||
* property references to the current node.
|
||||
*
|
||||
* @type {?ReferenceNode}
|
||||
* @default null
|
||||
*/
|
||||
this.referenceNode = referenceNode;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isReferenceElementNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type is inferred from
|
||||
* the uniform type of the reference node.
|
||||
*
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType() {
|
||||
|
||||
return this.referenceNode.uniformType;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const snippet = super.generate( builder );
|
||||
const arrayType = this.referenceNode.getNodeType();
|
||||
const elementType = this.getNodeType();
|
||||
|
||||
return builder.format( snippet, arrayType, elementType );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This type of node establishes a reference to a property of another object.
|
||||
* In this way, the value of the node is automatically linked to the value of
|
||||
* referenced object. Reference nodes internally represent the linked value
|
||||
* as a uniform.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ReferenceNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ReferenceNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new reference node.
|
||||
*
|
||||
* @param {string} property - The name of the property the node refers to.
|
||||
* @param {string} uniformType - The uniform type that should be used to represent the property value.
|
||||
* @param {?Object} [object=null] - The object the property belongs to.
|
||||
* @param {?number} [count=null] - When the linked property is an array-like, this parameter defines its length.
|
||||
*/
|
||||
constructor( property, uniformType, object = null, count = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The name of the property the node refers to.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.property = property;
|
||||
|
||||
/**
|
||||
* The uniform type that should be used to represent the property value.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.uniformType = uniformType;
|
||||
|
||||
/**
|
||||
* The object the property belongs to.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.object = object;
|
||||
|
||||
/**
|
||||
* When the linked property is an array, this parameter defines its length.
|
||||
*
|
||||
* @type {?number}
|
||||
* @default null
|
||||
*/
|
||||
this.count = count;
|
||||
|
||||
/**
|
||||
* The property name might have dots so nested properties can be referred.
|
||||
* The hierarchy of the names is stored inside this array.
|
||||
*
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
this.properties = property.split( '.' );
|
||||
|
||||
/**
|
||||
* Points to the current referred object. This property exists next to {@link ReferenceNode#object}
|
||||
* since the final reference might be updated from calling code.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.reference = object;
|
||||
|
||||
/**
|
||||
* The uniform node that holds the value of the reference node.
|
||||
*
|
||||
* @type {UniformNode}
|
||||
* @default null
|
||||
*/
|
||||
this.node = null;
|
||||
|
||||
/**
|
||||
* The uniform group of the internal uniform.
|
||||
*
|
||||
* @type {UniformGroupNode}
|
||||
* @default null
|
||||
*/
|
||||
this.group = null;
|
||||
|
||||
/**
|
||||
* An optional label of the internal uniform node.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.name = null;
|
||||
|
||||
/**
|
||||
* Overwritten since reference nodes are updated per object.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'object'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.OBJECT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* When the referred property is array-like, this method can be used
|
||||
* to access elements via an index node.
|
||||
*
|
||||
* @param {IndexNode} indexNode - indexNode.
|
||||
* @return {ReferenceElementNode} A reference to an element.
|
||||
*/
|
||||
element( indexNode ) {
|
||||
|
||||
return nodeObject( new ReferenceElementNode( this, nodeObject( indexNode ) ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the uniform group for this reference node.
|
||||
*
|
||||
* @param {UniformGroupNode} group - The uniform group to set.
|
||||
* @return {ReferenceNode} A reference to this node.
|
||||
*/
|
||||
setGroup( group ) {
|
||||
|
||||
this.group = group;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label for the internal uniform.
|
||||
*
|
||||
* @param {string} name - The label to set.
|
||||
* @return {ReferenceNode} A reference to this node.
|
||||
*/
|
||||
label( name ) {
|
||||
|
||||
this.name = name;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node type which automatically defines the internal
|
||||
* uniform type.
|
||||
*
|
||||
* @param {string} uniformType - The type to set.
|
||||
*/
|
||||
setNodeType( uniformType ) {
|
||||
|
||||
let node = null;
|
||||
|
||||
if ( this.count !== null ) {
|
||||
|
||||
node = buffer( null, uniformType, this.count );
|
||||
|
||||
} else if ( Array.isArray( this.getValueFromReference() ) ) {
|
||||
|
||||
node = uniformArray( null, uniformType );
|
||||
|
||||
} else if ( uniformType === 'texture' ) {
|
||||
|
||||
node = texture( null );
|
||||
|
||||
} else if ( uniformType === 'cubeTexture' ) {
|
||||
|
||||
node = cubeTexture( null );
|
||||
|
||||
} else {
|
||||
|
||||
node = uniform( null, uniformType );
|
||||
|
||||
}
|
||||
|
||||
if ( this.group !== null ) {
|
||||
|
||||
node.setGroup( this.group );
|
||||
|
||||
}
|
||||
|
||||
if ( this.name !== null ) node.label( this.name );
|
||||
|
||||
this.node = node.getSelf();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type is inferred from
|
||||
* the type of the reference node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
if ( this.node === null ) {
|
||||
|
||||
this.updateReference( builder );
|
||||
this.updateValue();
|
||||
|
||||
}
|
||||
|
||||
return this.node.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property value from the given referred object.
|
||||
*
|
||||
* @param {Object} [object=this.reference] - The object to retrieve the property value from.
|
||||
* @return {any} The value.
|
||||
*/
|
||||
getValueFromReference( object = this.reference ) {
|
||||
|
||||
const { properties } = this;
|
||||
|
||||
let value = object[ properties[ 0 ] ];
|
||||
|
||||
for ( let i = 1; i < properties.length; i ++ ) {
|
||||
|
||||
value = value[ properties[ i ] ];
|
||||
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to update the reference based on the given state. The state is only
|
||||
* evaluated {@link ReferenceNode#object} is not set.
|
||||
*
|
||||
* @param {(NodeFrame|NodeBuilder)} state - The current state.
|
||||
* @return {Object} The updated reference.
|
||||
*/
|
||||
updateReference( state ) {
|
||||
|
||||
this.reference = this.object !== null ? this.object : state.object;
|
||||
|
||||
return this.reference;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The output of the reference node is the internal uniform node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {UniformNode} The output node.
|
||||
*/
|
||||
setup( /* builder */ ) {
|
||||
|
||||
this.updateValue();
|
||||
|
||||
return this.node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to update the internal uniform value.
|
||||
*
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
*/
|
||||
update( /*frame*/ ) {
|
||||
|
||||
this.updateValue();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value from the referred object property and uses it
|
||||
* to updated the internal uniform.
|
||||
*/
|
||||
updateValue() {
|
||||
|
||||
if ( this.node === null ) this.setNodeType( this.uniformType );
|
||||
|
||||
const value = this.getValueFromReference();
|
||||
|
||||
if ( Array.isArray( value ) ) {
|
||||
|
||||
this.node.array = value;
|
||||
|
||||
} else {
|
||||
|
||||
this.node.value = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ReferenceNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a reference node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the property the node refers to.
|
||||
* @param {string} type - The uniform type that should be used to represent the property value.
|
||||
* @param {?Object} [object] - The object the property belongs to.
|
||||
* @returns {ReferenceNode}
|
||||
*/
|
||||
export const reference = ( name, type, object ) => nodeObject( new ReferenceNode( name, type, object ) );
|
||||
|
||||
/**
|
||||
* TSL function for creating a reference node. Use this function if you want need a reference
|
||||
* to an array-like property that should be represented as a uniform buffer.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the property the node refers to.
|
||||
* @param {string} type - The uniform type that should be used to represent the property value.
|
||||
* @param {number} count - The number of value inside the array-like object.
|
||||
* @param {Object} object - An array-like object the property belongs to.
|
||||
* @returns {ReferenceNode}
|
||||
*/
|
||||
export const referenceBuffer = ( name, type, count, object ) => nodeObject( new ReferenceNode( name, type, object, count ) );
|
||||
36
app/node_modules/three/src/nodes/accessors/ReflectVector.js
generated
vendored
Normal file
36
app/node_modules/three/src/nodes/accessors/ReflectVector.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
import { cameraViewMatrix } from './Camera.js';
|
||||
import { normalView } from './Normal.js';
|
||||
import { positionViewDirection } from './Position.js';
|
||||
import { materialRefractionRatio } from './MaterialProperties.js';
|
||||
|
||||
/**
|
||||
* The reflect vector in view space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const reflectView = /*@__PURE__*/ positionViewDirection.negate().reflect( normalView );
|
||||
|
||||
/**
|
||||
* The refract vector in view space.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const refractView = /*@__PURE__*/ positionViewDirection.negate().refract( normalView, materialRefractionRatio );
|
||||
|
||||
/**
|
||||
* Used for sampling cube maps when using cube reflection mapping.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' );
|
||||
|
||||
/**
|
||||
* Used for sampling cube maps when using cube refraction mapping.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' );
|
||||
79
app/node_modules/three/src/nodes/accessors/RendererReferenceNode.js
generated
vendored
Normal file
79
app/node_modules/three/src/nodes/accessors/RendererReferenceNode.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import ReferenceBaseNode from './ReferenceBaseNode.js';
|
||||
import { nodeObject } from '../tsl/TSLCore.js';
|
||||
import { renderGroup } from '../core/UniformGroupNode.js';
|
||||
|
||||
/**
|
||||
* This node is a special type of reference node which is intended
|
||||
* for linking renderer properties with node values.
|
||||
* ```js
|
||||
* const exposureNode = rendererReference( 'toneMappingExposure', 'float', renderer );
|
||||
* ```
|
||||
* When changing `renderer.toneMappingExposure`, the node value of `exposureNode` will
|
||||
* automatically be updated.
|
||||
*
|
||||
* @augments ReferenceBaseNode
|
||||
*/
|
||||
class RendererReferenceNode extends ReferenceBaseNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'RendererReferenceNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new renderer reference node.
|
||||
*
|
||||
* @param {string} property - The name of the property the node refers to.
|
||||
* @param {string} inputType - The uniform type that should be used to represent the property value.
|
||||
* @param {?Renderer} [renderer=null] - The renderer the property belongs to. When no renderer is set,
|
||||
* the node refers to the renderer of the current state.
|
||||
*/
|
||||
constructor( property, inputType, renderer = null ) {
|
||||
|
||||
super( property, inputType, renderer );
|
||||
|
||||
/**
|
||||
* The renderer the property belongs to. When no renderer is set,
|
||||
* the node refers to the renderer of the current state.
|
||||
*
|
||||
* @type {?Renderer}
|
||||
* @default null
|
||||
*/
|
||||
this.renderer = renderer;
|
||||
|
||||
this.setGroup( renderGroup );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the reference based on the given state. The state is only evaluated
|
||||
* {@link RendererReferenceNode#renderer} is not set.
|
||||
*
|
||||
* @param {(NodeFrame|NodeBuilder)} state - The current state.
|
||||
* @return {Object} The updated reference.
|
||||
*/
|
||||
updateReference( state ) {
|
||||
|
||||
this.reference = this.renderer !== null ? this.renderer : state.renderer;
|
||||
|
||||
return this.reference;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RendererReferenceNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a renderer reference node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the property the node refers to.
|
||||
* @param {string} type - The uniform type that should be used to represent the property value.
|
||||
* @param {?Renderer} [renderer=null] - The renderer the property belongs to. When no renderer is set,
|
||||
* the node refers to the renderer of the current state.
|
||||
* @returns {RendererReferenceNode}
|
||||
*/
|
||||
export const rendererReference = ( name, type, renderer = null ) => nodeObject( new RendererReferenceNode( name, type, renderer ) );
|
||||
144
app/node_modules/three/src/nodes/accessors/SceneNode.js
generated
vendored
Normal file
144
app/node_modules/three/src/nodes/accessors/SceneNode.js
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
import { UVMapping } from '../../constants.js';
|
||||
import { Euler } from '../../math/Euler.js';
|
||||
import { Matrix4 } from '../../math/Matrix4.js';
|
||||
import Node from '../core/Node.js';
|
||||
import { renderGroup } from '../core/UniformGroupNode.js';
|
||||
import { nodeImmutable, uniform } from '../tsl/TSLBase.js';
|
||||
import { reference } from './ReferenceNode.js';
|
||||
|
||||
const _e1 = /*@__PURE__*/ new Euler();
|
||||
const _m1 = /*@__PURE__*/ new Matrix4();
|
||||
|
||||
/**
|
||||
* This module allows access to a collection of scene properties. The following predefined TSL objects
|
||||
* are available for easier use:
|
||||
*
|
||||
* - `backgroundBlurriness`: A node that represents the scene's background blurriness.
|
||||
* - `backgroundIntensity`: A node that represents the scene's background intensity.
|
||||
* - `backgroundRotation`: A node that represents the scene's background rotation.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class SceneNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'SceneNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new scene node.
|
||||
*
|
||||
* @param {('backgroundBlurriness'|'backgroundIntensity'|'backgroundRotation')} scope - The scope defines the type of scene property that is accessed.
|
||||
* @param {?Scene} [scene=null] - A reference to the scene.
|
||||
*/
|
||||
constructor( scope = SceneNode.BACKGROUND_BLURRINESS, scene = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The scope defines the type of scene property that is accessed.
|
||||
*
|
||||
* @type {('backgroundBlurriness'|'backgroundIntensity'|'backgroundRotation')}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
/**
|
||||
* A reference to the scene that is going to be accessed.
|
||||
*
|
||||
* @type {?Scene}
|
||||
* @default null
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the scope, the method returns a different type of node that represents
|
||||
* the respective scene property.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node} The output node.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const scope = this.scope;
|
||||
const scene = this.scene !== null ? this.scene : builder.scene;
|
||||
|
||||
let output;
|
||||
|
||||
if ( scope === SceneNode.BACKGROUND_BLURRINESS ) {
|
||||
|
||||
output = reference( 'backgroundBlurriness', 'float', scene );
|
||||
|
||||
} else if ( scope === SceneNode.BACKGROUND_INTENSITY ) {
|
||||
|
||||
output = reference( 'backgroundIntensity', 'float', scene );
|
||||
|
||||
} else if ( scope === SceneNode.BACKGROUND_ROTATION ) {
|
||||
|
||||
output = uniform( 'mat4' ).label( 'backgroundRotation' ).setGroup( renderGroup ).onRenderUpdate( () => {
|
||||
|
||||
const background = scene.background;
|
||||
|
||||
if ( background !== null && background.isTexture && background.mapping !== UVMapping ) {
|
||||
|
||||
_e1.copy( scene.backgroundRotation );
|
||||
|
||||
// accommodate left-handed frame
|
||||
_e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1;
|
||||
|
||||
_m1.makeRotationFromEuler( _e1 );
|
||||
|
||||
} else {
|
||||
|
||||
_m1.identity();
|
||||
|
||||
}
|
||||
|
||||
return _m1;
|
||||
|
||||
} );
|
||||
|
||||
} else {
|
||||
|
||||
console.error( 'THREE.SceneNode: Unknown scope:', scope );
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness';
|
||||
SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity';
|
||||
SceneNode.BACKGROUND_ROTATION = 'backgroundRotation';
|
||||
|
||||
export default SceneNode;
|
||||
|
||||
/**
|
||||
* TSL object that represents the scene's background blurriness.
|
||||
*
|
||||
* @tsl
|
||||
* @type {SceneNode}
|
||||
*/
|
||||
export const backgroundBlurriness = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS );
|
||||
|
||||
/**
|
||||
* TSL object that represents the scene's background intensity.
|
||||
*
|
||||
* @tsl
|
||||
* @type {SceneNode}
|
||||
*/
|
||||
export const backgroundIntensity = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY );
|
||||
|
||||
/**
|
||||
* TSL object that represents the scene's background rotation.
|
||||
*
|
||||
* @tsl
|
||||
* @type {SceneNode}
|
||||
*/
|
||||
export const backgroundRotation = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_ROTATION );
|
||||
327
app/node_modules/three/src/nodes/accessors/SkinningNode.js
generated
vendored
Normal file
327
app/node_modules/three/src/nodes/accessors/SkinningNode.js
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { reference, referenceBuffer } from './ReferenceNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
import { normalLocal } from './Normal.js';
|
||||
import { positionLocal, positionPrevious } from './Position.js';
|
||||
import { tangentLocal } from './Tangent.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { buffer } from './BufferNode.js';
|
||||
import { getDataFromObject } from '../core/NodeUtils.js';
|
||||
import { storage } from './StorageBufferNode.js';
|
||||
import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js';
|
||||
import { instanceIndex } from '../core/IndexNode.js';
|
||||
|
||||
const _frameId = new WeakMap();
|
||||
|
||||
/**
|
||||
* This node implements the vertex transformation shader logic which is required
|
||||
* for skinning/skeletal animation.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class SkinningNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'SkinningNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new skinning node.
|
||||
*
|
||||
* @param {SkinnedMesh} skinnedMesh - The skinned mesh.
|
||||
*/
|
||||
constructor( skinnedMesh ) {
|
||||
|
||||
super( 'void' );
|
||||
|
||||
/**
|
||||
* The skinned mesh.
|
||||
*
|
||||
* @type {SkinnedMesh}
|
||||
*/
|
||||
this.skinnedMesh = skinnedMesh;
|
||||
|
||||
/**
|
||||
* The update type overwritten since skinning nodes are updated per object.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.updateType = NodeUpdateType.OBJECT;
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* The skin index attribute.
|
||||
*
|
||||
* @type {AttributeNode}
|
||||
*/
|
||||
this.skinIndexNode = attribute( 'skinIndex', 'uvec4' );
|
||||
|
||||
/**
|
||||
* The skin weight attribute.
|
||||
*
|
||||
* @type {AttributeNode}
|
||||
*/
|
||||
this.skinWeightNode = attribute( 'skinWeight', 'vec4' );
|
||||
|
||||
/**
|
||||
* The bind matrix node.
|
||||
*
|
||||
* @type {Node<mat4>}
|
||||
*/
|
||||
this.bindMatrixNode = reference( 'bindMatrix', 'mat4' );
|
||||
|
||||
/**
|
||||
* The bind matrix inverse node.
|
||||
*
|
||||
* @type {Node<mat4>}
|
||||
*/
|
||||
this.bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' );
|
||||
|
||||
/**
|
||||
* The bind matrices as a uniform buffer node.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length );
|
||||
|
||||
/**
|
||||
* The current vertex position in local space.
|
||||
*
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
this.positionNode = positionLocal;
|
||||
|
||||
/**
|
||||
* The result of vertex position in local space.
|
||||
*
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
this.toPositionNode = positionLocal;
|
||||
|
||||
/**
|
||||
* The previous bind matrices as a uniform buffer node.
|
||||
* Required for computing motion vectors.
|
||||
*
|
||||
* @type {?Node}
|
||||
* @default null
|
||||
*/
|
||||
this.previousBoneMatricesNode = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given vertex position via skinning.
|
||||
*
|
||||
* @param {Node} [boneMatrices=this.boneMatricesNode] - The bone matrices
|
||||
* @param {Node<vec3>} [position=this.positionNode] - The vertex position in local space.
|
||||
* @return {Node<vec3>} The transformed vertex position.
|
||||
*/
|
||||
getSkinnedPosition( boneMatrices = this.boneMatricesNode, position = this.positionNode ) {
|
||||
|
||||
const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this;
|
||||
|
||||
const boneMatX = boneMatrices.element( skinIndexNode.x );
|
||||
const boneMatY = boneMatrices.element( skinIndexNode.y );
|
||||
const boneMatZ = boneMatrices.element( skinIndexNode.z );
|
||||
const boneMatW = boneMatrices.element( skinIndexNode.w );
|
||||
|
||||
// POSITION
|
||||
|
||||
const skinVertex = bindMatrixNode.mul( position );
|
||||
|
||||
const skinned = add(
|
||||
boneMatX.mul( skinWeightNode.x ).mul( skinVertex ),
|
||||
boneMatY.mul( skinWeightNode.y ).mul( skinVertex ),
|
||||
boneMatZ.mul( skinWeightNode.z ).mul( skinVertex ),
|
||||
boneMatW.mul( skinWeightNode.w ).mul( skinVertex )
|
||||
);
|
||||
|
||||
return bindMatrixInverseNode.mul( skinned ).xyz;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given vertex normal via skinning.
|
||||
*
|
||||
* @param {Node} [boneMatrices=this.boneMatricesNode] - The bone matrices
|
||||
* @param {Node<vec3>} [normal=normalLocal] - The vertex normal in local space.
|
||||
* @return {Node<vec3>} The transformed vertex normal.
|
||||
*/
|
||||
getSkinnedNormal( boneMatrices = this.boneMatricesNode, normal = normalLocal ) {
|
||||
|
||||
const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this;
|
||||
|
||||
const boneMatX = boneMatrices.element( skinIndexNode.x );
|
||||
const boneMatY = boneMatrices.element( skinIndexNode.y );
|
||||
const boneMatZ = boneMatrices.element( skinIndexNode.z );
|
||||
const boneMatW = boneMatrices.element( skinIndexNode.w );
|
||||
|
||||
// NORMAL
|
||||
|
||||
let skinMatrix = add(
|
||||
skinWeightNode.x.mul( boneMatX ),
|
||||
skinWeightNode.y.mul( boneMatY ),
|
||||
skinWeightNode.z.mul( boneMatZ ),
|
||||
skinWeightNode.w.mul( boneMatW )
|
||||
);
|
||||
|
||||
skinMatrix = bindMatrixInverseNode.mul( skinMatrix ).mul( bindMatrixNode );
|
||||
|
||||
return skinMatrix.transformDirection( normal ).xyz;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the transformed/skinned vertex position of the previous frame.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node<vec3>} The skinned position from the previous frame.
|
||||
*/
|
||||
getPreviousSkinnedPosition( builder ) {
|
||||
|
||||
const skinnedMesh = builder.object;
|
||||
|
||||
if ( this.previousBoneMatricesNode === null ) {
|
||||
|
||||
skinnedMesh.skeleton.previousBoneMatrices = new Float32Array( skinnedMesh.skeleton.boneMatrices );
|
||||
|
||||
this.previousBoneMatricesNode = referenceBuffer( 'skeleton.previousBoneMatrices', 'mat4', skinnedMesh.skeleton.bones.length );
|
||||
|
||||
}
|
||||
|
||||
return this.getSkinnedPosition( this.previousBoneMatricesNode, positionPrevious );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if bone matrices from the previous frame are required. Relevant
|
||||
* when computing motion vectors with {@link VelocityNode}.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {boolean} Whether bone matrices from the previous frame are required or not.
|
||||
*/
|
||||
needsPreviousBoneMatrices( builder ) {
|
||||
|
||||
const mrt = builder.renderer.getMRT();
|
||||
|
||||
return ( mrt && mrt.has( 'velocity' ) ) || getDataFromObject( builder.object ).useVelocity === true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the skinning node by assigning the transformed vertex data to predefined node variables.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node<vec3>} The transformed vertex position.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
if ( this.needsPreviousBoneMatrices( builder ) ) {
|
||||
|
||||
positionPrevious.assign( this.getPreviousSkinnedPosition( builder ) );
|
||||
|
||||
}
|
||||
|
||||
const skinPosition = this.getSkinnedPosition();
|
||||
|
||||
if ( this.toPositionNode ) this.toPositionNode.assign( skinPosition );
|
||||
|
||||
//
|
||||
|
||||
if ( builder.hasGeometryAttribute( 'normal' ) ) {
|
||||
|
||||
const skinNormal = this.getSkinnedNormal();
|
||||
|
||||
normalLocal.assign( skinNormal );
|
||||
|
||||
if ( builder.hasGeometryAttribute( 'tangent' ) ) {
|
||||
|
||||
tangentLocal.assign( skinNormal );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return skinPosition;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the skinning node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} output - The current output.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( builder, output ) {
|
||||
|
||||
if ( output !== 'void' ) {
|
||||
|
||||
return super.generate( builder, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the skinned mesh by updating the skeleton once per frame.
|
||||
*
|
||||
* @param {NodeFrame} frame - The current node frame.
|
||||
*/
|
||||
update( frame ) {
|
||||
|
||||
const skeleton = frame.object && frame.object.skeleton ? frame.object.skeleton : this.skinnedMesh.skeleton;
|
||||
|
||||
if ( _frameId.get( skeleton ) === frame.frameId ) return;
|
||||
|
||||
_frameId.set( skeleton, frame.frameId );
|
||||
|
||||
if ( this.previousBoneMatricesNode !== null ) skeleton.previousBoneMatrices.set( skeleton.boneMatrices );
|
||||
|
||||
skeleton.update();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SkinningNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a skinning node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {SkinnedMesh} skinnedMesh - The skinned mesh.
|
||||
* @returns {SkinningNode}
|
||||
*/
|
||||
export const skinning = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh ) );
|
||||
|
||||
/**
|
||||
* TSL function for computing skinning.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {SkinnedMesh} skinnedMesh - The skinned mesh.
|
||||
* @param {Node<vec3>} [toPosition=null] - The target position.
|
||||
* @returns {SkinningNode}
|
||||
*/
|
||||
export const computeSkinning = ( skinnedMesh, toPosition = null ) => {
|
||||
|
||||
const node = new SkinningNode( skinnedMesh );
|
||||
node.positionNode = storage( new InstancedBufferAttribute( skinnedMesh.geometry.getAttribute( 'position' ).array, 3 ), 'vec3' ).setPBO( true ).toReadOnly().element( instanceIndex ).toVar();
|
||||
node.skinIndexNode = storage( new InstancedBufferAttribute( new Uint32Array( skinnedMesh.geometry.getAttribute( 'skinIndex' ).array ), 4 ), 'uvec4' ).setPBO( true ).toReadOnly().element( instanceIndex ).toVar();
|
||||
node.skinWeightNode = storage( new InstancedBufferAttribute( skinnedMesh.geometry.getAttribute( 'skinWeight' ).array, 4 ), 'vec4' ).setPBO( true ).toReadOnly().element( instanceIndex ).toVar();
|
||||
node.bindMatrixNode = uniform( skinnedMesh.bindMatrix, 'mat4' );
|
||||
node.bindMatrixInverseNode = uniform( skinnedMesh.bindMatrixInverse, 'mat4' );
|
||||
node.boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length );
|
||||
node.toPositionNode = toPosition;
|
||||
|
||||
return nodeObject( node );
|
||||
|
||||
};
|
||||
415
app/node_modules/three/src/nodes/accessors/StorageBufferNode.js
generated
vendored
Normal file
415
app/node_modules/three/src/nodes/accessors/StorageBufferNode.js
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
import BufferNode from './BufferNode.js';
|
||||
import { bufferAttribute } from './BufferAttributeNode.js';
|
||||
import { nodeObject, varying } from '../tsl/TSLBase.js';
|
||||
import { storageElement } from '../utils/StorageArrayElementNode.js';
|
||||
import { NodeAccess } from '../core/constants.js';
|
||||
import { getTypeFromLength } from '../core/NodeUtils.js';
|
||||
|
||||
/**
|
||||
* This node is used in context of compute shaders and allows to define a
|
||||
* storage buffer for data. A typical workflow is to create instances of
|
||||
* this node with the convenience functions `attributeArray()` or `instancedArray()`,
|
||||
* setup up a compute shader that writes into the buffers and then convert
|
||||
* the storage buffers to attribute nodes for rendering.
|
||||
*
|
||||
* ```js
|
||||
* const positionBuffer = instancedArray( particleCount, 'vec3' ); // the storage buffer node
|
||||
*
|
||||
* const computeInit = Fn( () => { // the compute shader
|
||||
*
|
||||
* const position = positionBuffer.element( instanceIndex );
|
||||
*
|
||||
* // compute position data
|
||||
*
|
||||
* position.x = 1;
|
||||
* position.y = 1;
|
||||
* position.z = 1;
|
||||
*
|
||||
* } )().compute( particleCount );
|
||||
*
|
||||
* const particleMaterial = new THREE.SpriteNodeMaterial();
|
||||
* particleMaterial.positionNode = positionBuffer.toAttribute();
|
||||
*
|
||||
* renderer.computeAsync( computeInit );
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* @augments BufferNode
|
||||
*/
|
||||
class StorageBufferNode extends BufferNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'StorageBufferNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new storage buffer node.
|
||||
*
|
||||
* @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data.
|
||||
* @param {?(string|Struct)} [bufferType=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [bufferCount=0] - The buffer count.
|
||||
*/
|
||||
constructor( value, bufferType = null, bufferCount = 0 ) {
|
||||
|
||||
let nodeType, structTypeNode = null;
|
||||
|
||||
if ( bufferType && bufferType.isStruct ) {
|
||||
|
||||
nodeType = 'struct';
|
||||
structTypeNode = bufferType.layout;
|
||||
|
||||
if ( value.isStorageBufferAttribute || value.isStorageInstancedBufferAttribute ) {
|
||||
|
||||
bufferCount = value.count;
|
||||
|
||||
}
|
||||
|
||||
} else if ( bufferType === null && ( value.isStorageBufferAttribute || value.isStorageInstancedBufferAttribute ) ) {
|
||||
|
||||
nodeType = getTypeFromLength( value.itemSize );
|
||||
bufferCount = value.count;
|
||||
|
||||
} else {
|
||||
|
||||
nodeType = bufferType;
|
||||
|
||||
}
|
||||
|
||||
super( value, nodeType, bufferCount );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isStorageBufferNode = true;
|
||||
|
||||
|
||||
/**
|
||||
* The buffer struct type.
|
||||
*
|
||||
* @type {?StructTypeNode}
|
||||
* @default null
|
||||
*/
|
||||
this.structTypeNode = structTypeNode;
|
||||
|
||||
/**
|
||||
* The access type of the texture node.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'readWrite'
|
||||
*/
|
||||
this.access = NodeAccess.READ_WRITE;
|
||||
|
||||
/**
|
||||
* Whether the node is atomic or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.isAtomic = false;
|
||||
|
||||
/**
|
||||
* Whether the node represents a PBO or not.
|
||||
* Only relevant for WebGL.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.isPBO = false;
|
||||
|
||||
/**
|
||||
* A reference to the internal buffer attribute node.
|
||||
*
|
||||
* @type {?BufferAttributeNode}
|
||||
* @default null
|
||||
*/
|
||||
this._attribute = null;
|
||||
|
||||
/**
|
||||
* A reference to the internal varying node.
|
||||
*
|
||||
* @type {?VaryingNode}
|
||||
* @default null
|
||||
*/
|
||||
this._varying = null;
|
||||
|
||||
/**
|
||||
* `StorageBufferNode` sets this property to `true` by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
if ( value.isStorageBufferAttribute !== true && value.isStorageInstancedBufferAttribute !== true ) {
|
||||
|
||||
// TODO: Improve it, possibly adding a new property to the BufferAttribute to identify it as a storage buffer read-only attribute in Renderer
|
||||
|
||||
if ( value.isInstancedBufferAttribute ) value.isStorageInstancedBufferAttribute = true;
|
||||
else value.isStorageBufferAttribute = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the buffer data might be shared
|
||||
* and thus the hash should be shared as well.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The hash.
|
||||
*/
|
||||
getHash( builder ) {
|
||||
|
||||
if ( this.bufferCount === 0 ) {
|
||||
|
||||
let bufferData = builder.globalCache.getData( this.value );
|
||||
|
||||
if ( bufferData === undefined ) {
|
||||
|
||||
bufferData = {
|
||||
node: this
|
||||
};
|
||||
|
||||
builder.globalCache.setData( this.value, bufferData );
|
||||
|
||||
}
|
||||
|
||||
return bufferData.node.uuid;
|
||||
|
||||
}
|
||||
|
||||
return this.uuid;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'indirectStorageBuffer'` or `'storageBuffer'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return this.value.isIndirectStorageBufferAttribute ? 'indirectStorageBuffer' : 'storageBuffer';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables element access with the given index node.
|
||||
*
|
||||
* @param {IndexNode} indexNode - The index node.
|
||||
* @return {StorageArrayElementNode} A node representing the element access.
|
||||
*/
|
||||
element( indexNode ) {
|
||||
|
||||
return storageElement( this, indexNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether this node is a PBO or not. Only relevant for WebGL.
|
||||
*
|
||||
* @param {boolean} value - The value so set.
|
||||
* @return {StorageBufferNode} A reference to this node.
|
||||
*/
|
||||
setPBO( value ) {
|
||||
|
||||
this.isPBO = value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `isPBO` value.
|
||||
*
|
||||
* @return {boolean} Whether the node represents a PBO or not.
|
||||
*/
|
||||
getPBO() {
|
||||
|
||||
return this.isPBO;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the node access.
|
||||
*
|
||||
* @param {string} value - The node access.
|
||||
* @return {StorageBufferNode} A reference to this node.
|
||||
*/
|
||||
setAccess( value ) {
|
||||
|
||||
this.access = value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for configuring a read-only node access.
|
||||
*
|
||||
* @return {StorageBufferNode} A reference to this node.
|
||||
*/
|
||||
toReadOnly() {
|
||||
|
||||
return this.setAccess( NodeAccess.READ_ONLY );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether the node is atomic or not.
|
||||
*
|
||||
* @param {boolean} value - The atomic flag.
|
||||
* @return {StorageBufferNode} A reference to this node.
|
||||
*/
|
||||
setAtomic( value ) {
|
||||
|
||||
this.isAtomic = value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for making this node atomic.
|
||||
*
|
||||
* @return {StorageBufferNode} A reference to this node.
|
||||
*/
|
||||
toAtomic() {
|
||||
|
||||
return this.setAtomic( true );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns attribute data for this storage buffer node.
|
||||
*
|
||||
* @return {{attribute: BufferAttributeNode, varying: VaryingNode}} The attribute data.
|
||||
*/
|
||||
getAttributeData() {
|
||||
|
||||
if ( this._attribute === null ) {
|
||||
|
||||
this._attribute = bufferAttribute( this.value );
|
||||
this._varying = varying( this._attribute );
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
attribute: this._attribute,
|
||||
varying: this._varying
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type from the availability of storage buffers
|
||||
* and the attribute data.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
if ( this.structTypeNode !== null ) {
|
||||
|
||||
return this.structTypeNode.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
if ( builder.isAvailable( 'storageBuffer' ) || builder.isAvailable( 'indirectStorageBuffer' ) ) {
|
||||
|
||||
return super.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
const { attribute } = this.getAttributeData();
|
||||
|
||||
return attribute.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of a member of the struct.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} name - The name of the member.
|
||||
* @return {string} The type of the member.
|
||||
*/
|
||||
getMemberType( builder, name ) {
|
||||
|
||||
if ( this.structTypeNode !== null ) {
|
||||
|
||||
return this.structTypeNode.getMemberType( builder, name );
|
||||
|
||||
}
|
||||
|
||||
return 'void';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the storage buffer node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( builder ) {
|
||||
|
||||
if ( this.structTypeNode !== null ) this.structTypeNode.build( builder );
|
||||
|
||||
if ( builder.isAvailable( 'storageBuffer' ) || builder.isAvailable( 'indirectStorageBuffer' ) ) {
|
||||
|
||||
return super.generate( builder );
|
||||
|
||||
}
|
||||
|
||||
const { attribute, varying } = this.getAttributeData();
|
||||
|
||||
const output = varying.build( builder );
|
||||
|
||||
builder.registerTransform( output, attribute );
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default StorageBufferNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a storage buffer node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data.
|
||||
* @param {?(string|Struct)} [type=null] - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} [count=0] - The buffer count.
|
||||
* @returns {StorageBufferNode}
|
||||
*/
|
||||
export const storage = ( value, type = null, count = 0 ) => nodeObject( new StorageBufferNode( value, type, count ) );
|
||||
|
||||
/**
|
||||
* @tsl
|
||||
* @function
|
||||
* @deprecated since r171. Use `storage().setPBO( true )` instead.
|
||||
*
|
||||
* @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data.
|
||||
* @param {?string} type - The buffer type (e.g. `'vec3'`).
|
||||
* @param {number} count - The buffer count.
|
||||
* @returns {StorageBufferNode}
|
||||
*/
|
||||
export const storageObject = ( value, type, count ) => { // @deprecated, r171
|
||||
|
||||
console.warn( 'THREE.TSL: "storageObject()" is deprecated. Use "storage().setPBO( true )" instead.' );
|
||||
|
||||
return storage( value, type, count ).setPBO( true );
|
||||
|
||||
};
|
||||
242
app/node_modules/three/src/nodes/accessors/StorageTextureNode.js
generated
vendored
Normal file
242
app/node_modules/three/src/nodes/accessors/StorageTextureNode.js
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
import TextureNode from './TextureNode.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
import { NodeAccess } from '../core/constants.js';
|
||||
|
||||
/**
|
||||
* This special version of a texture node can be used to
|
||||
* write data into a storage texture with a compute shader.
|
||||
*
|
||||
* ```js
|
||||
* const storageTexture = new THREE.StorageTexture( width, height );
|
||||
*
|
||||
* const computeTexture = Fn( ( { storageTexture } ) => {
|
||||
*
|
||||
* const posX = instanceIndex.mod( width );
|
||||
* const posY = instanceIndex.div( width );
|
||||
* const indexUV = uvec2( posX, posY );
|
||||
*
|
||||
* // generate RGB values
|
||||
*
|
||||
* const r = 1;
|
||||
* const g = 1;
|
||||
* const b = 1;
|
||||
*
|
||||
* textureStore( storageTexture, indexUV, vec4( r, g, b, 1 ) ).toWriteOnly();
|
||||
*
|
||||
* } );
|
||||
*
|
||||
* const computeNode = computeTexture( { storageTexture } ).compute( width * height );
|
||||
* renderer.computeAsync( computeNode );
|
||||
* ```
|
||||
*
|
||||
* This node can only be used with a WebGPU backend.
|
||||
*
|
||||
* @augments TextureNode
|
||||
*/
|
||||
class StorageTextureNode extends TextureNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'StorageTextureNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new storage texture node.
|
||||
*
|
||||
* @param {StorageTexture} value - The storage texture.
|
||||
* @param {Node<vec2|vec3>} uvNode - The uv node.
|
||||
* @param {?Node} [storeNode=null] - The value node that should be stored in the texture.
|
||||
*/
|
||||
constructor( value, uvNode, storeNode = null ) {
|
||||
|
||||
super( value, uvNode );
|
||||
|
||||
/**
|
||||
* The value node that should be stored in the texture.
|
||||
*
|
||||
* @type {?Node}
|
||||
* @default null
|
||||
*/
|
||||
this.storeNode = storeNode;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isStorageTextureNode = true;
|
||||
|
||||
/**
|
||||
* The access type of the texture node.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'writeOnly'
|
||||
*/
|
||||
this.access = NodeAccess.WRITE_ONLY;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'storageTexture'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return 'storageTexture';
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
super.setup( builder );
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
properties.storeNode = this.storeNode;
|
||||
|
||||
return properties;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the node access.
|
||||
*
|
||||
* @param {string} value - The node access.
|
||||
* @return {StorageTextureNode} A reference to this node.
|
||||
*/
|
||||
setAccess( value ) {
|
||||
|
||||
this.access = value;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the storage node. If no `storeNode`
|
||||
* is defined, the texture node is generated as normal texture.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} output - The current output.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( builder, output ) {
|
||||
|
||||
let snippet;
|
||||
|
||||
if ( this.storeNode !== null ) {
|
||||
|
||||
snippet = this.generateStore( builder );
|
||||
|
||||
} else {
|
||||
|
||||
snippet = super.generate( builder, output );
|
||||
|
||||
}
|
||||
|
||||
return snippet;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for configuring a read/write node access.
|
||||
*
|
||||
* @return {StorageTextureNode} A reference to this node.
|
||||
*/
|
||||
toReadWrite() {
|
||||
|
||||
return this.setAccess( NodeAccess.READ_WRITE );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for configuring a read-only node access.
|
||||
*
|
||||
* @return {StorageTextureNode} A reference to this node.
|
||||
*/
|
||||
toReadOnly() {
|
||||
|
||||
return this.setAccess( NodeAccess.READ_ONLY );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for configuring a write-only node access.
|
||||
*
|
||||
* @return {StorageTextureNode} A reference to this node.
|
||||
*/
|
||||
toWriteOnly() {
|
||||
|
||||
return this.setAccess( NodeAccess.WRITE_ONLY );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the storage texture node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
generateStore( builder ) {
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
|
||||
const { uvNode, storeNode, depthNode } = properties;
|
||||
|
||||
const textureProperty = super.generate( builder, 'property' );
|
||||
const uvSnippet = uvNode.build( builder, 'uvec2' );
|
||||
const storeSnippet = storeNode.build( builder, 'vec4' );
|
||||
const depthSnippet = depthNode ? depthNode.build( builder, 'int' ) : null;
|
||||
|
||||
const snippet = builder.generateTextureStore( builder, textureProperty, uvSnippet, depthSnippet, storeSnippet );
|
||||
|
||||
builder.addLineFlowCode( snippet, this );
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
const newNode = super.clone();
|
||||
newNode.storeNode = this.storeNode;
|
||||
return newNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default StorageTextureNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a storage texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {StorageTexture} value - The storage texture.
|
||||
* @param {?Node<vec2|vec3>} uvNode - The uv node.
|
||||
* @param {?Node} [storeNode=null] - The value node that should be stored in the texture.
|
||||
* @returns {StorageTextureNode}
|
||||
*/
|
||||
export const storageTexture = /*@__PURE__*/ nodeProxy( StorageTextureNode ).setParameterLength( 1, 3 );
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Explain difference to `storageTexture()`.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {StorageTexture} value - The storage texture.
|
||||
* @param {Node<vec2|vec3>} uvNode - The uv node.
|
||||
* @param {?Node} [storeNode=null] - The value node that should be stored in the texture.
|
||||
* @returns {StorageTextureNode}
|
||||
*/
|
||||
export const textureStore = ( value, uvNode, storeNode ) => {
|
||||
|
||||
const node = storageTexture( value, uvNode, storeNode );
|
||||
|
||||
if ( storeNode !== null ) node.toStack();
|
||||
|
||||
return node;
|
||||
|
||||
};
|
||||
70
app/node_modules/three/src/nodes/accessors/Tangent.js
generated
vendored
Normal file
70
app/node_modules/three/src/nodes/accessors/Tangent.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { cameraViewMatrix } from './Camera.js';
|
||||
import { modelViewMatrix } from './ModelNode.js';
|
||||
import { Fn, vec4 } from '../tsl/TSLBase.js';
|
||||
import { tangentViewFrame } from './TangentUtils.js';
|
||||
import { directionToFaceDirection } from '../display/FrontFacingNode.js';
|
||||
|
||||
/**
|
||||
* TSL object that represents the tangent attribute of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec4>}
|
||||
*/
|
||||
export const tangentGeometry = /*@__PURE__*/ Fn( ( builder ) => {
|
||||
|
||||
if ( builder.geometry.hasAttribute( 'tangent' ) === false ) {
|
||||
|
||||
builder.geometry.computeTangents();
|
||||
|
||||
}
|
||||
|
||||
return attribute( 'tangent', 'vec4' );
|
||||
|
||||
} )();
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex tangent in local space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const tangentLocal = /*@__PURE__*/ tangentGeometry.xyz.toVar( 'tangentLocal' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex tangent in view space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const tangentView = /*@__PURE__*/ ( Fn( ( { subBuildFn, geometry, material } ) => {
|
||||
|
||||
let node;
|
||||
|
||||
if ( subBuildFn === 'VERTEX' || geometry.hasAttribute( 'tangent' ) ) {
|
||||
|
||||
node = modelViewMatrix.mul( vec4( tangentLocal, 0 ) ).xyz.toVarying( 'v_tangentView' ).normalize();
|
||||
|
||||
} else {
|
||||
|
||||
node = tangentViewFrame;
|
||||
|
||||
}
|
||||
|
||||
if ( material.flatShading !== true ) {
|
||||
|
||||
node = directionToFaceDirection( node );
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}, 'vec3' ).once( [ 'NORMAL', 'VERTEX' ] ) )().toVar( 'tangentView' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the vertex tangent in world space of the current rendered object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraViewMatrix ).toVarying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' );
|
||||
46
app/node_modules/three/src/nodes/accessors/TangentUtils.js
generated
vendored
Normal file
46
app/node_modules/three/src/nodes/accessors/TangentUtils.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import { uv as getUV } from './UV.js';
|
||||
import { positionView } from './Position.js';
|
||||
import { normalView } from './Normal.js';
|
||||
|
||||
// Normal Mapping Without Precomputed Tangents
|
||||
// http://www.thetenthplanet.de/archives/1180
|
||||
|
||||
const uv = getUV();
|
||||
|
||||
const q0 = positionView.dFdx();
|
||||
const q1 = positionView.dFdy();
|
||||
const st0 = uv.dFdx();
|
||||
const st1 = uv.dFdy();
|
||||
|
||||
const N = normalView;
|
||||
|
||||
const q1perp = q1.cross( N );
|
||||
const q0perp = N.cross( q0 );
|
||||
|
||||
const T = q1perp.mul( st0.x ).add( q0perp.mul( st1.x ) );
|
||||
const B = q1perp.mul( st0.y ).add( q0perp.mul( st1.y ) );
|
||||
|
||||
const det = T.dot( T ).max( B.dot( B ) );
|
||||
const scale = det.equal( 0.0 ).select( 0.0, det.inverseSqrt() );
|
||||
|
||||
/**
|
||||
* Tangent vector in view space, computed dynamically from geometry and UV derivatives.
|
||||
* Useful for normal mapping without precomputed tangents.
|
||||
*
|
||||
* Reference: http://www.thetenthplanet.de/archives/1180
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const tangentViewFrame = /*@__PURE__*/ T.mul( scale ).toVar( 'tangentViewFrame' );
|
||||
|
||||
/**
|
||||
* Bitangent vector in view space, computed dynamically from geometry and UV derivatives.
|
||||
* Complements the tangentViewFrame for constructing the tangent space basis.
|
||||
*
|
||||
* Reference: http://www.thetenthplanet.de/archives/1180
|
||||
*
|
||||
* @tsl
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
export const bitangentViewFrame = /*@__PURE__*/ B.mul( scale ).toVar( 'bitangentViewFrame' );
|
||||
186
app/node_modules/three/src/nodes/accessors/Texture3DNode.js
generated
vendored
Normal file
186
app/node_modules/three/src/nodes/accessors/Texture3DNode.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
import TextureNode from './TextureNode.js';
|
||||
import { nodeProxy, vec3, Fn, If, int } from '../tsl/TSLBase.js';
|
||||
import { textureSize } from './TextureSizeNode.js';
|
||||
|
||||
const normal = Fn( ( { texture, uv } ) => {
|
||||
|
||||
const epsilon = 0.0001;
|
||||
|
||||
const ret = vec3().toVar();
|
||||
|
||||
If( uv.x.lessThan( epsilon ), () => {
|
||||
|
||||
ret.assign( vec3( 1, 0, 0 ) );
|
||||
|
||||
} ).ElseIf( uv.y.lessThan( epsilon ), () => {
|
||||
|
||||
ret.assign( vec3( 0, 1, 0 ) );
|
||||
|
||||
} ).ElseIf( uv.z.lessThan( epsilon ), () => {
|
||||
|
||||
ret.assign( vec3( 0, 0, 1 ) );
|
||||
|
||||
} ).ElseIf( uv.x.greaterThan( 1 - epsilon ), () => {
|
||||
|
||||
ret.assign( vec3( - 1, 0, 0 ) );
|
||||
|
||||
} ).ElseIf( uv.y.greaterThan( 1 - epsilon ), () => {
|
||||
|
||||
ret.assign( vec3( 0, - 1, 0 ) );
|
||||
|
||||
} ).ElseIf( uv.z.greaterThan( 1 - epsilon ), () => {
|
||||
|
||||
ret.assign( vec3( 0, 0, - 1 ) );
|
||||
|
||||
} ).Else( () => {
|
||||
|
||||
const step = 0.01;
|
||||
|
||||
const x = texture.sample( uv.add( vec3( - step, 0.0, 0.0 ) ) ).r.sub( texture.sample( uv.add( vec3( step, 0.0, 0.0 ) ) ).r );
|
||||
const y = texture.sample( uv.add( vec3( 0.0, - step, 0.0 ) ) ).r.sub( texture.sample( uv.add( vec3( 0.0, step, 0.0 ) ) ).r );
|
||||
const z = texture.sample( uv.add( vec3( 0.0, 0.0, - step ) ) ).r.sub( texture.sample( uv.add( vec3( 0.0, 0.0, step ) ) ).r );
|
||||
|
||||
ret.assign( vec3( x, y, z ) );
|
||||
|
||||
} );
|
||||
|
||||
return ret.normalize();
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* This type of uniform node represents a 3D texture.
|
||||
*
|
||||
* @augments TextureNode
|
||||
*/
|
||||
class Texture3DNode extends TextureNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'Texture3DNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new 3D texture node.
|
||||
*
|
||||
* @param {Data3DTexture} value - The 3D texture.
|
||||
* @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
*/
|
||||
constructor( value, uvNode = null, levelNode = null ) {
|
||||
|
||||
super( value, uvNode, levelNode );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isTexture3DNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'texture3D'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return 'texture3D';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a default uv node which is in context of 3D textures a three-dimensional
|
||||
* uv node.
|
||||
*
|
||||
* @return {Node<vec3>} The default uv node.
|
||||
*/
|
||||
getDefaultUV() {
|
||||
|
||||
return vec3( 0.5, 0.5, 0.5 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten with an empty implementation since the `updateMatrix` flag is ignored
|
||||
* for 3D textures. The uv transformation matrix is not applied to 3D textures.
|
||||
*
|
||||
* @param {boolean} value - The update toggle.
|
||||
*/
|
||||
setUpdateMatrix( /*value*/ ) { } // Ignore .updateMatrix for 3d TextureNode
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return the unmodified uv node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {Node} uvNode - The uv node to setup.
|
||||
* @return {Node} The unmodified uv node.
|
||||
*/
|
||||
setupUV( builder, uvNode ) {
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true ) ) {
|
||||
|
||||
if ( this.sampler ) {
|
||||
|
||||
uvNode = uvNode.flipY();
|
||||
|
||||
} else {
|
||||
|
||||
uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return uvNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the uv code snippet.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {Node} uvNode - The uv node to generate code for.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generateUV( builder, uvNode ) {
|
||||
|
||||
return uvNode.build( builder, 'vec3' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO.
|
||||
*
|
||||
* @param {Node<vec3>} uvNode - The uv node .
|
||||
* @return {Node<vec3>} TODO.
|
||||
*/
|
||||
normal( uvNode ) {
|
||||
|
||||
return normal( { texture: this, uv: uvNode } );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Texture3DNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a 3D texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Data3DTexture} value - The 3D texture.
|
||||
* @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @returns {Texture3DNode}
|
||||
*/
|
||||
export const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ).setParameterLength( 1, 3 );
|
||||
92
app/node_modules/three/src/nodes/accessors/TextureBicubic.js
generated
vendored
Normal file
92
app/node_modules/three/src/nodes/accessors/TextureBicubic.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import { add, mul, div } from '../math/OperatorNode.js';
|
||||
import { floor, ceil, fract, pow } from '../math/MathNode.js';
|
||||
import { Fn, vec2, vec4, int } from '../tsl/TSLBase.js';
|
||||
import { maxMipLevel } from '../utils/MaxMipLevelNode.js';
|
||||
|
||||
// Mipped Bicubic Texture Filtering by N8
|
||||
// https://www.shadertoy.com/view/Dl2SDW
|
||||
|
||||
const bC = 1.0 / 6.0;
|
||||
|
||||
const w0 = ( a ) => mul( bC, mul( a, mul( a, a.negate().add( 3.0 ) ).sub( 3.0 ) ).add( 1.0 ) );
|
||||
|
||||
const w1 = ( a ) => mul( bC, mul( a, mul( a, mul( 3.0, a ).sub( 6.0 ) ) ).add( 4.0 ) );
|
||||
|
||||
const w2 = ( a ) => mul( bC, mul( a, mul( a, mul( - 3.0, a ).add( 3.0 ) ).add( 3.0 ) ).add( 1.0 ) );
|
||||
|
||||
const w3 = ( a ) => mul( bC, pow( a, 3 ) );
|
||||
|
||||
const g0 = ( a ) => w0( a ).add( w1( a ) );
|
||||
|
||||
const g1 = ( a ) => w2( a ).add( w3( a ) );
|
||||
|
||||
// h0 and h1 are the two offset functions
|
||||
const h0 = ( a ) => add( - 1.0, w1( a ).div( w0( a ).add( w1( a ) ) ) );
|
||||
|
||||
const h1 = ( a ) => add( 1.0, w3( a ).div( w2( a ).add( w3( a ) ) ) );
|
||||
|
||||
const bicubic = ( textureNode, texelSize, lod ) => {
|
||||
|
||||
const uv = textureNode.uvNode;
|
||||
const uvScaled = mul( uv, texelSize.zw ).add( 0.5 );
|
||||
|
||||
const iuv = floor( uvScaled );
|
||||
const fuv = fract( uvScaled );
|
||||
|
||||
const g0x = g0( fuv.x );
|
||||
const g1x = g1( fuv.x );
|
||||
const h0x = h0( fuv.x );
|
||||
const h1x = h1( fuv.x );
|
||||
const h0y = h0( fuv.y );
|
||||
const h1y = h1( fuv.y );
|
||||
|
||||
const p0 = vec2( iuv.x.add( h0x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy );
|
||||
const p1 = vec2( iuv.x.add( h1x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy );
|
||||
const p2 = vec2( iuv.x.add( h0x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy );
|
||||
const p3 = vec2( iuv.x.add( h1x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy );
|
||||
|
||||
const a = g0( fuv.y ).mul( add( g0x.mul( textureNode.sample( p0 ).level( lod ) ), g1x.mul( textureNode.sample( p1 ).level( lod ) ) ) );
|
||||
const b = g1( fuv.y ).mul( add( g0x.mul( textureNode.sample( p2 ).level( lod ) ), g1x.mul( textureNode.sample( p3 ).level( lod ) ) ) );
|
||||
|
||||
return a.add( b );
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies mipped bicubic texture filtering to the given texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {TextureNode} textureNode - The texture node that should be filtered.
|
||||
* @param {Node<float>} lodNode - Defines the LOD to sample from.
|
||||
* @return {Node} The filtered texture sample.
|
||||
*/
|
||||
export const textureBicubicLevel = /*@__PURE__*/ Fn( ( [ textureNode, lodNode ] ) => {
|
||||
|
||||
const fLodSize = vec2( textureNode.size( int( lodNode ) ) );
|
||||
const cLodSize = vec2( textureNode.size( int( lodNode.add( 1.0 ) ) ) );
|
||||
const fLodSizeInv = div( 1.0, fLodSize );
|
||||
const cLodSizeInv = div( 1.0, cLodSize );
|
||||
const fSample = bicubic( textureNode, vec4( fLodSizeInv, fLodSize ), floor( lodNode ) );
|
||||
const cSample = bicubic( textureNode, vec4( cLodSizeInv, cLodSize ), ceil( lodNode ) );
|
||||
|
||||
return fract( lodNode ).mix( fSample, cSample );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Applies mipped bicubic texture filtering to the given texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {TextureNode} textureNode - The texture node that should be filtered.
|
||||
* @param {Node<float>} [strength] - Defines the strength of the bicubic filtering.
|
||||
* @return {Node} The filtered texture sample.
|
||||
*/
|
||||
export const textureBicubic = /*@__PURE__*/ Fn( ( [ textureNode, strength ] ) => {
|
||||
|
||||
const lod = strength.mul( maxMipLevel( textureNode ) );
|
||||
|
||||
return textureBicubicLevel( textureNode, lod );
|
||||
|
||||
} );
|
||||
829
app/node_modules/three/src/nodes/accessors/TextureNode.js
generated
vendored
Normal file
829
app/node_modules/three/src/nodes/accessors/TextureNode.js
generated
vendored
Normal file
@@ -0,0 +1,829 @@
|
||||
import UniformNode, { uniform } from '../core/UniformNode.js';
|
||||
import { uv } from './UV.js';
|
||||
import { textureSize } from './TextureSizeNode.js';
|
||||
import { colorSpaceToWorking } from '../display/ColorSpaceNode.js';
|
||||
import { expression } from '../code/ExpressionNode.js';
|
||||
import { maxMipLevel } from '../utils/MaxMipLevelNode.js';
|
||||
import { nodeProxy, vec3, nodeObject, int } from '../tsl/TSLBase.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
|
||||
import { IntType, NearestFilter, UnsignedIntType } from '../../constants.js';
|
||||
|
||||
import { Texture } from '../../textures/Texture.js';
|
||||
|
||||
const EmptyTexture = /*@__PURE__*/ new Texture();
|
||||
|
||||
/**
|
||||
* This type of uniform node represents a 2D texture.
|
||||
*
|
||||
* @augments UniformNode
|
||||
*/
|
||||
class TextureNode extends UniformNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'TextureNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new texture node.
|
||||
*
|
||||
* @param {Texture} [value=EmptyTexture] - The texture.
|
||||
* @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
*/
|
||||
constructor( value = EmptyTexture, uvNode = null, levelNode = null, biasNode = null ) {
|
||||
|
||||
super( value );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isTextureNode = true;
|
||||
|
||||
/**
|
||||
* Represents the texture coordinates.
|
||||
*
|
||||
* @type {?Node<vec2|vec3>}
|
||||
* @default null
|
||||
*/
|
||||
this.uvNode = uvNode;
|
||||
|
||||
/**
|
||||
* Represents the mip level that should be selected.
|
||||
*
|
||||
* @type {?Node<int>}
|
||||
* @default null
|
||||
*/
|
||||
this.levelNode = levelNode;
|
||||
|
||||
/**
|
||||
* Represents the bias to be applied during level-of-detail computation.
|
||||
*
|
||||
* @type {?Node<float>}
|
||||
* @default null
|
||||
*/
|
||||
this.biasNode = biasNode;
|
||||
|
||||
/**
|
||||
* Represents a reference value a texture sample is compared to.
|
||||
*
|
||||
* @type {?Node<float>}
|
||||
* @default null
|
||||
*/
|
||||
this.compareNode = null;
|
||||
|
||||
/**
|
||||
* When using texture arrays, the depth node defines the layer to select.
|
||||
*
|
||||
* @type {?Node<int>}
|
||||
* @default null
|
||||
*/
|
||||
this.depthNode = null;
|
||||
|
||||
/**
|
||||
* When defined, a texture is sampled using explicit gradients.
|
||||
*
|
||||
* @type {?Array<Node<vec2>>}
|
||||
* @default null
|
||||
*/
|
||||
this.gradNode = null;
|
||||
|
||||
/**
|
||||
* Whether texture values should be sampled or fetched.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.sampler = true;
|
||||
|
||||
/**
|
||||
* Whether the uv transformation matrix should be
|
||||
* automatically updated or not. Use `setUpdateMatrix()`
|
||||
* if you want to change the value of the property.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.updateMatrix = false;
|
||||
|
||||
/**
|
||||
* By default the `update()` method is not executed. `setUpdateMatrix()`
|
||||
* sets the value to `frame` when the uv transformation matrix should
|
||||
* automatically be updated.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'none'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.NONE;
|
||||
|
||||
/**
|
||||
* The reference node.
|
||||
*
|
||||
* @type {?Node}
|
||||
* @default null
|
||||
*/
|
||||
this.referenceNode = null;
|
||||
|
||||
/**
|
||||
* The texture value is stored in a private property.
|
||||
*
|
||||
* @private
|
||||
* @type {Texture}
|
||||
*/
|
||||
this._value = value;
|
||||
|
||||
/**
|
||||
* The uniform node that represents the uv transformation matrix.
|
||||
*
|
||||
* @private
|
||||
* @type {?UniformNode<mat3>}
|
||||
*/
|
||||
this._matrixUniform = null;
|
||||
|
||||
this.setUpdateMatrix( uvNode === null );
|
||||
|
||||
}
|
||||
|
||||
set value( value ) {
|
||||
|
||||
if ( this.referenceNode ) {
|
||||
|
||||
this.referenceNode.value = value;
|
||||
|
||||
} else {
|
||||
|
||||
this._value = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The texture value.
|
||||
*
|
||||
* @type {Texture}
|
||||
*/
|
||||
get value() {
|
||||
|
||||
return this.referenceNode ? this.referenceNode.value : this._value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten since the uniform hash is defined by the texture's UUID.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The uniform hash.
|
||||
*/
|
||||
getUniformHash( /*builder*/ ) {
|
||||
|
||||
return this.value.uuid;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten since the node type is inferred from the texture type.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( /*builder*/ ) {
|
||||
|
||||
if ( this.value.isDepthTexture === true ) return 'float';
|
||||
|
||||
if ( this.value.type === UnsignedIntType ) {
|
||||
|
||||
return 'uvec4';
|
||||
|
||||
} else if ( this.value.type === IntType ) {
|
||||
|
||||
return 'ivec4';
|
||||
|
||||
}
|
||||
|
||||
return 'vec4';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation to return a fixed value `'texture'`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( /*builder*/ ) {
|
||||
|
||||
return 'texture';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a default uvs based on the current texture's channel.
|
||||
*
|
||||
* @return {AttributeNode<vec2>} The default uvs.
|
||||
*/
|
||||
getDefaultUV() {
|
||||
|
||||
return uv( this.value.channel );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to always return the texture reference of the node.
|
||||
*
|
||||
* @param {any} state - This method can be invocated in different contexts so `state` can refer to any object type.
|
||||
* @return {Texture} The texture reference.
|
||||
*/
|
||||
updateReference( /*state*/ ) {
|
||||
|
||||
return this.value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given uv node with the texture transformation matrix.
|
||||
*
|
||||
* @param {Node} uvNode - The uv node to transform.
|
||||
* @return {Node} The transformed uv node.
|
||||
*/
|
||||
getTransformedUV( uvNode ) {
|
||||
|
||||
if ( this._matrixUniform === null ) this._matrixUniform = uniform( this.value.matrix );
|
||||
|
||||
return this._matrixUniform.mul( vec3( uvNode, 1 ) ).xy;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether the uv transformation matrix should automatically be updated or not.
|
||||
*
|
||||
* @param {boolean} value - The update toggle.
|
||||
* @return {TextureNode} A reference to this node.
|
||||
*/
|
||||
setUpdateMatrix( value ) {
|
||||
|
||||
this.updateMatrix = value;
|
||||
this.updateType = value ? NodeUpdateType.OBJECT : NodeUpdateType.NONE;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the uv node. Depending on the backend as well as texture's image and type, it might be necessary
|
||||
* to modify the uv node for correct sampling.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {Node} uvNode - The uv node to setup.
|
||||
* @return {Node} The updated uv node.
|
||||
*/
|
||||
setupUV( builder, uvNode ) {
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
if ( builder.isFlipY() && ( ( texture.image instanceof ImageBitmap && texture.flipY === true ) || texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true || texture.isDepthTexture === true ) ) {
|
||||
|
||||
if ( this.sampler ) {
|
||||
|
||||
uvNode = uvNode.flipY();
|
||||
|
||||
} else {
|
||||
|
||||
uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return uvNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups texture node by preparing the internal nodes for code generation.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
properties.referenceNode = this.referenceNode;
|
||||
|
||||
//
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
if ( ! texture || texture.isTexture !== true ) {
|
||||
|
||||
throw new Error( 'THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().' );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
let uvNode = this.uvNode;
|
||||
|
||||
if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) {
|
||||
|
||||
uvNode = builder.context.getUV( this, builder );
|
||||
|
||||
}
|
||||
|
||||
if ( ! uvNode ) uvNode = this.getDefaultUV();
|
||||
|
||||
if ( this.updateMatrix === true ) {
|
||||
|
||||
uvNode = this.getTransformedUV( uvNode );
|
||||
|
||||
}
|
||||
|
||||
uvNode = this.setupUV( builder, uvNode );
|
||||
|
||||
//
|
||||
|
||||
let levelNode = this.levelNode;
|
||||
|
||||
if ( levelNode === null && builder.context.getTextureLevel ) {
|
||||
|
||||
levelNode = builder.context.getTextureLevel( this );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
properties.uvNode = uvNode;
|
||||
properties.levelNode = levelNode;
|
||||
properties.biasNode = this.biasNode;
|
||||
properties.compareNode = this.compareNode;
|
||||
properties.gradNode = this.gradNode;
|
||||
properties.depthNode = this.depthNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the uv code snippet.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {Node} uvNode - The uv node to generate code for.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generateUV( builder, uvNode ) {
|
||||
|
||||
return uvNode.build( builder, this.sampler === true ? 'vec2' : 'ivec2' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the snippet for the texture sampling.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} textureProperty - The texture property.
|
||||
* @param {string} uvSnippet - The uv snippet.
|
||||
* @param {?string} levelSnippet - The level snippet.
|
||||
* @param {?string} biasSnippet - The bias snippet.
|
||||
* @param {?string} depthSnippet - The depth snippet.
|
||||
* @param {?string} compareSnippet - The compare snippet.
|
||||
* @param {?Array<string>} gradSnippet - The grad snippet.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ) {
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
let snippet;
|
||||
|
||||
if ( levelSnippet ) {
|
||||
|
||||
snippet = builder.generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet );
|
||||
|
||||
} else if ( biasSnippet ) {
|
||||
|
||||
snippet = builder.generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet );
|
||||
|
||||
} else if ( gradSnippet ) {
|
||||
|
||||
snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet );
|
||||
|
||||
} else if ( compareSnippet ) {
|
||||
|
||||
snippet = builder.generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet );
|
||||
|
||||
} else if ( this.sampler === false ) {
|
||||
|
||||
snippet = builder.generateTextureLoad( texture, textureProperty, uvSnippet, depthSnippet );
|
||||
|
||||
} else {
|
||||
|
||||
snippet = builder.generateTexture( texture, textureProperty, uvSnippet, depthSnippet );
|
||||
|
||||
}
|
||||
|
||||
return snippet;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the code snippet of the texture node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} output - The current output.
|
||||
* @return {string} The generated code snippet.
|
||||
*/
|
||||
generate( builder, output ) {
|
||||
|
||||
const texture = this.value;
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
const textureProperty = super.generate( builder, 'property' );
|
||||
|
||||
if ( /^sampler/.test( output ) ) {
|
||||
|
||||
return textureProperty + '_sampler';
|
||||
|
||||
} else if ( builder.isReference( output ) ) {
|
||||
|
||||
return textureProperty;
|
||||
|
||||
} else {
|
||||
|
||||
const nodeData = builder.getDataFromNode( this );
|
||||
|
||||
let propertyName = nodeData.propertyName;
|
||||
|
||||
if ( propertyName === undefined ) {
|
||||
|
||||
const { uvNode, levelNode, biasNode, compareNode, depthNode, gradNode } = properties;
|
||||
|
||||
const uvSnippet = this.generateUV( builder, uvNode );
|
||||
const levelSnippet = levelNode ? levelNode.build( builder, 'float' ) : null;
|
||||
const biasSnippet = biasNode ? biasNode.build( builder, 'float' ) : null;
|
||||
const depthSnippet = depthNode ? depthNode.build( builder, 'int' ) : null;
|
||||
const compareSnippet = compareNode ? compareNode.build( builder, 'float' ) : null;
|
||||
const gradSnippet = gradNode ? [ gradNode[ 0 ].build( builder, 'vec2' ), gradNode[ 1 ].build( builder, 'vec2' ) ] : null;
|
||||
|
||||
const nodeVar = builder.getVarFromNode( this );
|
||||
|
||||
propertyName = builder.getPropertyName( nodeVar );
|
||||
|
||||
const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet );
|
||||
|
||||
builder.addLineFlowCode( `${propertyName} = ${snippet}`, this );
|
||||
|
||||
nodeData.snippet = snippet;
|
||||
nodeData.propertyName = propertyName;
|
||||
|
||||
}
|
||||
|
||||
let snippet = propertyName;
|
||||
const nodeType = this.getNodeType( builder );
|
||||
|
||||
if ( builder.needsToWorkingColorSpace( texture ) ) {
|
||||
|
||||
snippet = colorSpaceToWorking( expression( snippet, nodeType ), texture.colorSpace ).setup( builder ).build( builder, nodeType );
|
||||
|
||||
}
|
||||
|
||||
return builder.format( snippet, nodeType, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sampler value.
|
||||
*
|
||||
* @param {boolean} value - The sampler value to set.
|
||||
* @return {TextureNode} A reference to this texture node.
|
||||
*/
|
||||
setSampler( value ) {
|
||||
|
||||
this.sampler = value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sampler value.
|
||||
*
|
||||
* @return {boolean} The sampler value.
|
||||
*/
|
||||
getSampler() {
|
||||
|
||||
return this.sampler;
|
||||
|
||||
}
|
||||
|
||||
// @TODO: Move to TSL
|
||||
|
||||
/**
|
||||
* @function
|
||||
* @deprecated since r172. Use {@link TextureNode#sample} instead.
|
||||
*
|
||||
* @param {Node} uvNode - The uv node.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
uv( uvNode ) { // @deprecated, r172
|
||||
|
||||
console.warn( 'THREE.TextureNode: .uv() has been renamed. Use .sample() instead.' );
|
||||
|
||||
return this.sample( uvNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples the texture with the given uv node.
|
||||
*
|
||||
* @param {Node} uvNode - The uv node.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
sample( uvNode ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.uvNode = nodeObject( uvNode );
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples a blurred version of the texture by defining an internal bias.
|
||||
*
|
||||
* @param {Node<float>} amountNode - How blurred the texture should be.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
blur( amountNode ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.biasNode = nodeObject( amountNode ).mul( maxMipLevel( textureNode ) );
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
const map = textureNode.value;
|
||||
|
||||
if ( textureNode.generateMipmaps === false && ( map && map.generateMipmaps === false || map.minFilter === NearestFilter || map.magFilter === NearestFilter ) ) {
|
||||
|
||||
console.warn( 'THREE.TSL: texture().blur() requires mipmaps and sampling. Use .generateMipmaps=true and .minFilter/.magFilter=THREE.LinearFilter in the Texture.' );
|
||||
|
||||
textureNode.biasNode = null;
|
||||
|
||||
}
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples a specific mip of the texture.
|
||||
*
|
||||
* @param {Node<int>} levelNode - The mip level to sample.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
level( levelNode ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.levelNode = nodeObject( levelNode );
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the texture size of the requested level.
|
||||
*
|
||||
* @param {Node<int>} levelNode - The level to compute the size for.
|
||||
* @return {TextureSizeNode} The texture size.
|
||||
*/
|
||||
size( levelNode ) {
|
||||
|
||||
return textureSize( this, levelNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples the texture with the given bias.
|
||||
*
|
||||
* @param {Node<float>} biasNode - The bias node.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
bias( biasNode ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.biasNode = nodeObject( biasNode );
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples the texture by executing a compare operation.
|
||||
*
|
||||
* @param {Node<float>} compareNode - The node that defines the compare value.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
compare( compareNode ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.compareNode = nodeObject( compareNode );
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples the texture using an explicit gradient.
|
||||
*
|
||||
* @param {Node<vec2>} gradNodeX - The gradX node.
|
||||
* @param {Node<vec2>} gradNodeY - The gradY node.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
grad( gradNodeX, gradNodeY ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.gradNode = [ nodeObject( gradNodeX ), nodeObject( gradNodeY ) ];
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Samples the texture by defining a depth node.
|
||||
*
|
||||
* @param {Node<int>} depthNode - The depth node.
|
||||
* @return {TextureNode} A texture node representing the texture sample.
|
||||
*/
|
||||
depth( depthNode ) {
|
||||
|
||||
const textureNode = this.clone();
|
||||
textureNode.depthNode = nodeObject( depthNode );
|
||||
textureNode.referenceNode = this.getSelf();
|
||||
|
||||
return nodeObject( textureNode );
|
||||
|
||||
}
|
||||
|
||||
// --
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.value = this.value.toJSON( data.meta ).uuid;
|
||||
data.sampler = this.sampler;
|
||||
data.updateMatrix = this.updateMatrix;
|
||||
data.updateType = this.updateType;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.value = data.meta.textures[ data.value ];
|
||||
this.sampler = data.sampler;
|
||||
this.updateMatrix = data.updateMatrix;
|
||||
this.updateType = data.updateType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The update is used to implement the update of the uv transformation matrix.
|
||||
*/
|
||||
update() {
|
||||
|
||||
const texture = this.value;
|
||||
const matrixUniform = this._matrixUniform;
|
||||
|
||||
if ( matrixUniform !== null ) matrixUniform.value = texture.matrix;
|
||||
|
||||
if ( texture.matrixAutoUpdate === true ) {
|
||||
|
||||
texture.updateMatrix();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the texture node.
|
||||
*
|
||||
* @return {TextureNode} The cloned texture node.
|
||||
*/
|
||||
clone() {
|
||||
|
||||
const newNode = new this.constructor( this.value, this.uvNode, this.levelNode, this.biasNode );
|
||||
newNode.sampler = this.sampler;
|
||||
newNode.depthNode = this.depthNode;
|
||||
newNode.compareNode = this.compareNode;
|
||||
newNode.gradNode = this.gradNode;
|
||||
|
||||
return newNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TextureNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Texture} value - The texture.
|
||||
* @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
* @returns {TextureNode}
|
||||
*/
|
||||
const textureBase = /*@__PURE__*/ nodeProxy( TextureNode ).setParameterLength( 1, 4 ).setName( 'texture' );
|
||||
|
||||
/**
|
||||
* TSL function for creating a texture node or sample a texture node already existing.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Texture|TextureNode} [value=EmptyTexture] - The texture.
|
||||
* @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
* @returns {TextureNode}
|
||||
*/
|
||||
export const texture = ( value = EmptyTexture, uvNode = null, levelNode = null, biasNode = null ) => {
|
||||
|
||||
let textureNode;
|
||||
|
||||
if ( value && value.isTextureNode === true ) {
|
||||
|
||||
textureNode = nodeObject( value.clone() );
|
||||
textureNode.referenceNode = value.getSelf(); // Ensure the reference is set to the original node
|
||||
|
||||
if ( uvNode !== null ) textureNode.uvNode = nodeObject( uvNode );
|
||||
if ( levelNode !== null ) textureNode.levelNode = nodeObject( levelNode );
|
||||
if ( biasNode !== null ) textureNode.biasNode = nodeObject( biasNode );
|
||||
|
||||
} else {
|
||||
|
||||
textureNode = textureBase( value, uvNode, levelNode, biasNode );
|
||||
|
||||
}
|
||||
|
||||
return textureNode;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* TSL function for creating a uniform texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Texture} value - The texture.
|
||||
* @returns {TextureNode}
|
||||
*/
|
||||
export const uniformTexture = ( value = EmptyTexture ) => texture( value );
|
||||
|
||||
/**
|
||||
* TSL function for creating a texture node that fetches/loads texels without interpolation.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?Texture|TextureNode} [value=EmptyTexture] - The texture.
|
||||
* @param {?Node<vec2|vec3>} [uvNode=null] - The uv node.
|
||||
* @param {?Node<int>} [levelNode=null] - The level node.
|
||||
* @param {?Node<float>} [biasNode=null] - The bias node.
|
||||
* @returns {TextureNode}
|
||||
*/
|
||||
export const textureLoad = ( ...params ) => texture( ...params ).setSampler( false );
|
||||
|
||||
//export const textureLevel = ( value, uv, level ) => texture( value, uv ).level( level );
|
||||
|
||||
/**
|
||||
* Converts a texture or texture node to a sampler.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {TextureNode|Texture} value - The texture or texture node to convert.
|
||||
* @returns {Node}
|
||||
*/
|
||||
export const sampler = ( value ) => ( value.isNode === true ? value : texture( value ) ).convert( 'sampler' );
|
||||
|
||||
/**
|
||||
* Converts a texture or texture node to a sampler comparison.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {TextureNode|Texture} value - The texture or texture node to convert.
|
||||
* @returns {Node}
|
||||
*/
|
||||
export const samplerComparison = ( value ) => ( value.isNode === true ? value : texture( value ) ).convert( 'samplerComparison' );
|
||||
77
app/node_modules/three/src/nodes/accessors/TextureSizeNode.js
generated
vendored
Normal file
77
app/node_modules/three/src/nodes/accessors/TextureSizeNode.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* A node that represents the dimensions of a texture. The texture size is
|
||||
* retrieved in the shader via built-in shader functions like `textureDimensions()`
|
||||
* or `textureSize()`.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class TextureSizeNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'TextureSizeNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new texture size node.
|
||||
*
|
||||
* @param {TextureNode} textureNode - A texture node which size should be retrieved.
|
||||
* @param {?Node<int>} [levelNode=null] - A level node which defines the requested mip.
|
||||
*/
|
||||
constructor( textureNode, levelNode = null ) {
|
||||
|
||||
super( 'uvec2' );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isTextureSizeNode = true;
|
||||
|
||||
/**
|
||||
* A texture node which size should be retrieved.
|
||||
*
|
||||
* @type {TextureNode}
|
||||
*/
|
||||
this.textureNode = textureNode;
|
||||
|
||||
/**
|
||||
* A level node which defines the requested mip.
|
||||
*
|
||||
* @type {Node<int>}
|
||||
* @default null
|
||||
*/
|
||||
this.levelNode = levelNode;
|
||||
|
||||
}
|
||||
|
||||
generate( builder, output ) {
|
||||
|
||||
const textureProperty = this.textureNode.build( builder, 'property' );
|
||||
const level = this.levelNode === null ? '0' : this.levelNode.build( builder, 'int' );
|
||||
|
||||
return builder.format( `${ builder.getMethod( 'textureDimensions' ) }( ${ textureProperty }, ${ level } )`, this.getNodeType( builder ), output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TextureSizeNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a texture size node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {TextureNode} textureNode - A texture node which size should be retrieved.
|
||||
* @param {?Node<int>} [levelNode=null] - A level node which defines the requested mip.
|
||||
* @returns {TextureSizeNode}
|
||||
*/
|
||||
export const textureSize = /*@__PURE__*/ nodeProxy( TextureSizeNode ).setParameterLength( 1, 2 );
|
||||
11
app/node_modules/three/src/nodes/accessors/UV.js
generated
vendored
Normal file
11
app/node_modules/three/src/nodes/accessors/UV.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
|
||||
/**
|
||||
* TSL function for creating an uv attribute node with the given index.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {number} [index=0] - The uv index.
|
||||
* @return {AttributeNode<vec2>} The uv attribute node.
|
||||
*/
|
||||
export const uv = ( index = 0 ) => attribute( 'uv' + ( index > 0 ? index : '' ), 'vec2' );
|
||||
348
app/node_modules/three/src/nodes/accessors/UniformArrayNode.js
generated
vendored
Normal file
348
app/node_modules/three/src/nodes/accessors/UniformArrayNode.js
generated
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { getValueType } from '../core/NodeUtils.js';
|
||||
import ArrayElementNode from '../utils/ArrayElementNode.js';
|
||||
import BufferNode from './BufferNode.js';
|
||||
|
||||
/**
|
||||
* Represents the element access on uniform array nodes.
|
||||
*
|
||||
* @augments ArrayElementNode
|
||||
*/
|
||||
class UniformArrayElementNode extends ArrayElementNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'UniformArrayElementNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new buffer node.
|
||||
*
|
||||
* @param {UniformArrayNode} uniformArrayNode - The uniform array node to access.
|
||||
* @param {IndexNode} indexNode - The index data that define the position of the accessed element in the array.
|
||||
*/
|
||||
constructor( uniformArrayNode, indexNode ) {
|
||||
|
||||
super( uniformArrayNode, indexNode );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isArrayBufferElementNode = true;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const snippet = super.generate( builder );
|
||||
const type = this.getNodeType();
|
||||
const paddedType = this.node.getPaddedType();
|
||||
|
||||
return builder.format( snippet, paddedType, type );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link BufferNode} this module represents array-like data as
|
||||
* uniform buffers. Unlike {@link BufferNode}, it can handle more common
|
||||
* data types in the array (e.g `three.js` primitives) and automatically
|
||||
* manage buffer padding. It should be the first choice when working with
|
||||
* uniforms buffers.
|
||||
* ```js
|
||||
* const tintColors = uniformArray( [
|
||||
* new Color( 1, 0, 0 ),
|
||||
* new Color( 0, 1, 0 ),
|
||||
* new Color( 0, 0, 1 )
|
||||
* ], 'color' );
|
||||
*
|
||||
* const redColor = tintColors.element( 0 );
|
||||
*
|
||||
* @augments BufferNode
|
||||
*/
|
||||
class UniformArrayNode extends BufferNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'UniformArrayNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new uniform array node.
|
||||
*
|
||||
* @param {Array<any>} value - Array holding the buffer data.
|
||||
* @param {?string} [elementType=null] - The data type of a buffer element.
|
||||
*/
|
||||
constructor( value, elementType = null ) {
|
||||
|
||||
super( null );
|
||||
|
||||
/**
|
||||
* Array holding the buffer data. Unlike {@link BufferNode}, the array can
|
||||
* hold number primitives as well as three.js objects like vectors, matrices
|
||||
* or colors.
|
||||
*
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
this.array = value;
|
||||
|
||||
/**
|
||||
* The data type of an array element.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.elementType = elementType === null ? getValueType( value[ 0 ] ) : elementType;
|
||||
|
||||
/**
|
||||
* The padded type. Uniform buffers must conform to a certain buffer layout
|
||||
* so a separate type is computed to ensure correct buffer size.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.paddedType = this.getPaddedType();
|
||||
|
||||
/**
|
||||
* Overwritten since uniform array nodes are updated per render.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'render'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.RENDER;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isArrayBufferNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type is inferred from the
|
||||
* {@link UniformArrayNode#paddedType}.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( /*builder*/ ) {
|
||||
|
||||
return this.paddedType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The data type of the array elements.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The element type.
|
||||
*/
|
||||
getElementType() {
|
||||
|
||||
return this.elementType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the padded type based on the element type.
|
||||
*
|
||||
* @return {string} The padded type.
|
||||
*/
|
||||
getPaddedType() {
|
||||
|
||||
const elementType = this.elementType;
|
||||
|
||||
let paddedType = 'vec4';
|
||||
|
||||
if ( elementType === 'mat2' ) {
|
||||
|
||||
paddedType = 'mat2';
|
||||
|
||||
} else if ( /mat/.test( elementType ) === true ) {
|
||||
|
||||
paddedType = 'mat4';
|
||||
|
||||
} else if ( elementType.charAt( 0 ) === 'i' ) {
|
||||
|
||||
paddedType = 'ivec4';
|
||||
|
||||
} else if ( elementType.charAt( 0 ) === 'u' ) {
|
||||
|
||||
paddedType = 'uvec4';
|
||||
|
||||
}
|
||||
|
||||
return paddedType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The update makes sure to correctly transfer the data from the (complex) objects
|
||||
* in the array to the internal, correctly padded value buffer.
|
||||
*
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
*/
|
||||
update( /*frame*/ ) {
|
||||
|
||||
const { array, value } = this;
|
||||
|
||||
const elementType = this.elementType;
|
||||
|
||||
if ( elementType === 'float' || elementType === 'int' || elementType === 'uint' ) {
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
const index = i * 4;
|
||||
|
||||
value[ index ] = array[ i ];
|
||||
|
||||
}
|
||||
|
||||
} else if ( elementType === 'color' ) {
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
const index = i * 4;
|
||||
const vector = array[ i ];
|
||||
|
||||
value[ index ] = vector.r;
|
||||
value[ index + 1 ] = vector.g;
|
||||
value[ index + 2 ] = vector.b || 0;
|
||||
//value[ index + 3 ] = vector.a || 0;
|
||||
|
||||
}
|
||||
|
||||
} else if ( elementType === 'mat2' ) {
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
const index = i * 4;
|
||||
const matrix = array[ i ];
|
||||
|
||||
value[ index ] = matrix.elements[ 0 ];
|
||||
value[ index + 1 ] = matrix.elements[ 1 ];
|
||||
value[ index + 2 ] = matrix.elements[ 2 ];
|
||||
value[ index + 3 ] = matrix.elements[ 3 ];
|
||||
|
||||
}
|
||||
|
||||
} else if ( elementType === 'mat3' ) {
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
const index = i * 16;
|
||||
const matrix = array[ i ];
|
||||
|
||||
value[ index ] = matrix.elements[ 0 ];
|
||||
value[ index + 1 ] = matrix.elements[ 1 ];
|
||||
value[ index + 2 ] = matrix.elements[ 2 ];
|
||||
|
||||
value[ index + 4 ] = matrix.elements[ 3 ];
|
||||
value[ index + 5 ] = matrix.elements[ 4 ];
|
||||
value[ index + 6 ] = matrix.elements[ 5 ];
|
||||
|
||||
value[ index + 8 ] = matrix.elements[ 6 ];
|
||||
value[ index + 9 ] = matrix.elements[ 7 ];
|
||||
value[ index + 10 ] = matrix.elements[ 8 ];
|
||||
|
||||
value[ index + 15 ] = 1;
|
||||
|
||||
}
|
||||
|
||||
} else if ( elementType === 'mat4' ) {
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
const index = i * 16;
|
||||
const matrix = array[ i ];
|
||||
|
||||
for ( let i = 0; i < matrix.elements.length; i ++ ) {
|
||||
|
||||
value[ index + i ] = matrix.elements[ i ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
const index = i * 4;
|
||||
const vector = array[ i ];
|
||||
|
||||
value[ index ] = vector.x;
|
||||
value[ index + 1 ] = vector.y;
|
||||
value[ index + 2 ] = vector.z || 0;
|
||||
value[ index + 3 ] = vector.w || 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement the value buffer creation based on the array data.
|
||||
*
|
||||
* @param {NodeBuilder} builder - A reference to the current node builder.
|
||||
* @return {null}
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const length = this.array.length;
|
||||
const elementType = this.elementType;
|
||||
|
||||
let arrayType = Float32Array;
|
||||
|
||||
const paddedType = this.paddedType;
|
||||
const paddedElementLength = builder.getTypeLength( paddedType );
|
||||
|
||||
if ( elementType.charAt( 0 ) === 'i' ) arrayType = Int32Array;
|
||||
if ( elementType.charAt( 0 ) === 'u' ) arrayType = Uint32Array;
|
||||
|
||||
this.value = new arrayType( length * paddedElementLength );
|
||||
this.bufferCount = length;
|
||||
this.bufferType = paddedType;
|
||||
|
||||
return super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default `element()` method to provide element access
|
||||
* based on {@link UniformArrayNode}.
|
||||
*
|
||||
* @param {IndexNode} indexNode - The index node.
|
||||
* @return {UniformArrayElementNode}
|
||||
*/
|
||||
element( indexNode ) {
|
||||
|
||||
return nodeObject( new UniformArrayElementNode( this, nodeObject( indexNode ) ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default UniformArrayNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an uniform array node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Array<any>} values - Array-like data.
|
||||
* @param {?string} [nodeType] - The data type of the array elements.
|
||||
* @returns {UniformArrayNode}
|
||||
*/
|
||||
export const uniformArray = ( values, nodeType ) => nodeObject( new UniformArrayNode( values, nodeType ) );
|
||||
77
app/node_modules/three/src/nodes/accessors/UserDataNode.js
generated
vendored
Normal file
77
app/node_modules/three/src/nodes/accessors/UserDataNode.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
import ReferenceNode from './ReferenceNode.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* A special type of reference node that allows to link values in
|
||||
* `userData` fields to node objects.
|
||||
* ```js
|
||||
* sprite.userData.rotation = 1; // stores individual rotation per sprite
|
||||
*
|
||||
* const material = new THREE.SpriteNodeMaterial();
|
||||
* material.rotationNode = userData( 'rotation', 'float' );
|
||||
* ```
|
||||
* Since `UserDataNode` is extended from {@link ReferenceNode}, the node value
|
||||
* will automatically be updated when the `rotation` user data field changes.
|
||||
*
|
||||
* @augments ReferenceNode
|
||||
*/
|
||||
class UserDataNode extends ReferenceNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'UserDataNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new user data node.
|
||||
*
|
||||
* @param {string} property - The property name that should be referenced by the node.
|
||||
* @param {string} inputType - The node data type of the reference.
|
||||
* @param {?Object} [userData=null] - A reference to the `userData` object. If not provided, the `userData` property of the 3D object that uses the node material is evaluated.
|
||||
*/
|
||||
constructor( property, inputType, userData = null ) {
|
||||
|
||||
super( property, inputType, userData );
|
||||
|
||||
/**
|
||||
* A reference to the `userData` object. If not provided, the `userData`
|
||||
* property of the 3D object that uses the node material is evaluated.
|
||||
*
|
||||
* @type {?Object}
|
||||
* @default null
|
||||
*/
|
||||
this.userData = userData;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to make sure {@link ReferenceNode#reference} points to the correct
|
||||
* `userData` field.
|
||||
*
|
||||
* @param {(NodeFrame|NodeBuilder)} state - The current state to evaluate.
|
||||
* @return {Object} A reference to the `userData` field.
|
||||
*/
|
||||
updateReference( state ) {
|
||||
|
||||
this.reference = this.userData !== null ? this.userData : state.object.userData;
|
||||
|
||||
return this.reference;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default UserDataNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a user data node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The property name that should be referenced by the node.
|
||||
* @param {string} inputType - The node data type of the reference.
|
||||
* @param {?Object} userData - A reference to the `userData` object. If not provided, the `userData` property of the 3D object that uses the node material is evaluated.
|
||||
* @returns {UserDataNode}
|
||||
*/
|
||||
export const userData = ( name, inputType, userData ) => nodeObject( new UserDataNode( name, inputType, userData ) );
|
||||
224
app/node_modules/three/src/nodes/accessors/VelocityNode.js
generated
vendored
Normal file
224
app/node_modules/three/src/nodes/accessors/VelocityNode.js
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { modelViewMatrix } from './ModelNode.js';
|
||||
import { positionLocal, positionPrevious } from './Position.js';
|
||||
import { nodeImmutable } from '../tsl/TSLBase.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { Matrix4 } from '../../math/Matrix4.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { sub } from '../math/OperatorNode.js';
|
||||
import { cameraProjectionMatrix } from './Camera.js';
|
||||
import { renderGroup } from '../core/UniformGroupNode.js';
|
||||
|
||||
const _objectData = new WeakMap();
|
||||
|
||||
/**
|
||||
* A node for representing motion or velocity vectors. Foundation
|
||||
* for advanced post processing effects like motion blur or TRAA.
|
||||
*
|
||||
* The node keeps track of the model, view and projection matrices
|
||||
* of the previous frame and uses them to compute offsets in NDC space.
|
||||
* These offsets represent the final velocity.
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class VelocityNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'VelocityNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new vertex color node.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
super( 'vec2' );
|
||||
|
||||
/**
|
||||
* The current projection matrix.
|
||||
*
|
||||
* @type {?Matrix4}
|
||||
* @default null
|
||||
*/
|
||||
this.projectionMatrix = null;
|
||||
|
||||
/**
|
||||
* Overwritten since velocity nodes are updated per object.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'object'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.OBJECT;
|
||||
|
||||
/**
|
||||
* Overwritten since velocity nodes save data after the update.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'object'
|
||||
*/
|
||||
this.updateAfterType = NodeUpdateType.OBJECT;
|
||||
|
||||
/**
|
||||
* Uniform node representing the previous model matrix in world space.
|
||||
*
|
||||
* @type {UniformNode<mat4>}
|
||||
* @default null
|
||||
*/
|
||||
this.previousModelWorldMatrix = uniform( new Matrix4() );
|
||||
|
||||
/**
|
||||
* Uniform node representing the previous projection matrix.
|
||||
*
|
||||
* @type {UniformNode<mat4>}
|
||||
* @default null
|
||||
*/
|
||||
this.previousProjectionMatrix = uniform( new Matrix4() ).setGroup( renderGroup );
|
||||
|
||||
/**
|
||||
* Uniform node representing the previous view matrix.
|
||||
*
|
||||
* @type {UniformNode<mat4>}
|
||||
* @default null
|
||||
*/
|
||||
this.previousCameraViewMatrix = uniform( new Matrix4() );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given projection matrix.
|
||||
*
|
||||
* @param {Matrix4} projectionMatrix - The projection matrix to set.
|
||||
*/
|
||||
setProjectionMatrix( projectionMatrix ) {
|
||||
|
||||
this.projectionMatrix = projectionMatrix;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates velocity specific uniforms.
|
||||
*
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
*/
|
||||
update( { frameId, camera, object } ) {
|
||||
|
||||
const previousModelMatrix = getPreviousMatrix( object );
|
||||
|
||||
this.previousModelWorldMatrix.value.copy( previousModelMatrix );
|
||||
|
||||
//
|
||||
|
||||
const cameraData = getData( camera );
|
||||
|
||||
if ( cameraData.frameId !== frameId ) {
|
||||
|
||||
cameraData.frameId = frameId;
|
||||
|
||||
if ( cameraData.previousProjectionMatrix === undefined ) {
|
||||
|
||||
cameraData.previousProjectionMatrix = new Matrix4();
|
||||
cameraData.previousCameraViewMatrix = new Matrix4();
|
||||
|
||||
cameraData.currentProjectionMatrix = new Matrix4();
|
||||
cameraData.currentCameraViewMatrix = new Matrix4();
|
||||
|
||||
cameraData.previousProjectionMatrix.copy( this.projectionMatrix || camera.projectionMatrix );
|
||||
cameraData.previousCameraViewMatrix.copy( camera.matrixWorldInverse );
|
||||
|
||||
} else {
|
||||
|
||||
cameraData.previousProjectionMatrix.copy( cameraData.currentProjectionMatrix );
|
||||
cameraData.previousCameraViewMatrix.copy( cameraData.currentCameraViewMatrix );
|
||||
|
||||
}
|
||||
|
||||
cameraData.currentProjectionMatrix.copy( this.projectionMatrix || camera.projectionMatrix );
|
||||
cameraData.currentCameraViewMatrix.copy( camera.matrixWorldInverse );
|
||||
|
||||
this.previousProjectionMatrix.value.copy( cameraData.previousProjectionMatrix );
|
||||
this.previousCameraViewMatrix.value.copy( cameraData.previousCameraViewMatrix );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten to updated velocity specific uniforms.
|
||||
*
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
*/
|
||||
updateAfter( { object } ) {
|
||||
|
||||
getPreviousMatrix( object ).copy( object.matrixWorld );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the velocity computation based on the previous and current vertex data.
|
||||
*
|
||||
* @param {NodeBuilder} builder - A reference to the current node builder.
|
||||
* @return {Node<vec2>} The motion vector.
|
||||
*/
|
||||
setup( /*builder*/ ) {
|
||||
|
||||
const projectionMatrix = ( this.projectionMatrix === null ) ? cameraProjectionMatrix : uniform( this.projectionMatrix );
|
||||
|
||||
const previousModelViewMatrix = this.previousCameraViewMatrix.mul( this.previousModelWorldMatrix );
|
||||
|
||||
const clipPositionCurrent = projectionMatrix.mul( modelViewMatrix ).mul( positionLocal );
|
||||
const clipPositionPrevious = this.previousProjectionMatrix.mul( previousModelViewMatrix ).mul( positionPrevious );
|
||||
|
||||
const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w );
|
||||
const ndcPositionPrevious = clipPositionPrevious.xy.div( clipPositionPrevious.w );
|
||||
|
||||
const velocity = sub( ndcPositionCurrent, ndcPositionPrevious );
|
||||
|
||||
return velocity;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getData( object ) {
|
||||
|
||||
let objectData = _objectData.get( object );
|
||||
|
||||
if ( objectData === undefined ) {
|
||||
|
||||
objectData = {};
|
||||
_objectData.set( object, objectData );
|
||||
|
||||
}
|
||||
|
||||
return objectData;
|
||||
|
||||
}
|
||||
|
||||
function getPreviousMatrix( object, index = 0 ) {
|
||||
|
||||
const objectData = getData( object );
|
||||
|
||||
let matrix = objectData[ index ];
|
||||
|
||||
if ( matrix === undefined ) {
|
||||
|
||||
objectData[ index ] = matrix = new Matrix4();
|
||||
objectData[ index ].copy( object.matrixWorld );
|
||||
|
||||
}
|
||||
|
||||
return matrix;
|
||||
|
||||
}
|
||||
|
||||
export default VelocityNode;
|
||||
|
||||
/**
|
||||
* TSL object that represents the velocity of a render pass.
|
||||
*
|
||||
* @tsl
|
||||
* @type {VelocityNode}
|
||||
*/
|
||||
export const velocity = /*@__PURE__*/ nodeImmutable( VelocityNode );
|
||||
110
app/node_modules/three/src/nodes/accessors/VertexColorNode.js
generated
vendored
Normal file
110
app/node_modules/three/src/nodes/accessors/VertexColorNode.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
import AttributeNode from '../core/AttributeNode.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
|
||||
/**
|
||||
* An attribute node for representing vertex colors.
|
||||
*
|
||||
* @augments AttributeNode
|
||||
*/
|
||||
class VertexColorNode extends AttributeNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'VertexColorNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new vertex color node.
|
||||
*
|
||||
* @param {number} index - The attribute index.
|
||||
*/
|
||||
constructor( index ) {
|
||||
|
||||
super( null, 'vec4' );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isVertexColorNode = true;
|
||||
|
||||
/**
|
||||
* The attribute index to enable more than one sets of vertex colors.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.index = index;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default implementation by honoring the attribute index.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The attribute name.
|
||||
*/
|
||||
getAttributeName( /*builder*/ ) {
|
||||
|
||||
const index = this.index;
|
||||
|
||||
return 'color' + ( index > 0 ? index : '' );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const attributeName = this.getAttributeName( builder );
|
||||
const geometryAttribute = builder.hasGeometryAttribute( attributeName );
|
||||
|
||||
let result;
|
||||
|
||||
if ( geometryAttribute === true ) {
|
||||
|
||||
result = super.generate( builder );
|
||||
|
||||
} else {
|
||||
|
||||
// Vertex color fallback should be white
|
||||
result = builder.generateConst( this.nodeType, new Vector4( 1, 1, 1, 1 ) );
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.index = this.index;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.index = data.index;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default VertexColorNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a reference node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {number} [index=0] - The attribute index.
|
||||
* @returns {VertexColorNode}
|
||||
*/
|
||||
export const vertexColor = ( index = 0 ) => nodeObject( new VertexColorNode( index ) );
|
||||
181
app/node_modules/three/src/nodes/code/CodeNode.js
generated
vendored
Normal file
181
app/node_modules/three/src/nodes/code/CodeNode.js
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* This class represents native code sections. It is the base
|
||||
* class for modules like {@link FunctionNode} which allows to implement
|
||||
* functions with native shader languages.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class CodeNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'CodeNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new code node.
|
||||
*
|
||||
* @param {string} [code=''] - The native code.
|
||||
* @param {Array<Node>} [includes=[]] - An array of includes.
|
||||
* @param {('js'|'wgsl'|'glsl')} [language=''] - The used language.
|
||||
*/
|
||||
constructor( code = '', includes = [], language = '' ) {
|
||||
|
||||
super( 'code' );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isCodeNode = true;
|
||||
|
||||
/**
|
||||
* This flag is used for global cache.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
/**
|
||||
* The native code.
|
||||
*
|
||||
* @type {string}
|
||||
* @default ''
|
||||
*/
|
||||
this.code = code;
|
||||
|
||||
/**
|
||||
* An array of includes
|
||||
*
|
||||
* @type {Array<Node>}
|
||||
* @default []
|
||||
*/
|
||||
this.includes = includes;
|
||||
|
||||
/**
|
||||
* The used language.
|
||||
*
|
||||
* @type {('js'|'wgsl'|'glsl')}
|
||||
* @default ''
|
||||
*/
|
||||
this.language = language;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the includes of this code node.
|
||||
*
|
||||
* @param {Array<Node>} includes - The includes to set.
|
||||
* @return {CodeNode} A reference to this node.
|
||||
*/
|
||||
setIncludes( includes ) {
|
||||
|
||||
this.includes = includes;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the includes of this code node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Array<Node>} The includes.
|
||||
*/
|
||||
getIncludes( /*builder*/ ) {
|
||||
|
||||
return this.includes;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const includes = this.getIncludes( builder );
|
||||
|
||||
for ( const include of includes ) {
|
||||
|
||||
include.build( builder );
|
||||
|
||||
}
|
||||
|
||||
const nodeCode = builder.getCodeFromNode( this, this.getNodeType( builder ) );
|
||||
nodeCode.code = this.code;
|
||||
|
||||
return nodeCode.code;
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.code = this.code;
|
||||
data.language = this.language;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.code = data.code;
|
||||
this.language = data.language;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CodeNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a code node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} [code] - The native code.
|
||||
* @param {?Array<Node>} [includes=[]] - An array of includes.
|
||||
* @param {?('js'|'wgsl'|'glsl')} [language=''] - The used language.
|
||||
* @returns {CodeNode}
|
||||
*/
|
||||
export const code = /*@__PURE__*/ nodeProxy( CodeNode ).setParameterLength( 1, 3 );
|
||||
|
||||
/**
|
||||
* TSL function for creating a JS code node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} src - The native code.
|
||||
* @param {Array<Node>} includes - An array of includes.
|
||||
* @returns {CodeNode}
|
||||
*/
|
||||
export const js = ( src, includes ) => code( src, includes, 'js' );
|
||||
|
||||
/**
|
||||
* TSL function for creating a WGSL code node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} src - The native code.
|
||||
* @param {Array<Node>} includes - An array of includes.
|
||||
* @returns {CodeNode}
|
||||
*/
|
||||
export const wgsl = ( src, includes ) => code( src, includes, 'wgsl' );
|
||||
|
||||
/**
|
||||
* TSL function for creating a GLSL code node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} src - The native code.
|
||||
* @param {Array<Node>} includes - An array of includes.
|
||||
* @returns {CodeNode}
|
||||
*/
|
||||
export const glsl = ( src, includes ) => code( src, includes, 'glsl' );
|
||||
68
app/node_modules/three/src/nodes/code/ExpressionNode.js
generated
vendored
Normal file
68
app/node_modules/three/src/nodes/code/ExpressionNode.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeProxy } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* This class can be used to implement basic expressions in shader code.
|
||||
* Basic examples for that are `return`, `continue` or `discard` statements.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ExpressionNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ExpressionNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new expression node.
|
||||
*
|
||||
* @param {string} [snippet=''] - The native code snippet.
|
||||
* @param {string} [nodeType='void'] - The node type.
|
||||
*/
|
||||
constructor( snippet = '', nodeType = 'void' ) {
|
||||
|
||||
super( nodeType );
|
||||
|
||||
/**
|
||||
* The native code snippet.
|
||||
*
|
||||
* @type {string}
|
||||
* @default ''
|
||||
*/
|
||||
this.snippet = snippet;
|
||||
|
||||
}
|
||||
|
||||
generate( builder, output ) {
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
const snippet = this.snippet;
|
||||
|
||||
if ( type === 'void' ) {
|
||||
|
||||
builder.addLineFlowCode( snippet, this );
|
||||
|
||||
} else {
|
||||
|
||||
return builder.format( snippet, type, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ExpressionNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an expression node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} [snippet] - The native code snippet.
|
||||
* @param {?string} [nodeType='void'] - The node type.
|
||||
* @returns {ExpressionNode}
|
||||
*/
|
||||
export const expression = /*@__PURE__*/ nodeProxy( ExpressionNode ).setParameterLength( 1, 2 );
|
||||
167
app/node_modules/three/src/nodes/code/FunctionCallNode.js
generated
vendored
Normal file
167
app/node_modules/three/src/nodes/code/FunctionCallNode.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addMethodChaining, nodeArray, nodeObject, nodeObjects, float } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* This module represents the call of a {@link FunctionNode}. Developers are usually not confronted
|
||||
* with this module since they use the predefined TSL syntax `wgslFn` and `glslFn` which encapsulate
|
||||
* this logic.
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class FunctionCallNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'FunctionCallNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new function call node.
|
||||
*
|
||||
* @param {?FunctionNode} functionNode - The function node.
|
||||
* @param {Object<string, Node>} [parameters={}] - The parameters for the function call.
|
||||
*/
|
||||
constructor( functionNode = null, parameters = {} ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The function node.
|
||||
*
|
||||
* @type {?FunctionNode}
|
||||
* @default null
|
||||
*/
|
||||
this.functionNode = functionNode;
|
||||
|
||||
/**
|
||||
* The parameters of the function call.
|
||||
*
|
||||
* @type {Object<string, Node>}
|
||||
* @default {}
|
||||
*/
|
||||
this.parameters = parameters;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameters of the function call node.
|
||||
*
|
||||
* @param {Object<string, Node>} parameters - The parameters to set.
|
||||
* @return {FunctionCallNode} A reference to this node.
|
||||
*/
|
||||
setParameters( parameters ) {
|
||||
|
||||
this.parameters = parameters;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parameters of the function call node.
|
||||
*
|
||||
* @return {Object<string, Node>} The parameters of this node.
|
||||
*/
|
||||
getParameters() {
|
||||
|
||||
return this.parameters;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.functionNode.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const params = [];
|
||||
|
||||
const functionNode = this.functionNode;
|
||||
|
||||
const inputs = functionNode.getInputs( builder );
|
||||
const parameters = this.parameters;
|
||||
|
||||
const generateInput = ( node, inputNode ) => {
|
||||
|
||||
const type = inputNode.type;
|
||||
const pointer = type === 'pointer';
|
||||
|
||||
let output;
|
||||
|
||||
if ( pointer ) output = '&' + node.build( builder );
|
||||
else output = node.build( builder, type );
|
||||
|
||||
return output;
|
||||
|
||||
};
|
||||
|
||||
if ( Array.isArray( parameters ) ) {
|
||||
|
||||
if ( parameters.length > inputs.length ) {
|
||||
|
||||
console.error( 'THREE.TSL: The number of provided parameters exceeds the expected number of inputs in \'Fn()\'.' );
|
||||
|
||||
parameters.length = inputs.length;
|
||||
|
||||
} else if ( parameters.length < inputs.length ) {
|
||||
|
||||
console.error( 'THREE.TSL: The number of provided parameters is less than the expected number of inputs in \'Fn()\'.' );
|
||||
|
||||
while ( parameters.length < inputs.length ) {
|
||||
|
||||
parameters.push( float( 0 ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for ( let i = 0; i < parameters.length; i ++ ) {
|
||||
|
||||
params.push( generateInput( parameters[ i ], inputs[ i ] ) );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for ( const inputNode of inputs ) {
|
||||
|
||||
const node = parameters[ inputNode.name ];
|
||||
|
||||
if ( node !== undefined ) {
|
||||
|
||||
params.push( generateInput( node, inputNode ) );
|
||||
|
||||
} else {
|
||||
|
||||
console.error( `THREE.TSL: Input '${ inputNode.name }' not found in \'Fn()\'.` );
|
||||
|
||||
params.push( generateInput( float( 0 ), inputNode ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const functionName = functionNode.build( builder, 'property' );
|
||||
|
||||
return `${ functionName }( ${ params.join( ', ' ) } )`;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FunctionCallNode;
|
||||
|
||||
export const call = ( func, ...params ) => {
|
||||
|
||||
params = params.length > 1 || ( params[ 0 ] && params[ 0 ].isNode === true ) ? nodeArray( params ) : nodeObjects( params[ 0 ] );
|
||||
|
||||
return nodeObject( new FunctionCallNode( nodeObject( func ), params ) );
|
||||
|
||||
};
|
||||
|
||||
addMethodChaining( 'call', call );
|
||||
160
app/node_modules/three/src/nodes/code/FunctionNode.js
generated
vendored
Normal file
160
app/node_modules/three/src/nodes/code/FunctionNode.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import CodeNode from './CodeNode.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* This class represents a native shader function. It can be used to implement
|
||||
* certain aspects of a node material with native shader code. There are two predefined
|
||||
* TSL functions for easier usage.
|
||||
*
|
||||
* - `wgslFn`: Creates a WGSL function node.
|
||||
* - `glslFn`: Creates a GLSL function node.
|
||||
*
|
||||
* A basic example with one include looks like so:
|
||||
*
|
||||
* ```js
|
||||
* const desaturateWGSLFn = wgslFn( `
|
||||
* fn desaturate( color:vec3<f32> ) -> vec3<f32> {
|
||||
* let lum = vec3<f32>( 0.299, 0.587, 0.114 );
|
||||
* return vec3<f32>( dot( lum, color ) );
|
||||
* }`
|
||||
*);
|
||||
* const someWGSLFn = wgslFn( `
|
||||
* fn someFn( color:vec3<f32> ) -> vec3<f32> {
|
||||
* return desaturate( color );
|
||||
* }
|
||||
* `, [ desaturateWGSLFn ] );
|
||||
* material.colorNode = someWGSLFn( { color: texture( map ) } );
|
||||
*```
|
||||
* @augments CodeNode
|
||||
*/
|
||||
class FunctionNode extends CodeNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'FunctionNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new function node.
|
||||
*
|
||||
* @param {string} [code=''] - The native code.
|
||||
* @param {Array<Node>} [includes=[]] - An array of includes.
|
||||
* @param {('js'|'wgsl'|'glsl')} [language=''] - The used language.
|
||||
*/
|
||||
constructor( code = '', includes = [], language = '' ) {
|
||||
|
||||
super( code, includes, language );
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.getNodeFunction( builder ).type;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inputs of this function node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Array<NodeFunctionInput>} The inputs.
|
||||
*/
|
||||
getInputs( builder ) {
|
||||
|
||||
return this.getNodeFunction( builder ).inputs;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node function for this function node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {NodeFunction} The node function.
|
||||
*/
|
||||
getNodeFunction( builder ) {
|
||||
|
||||
const nodeData = builder.getDataFromNode( this );
|
||||
|
||||
let nodeFunction = nodeData.nodeFunction;
|
||||
|
||||
if ( nodeFunction === undefined ) {
|
||||
|
||||
nodeFunction = builder.parser.parseFunction( this.code );
|
||||
|
||||
nodeData.nodeFunction = nodeFunction;
|
||||
|
||||
}
|
||||
|
||||
return nodeFunction;
|
||||
|
||||
}
|
||||
|
||||
generate( builder, output ) {
|
||||
|
||||
super.generate( builder );
|
||||
|
||||
const nodeFunction = this.getNodeFunction( builder );
|
||||
|
||||
const name = nodeFunction.name;
|
||||
const type = nodeFunction.type;
|
||||
|
||||
const nodeCode = builder.getCodeFromNode( this, type );
|
||||
|
||||
if ( name !== '' ) {
|
||||
|
||||
// use a custom property name
|
||||
|
||||
nodeCode.name = name;
|
||||
|
||||
}
|
||||
|
||||
const propertyName = builder.getPropertyName( nodeCode );
|
||||
|
||||
const code = this.getNodeFunction( builder ).getCode( propertyName );
|
||||
|
||||
nodeCode.code = code + '\n';
|
||||
|
||||
if ( output === 'property' ) {
|
||||
|
||||
return propertyName;
|
||||
|
||||
} else {
|
||||
|
||||
return builder.format( `${ propertyName }()`, type, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FunctionNode;
|
||||
|
||||
const nativeFn = ( code, includes = [], language = '' ) => {
|
||||
|
||||
for ( let i = 0; i < includes.length; i ++ ) {
|
||||
|
||||
const include = includes[ i ];
|
||||
|
||||
// TSL Function: glslFn, wgslFn
|
||||
|
||||
if ( typeof include === 'function' ) {
|
||||
|
||||
includes[ i ] = include.functionNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const functionNode = nodeObject( new FunctionNode( code, includes, language ) );
|
||||
|
||||
const fn = ( ...params ) => functionNode.call( ...params );
|
||||
fn.functionNode = functionNode;
|
||||
|
||||
return fn;
|
||||
|
||||
};
|
||||
|
||||
export const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' );
|
||||
export const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' );
|
||||
726
app/node_modules/three/src/nodes/code/ScriptableNode.js
generated
vendored
Normal file
726
app/node_modules/three/src/nodes/code/ScriptableNode.js
generated
vendored
Normal file
@@ -0,0 +1,726 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { scriptableValue } from './ScriptableValueNode.js';
|
||||
import { nodeProxy, float } from '../tsl/TSLBase.js';
|
||||
import { hashArray, hashString } from '../core/NodeUtils.js';
|
||||
|
||||
/**
|
||||
* A Map-like data structure for managing resources of scriptable nodes.
|
||||
*
|
||||
* @augments Map
|
||||
*/
|
||||
class Resources extends Map {
|
||||
|
||||
get( key, callback = null, ...params ) {
|
||||
|
||||
if ( this.has( key ) ) return super.get( key );
|
||||
|
||||
if ( callback !== null ) {
|
||||
|
||||
const value = callback( ...params );
|
||||
this.set( key, value );
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Parameters {
|
||||
|
||||
constructor( scriptableNode ) {
|
||||
|
||||
this.scriptableNode = scriptableNode;
|
||||
|
||||
}
|
||||
|
||||
get parameters() {
|
||||
|
||||
return this.scriptableNode.parameters;
|
||||
|
||||
}
|
||||
|
||||
get layout() {
|
||||
|
||||
return this.scriptableNode.getLayout();
|
||||
|
||||
}
|
||||
|
||||
getInputLayout( id ) {
|
||||
|
||||
return this.scriptableNode.getInputLayout( id );
|
||||
|
||||
}
|
||||
|
||||
get( name ) {
|
||||
|
||||
const param = this.parameters[ name ];
|
||||
const value = param ? param.getValue() : null;
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the resources (e.g. namespaces) of scriptable nodes.
|
||||
*
|
||||
* @type {Resources}
|
||||
*/
|
||||
export const ScriptableNodeResources = new Resources();
|
||||
|
||||
/**
|
||||
* This type of node allows to implement nodes with custom scripts. The script
|
||||
* section is represented as an instance of `CodeNode` written with JavaScript.
|
||||
* The script itself must adhere to a specific structure.
|
||||
*
|
||||
* - main(): Executed once by default and every time `node.needsUpdate` is set.
|
||||
* - layout: The layout object defines the script's interface (inputs and outputs).
|
||||
*
|
||||
* ```js
|
||||
* ScriptableNodeResources.set( 'TSL', TSL );
|
||||
*
|
||||
* const scriptableNode = scriptable( js( `
|
||||
* layout = {
|
||||
* outputType: 'node',
|
||||
* elements: [
|
||||
* { name: 'source', inputType: 'node' },
|
||||
* ]
|
||||
* };
|
||||
*
|
||||
* const { mul, oscSine } = TSL;
|
||||
*
|
||||
* function main() {
|
||||
* const source = parameters.get( 'source' ) || float();
|
||||
* return mul( source, oscSine() ) );
|
||||
* }
|
||||
*
|
||||
* ` ) );
|
||||
*
|
||||
* scriptableNode.setParameter( 'source', color( 1, 0, 0 ) );
|
||||
*
|
||||
* const material = new THREE.MeshBasicNodeMaterial();
|
||||
* material.colorNode = scriptableNode;
|
||||
* ```
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ScriptableNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ScriptableNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new scriptable node.
|
||||
*
|
||||
* @param {?CodeNode} [codeNode=null] - The code node.
|
||||
* @param {Object} [parameters={}] - The parameters definition.
|
||||
*/
|
||||
constructor( codeNode = null, parameters = {} ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The code node.
|
||||
*
|
||||
* @type {?CodeNode}
|
||||
* @default null
|
||||
*/
|
||||
this.codeNode = codeNode;
|
||||
|
||||
/**
|
||||
* The parameters definition.
|
||||
*
|
||||
* @type {Object}
|
||||
* @default {}
|
||||
*/
|
||||
this.parameters = parameters;
|
||||
|
||||
this._local = new Resources();
|
||||
this._output = scriptableValue( null );
|
||||
this._outputs = {};
|
||||
this._source = this.source;
|
||||
this._method = null;
|
||||
this._object = null;
|
||||
this._value = null;
|
||||
this._needsOutputUpdate = true;
|
||||
|
||||
this.onRefresh = this.onRefresh.bind( this );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isScriptableNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The source code of the scriptable node.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
get source() {
|
||||
|
||||
return this.codeNode ? this.codeNode.code : '';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reference of a local script variable.
|
||||
*
|
||||
* @param {string} name - The variable name.
|
||||
* @param {Object} value - The reference to set.
|
||||
* @return {Resources} The resource map
|
||||
*/
|
||||
setLocal( name, value ) {
|
||||
|
||||
return this._local.set( name, value );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a local script variable.
|
||||
*
|
||||
* @param {string} name - The variable name.
|
||||
* @return {Object} The value.
|
||||
*/
|
||||
getLocal( name ) {
|
||||
|
||||
return this._local.get( name );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for the `refresh` event.
|
||||
*/
|
||||
onRefresh() {
|
||||
|
||||
this._refresh();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input from the layout with the given id/name.
|
||||
*
|
||||
* @param {string} id - The id/name of the input.
|
||||
* @return {Object} The element entry.
|
||||
*/
|
||||
getInputLayout( id ) {
|
||||
|
||||
for ( const element of this.getLayout() ) {
|
||||
|
||||
if ( element.inputType && ( element.id === id || element.name === id ) ) {
|
||||
|
||||
return element;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an output from the layout with the given id/name.
|
||||
*
|
||||
* @param {string} id - The id/name of the output.
|
||||
* @return {Object} The element entry.
|
||||
*/
|
||||
getOutputLayout( id ) {
|
||||
|
||||
for ( const element of this.getLayout() ) {
|
||||
|
||||
if ( element.outputType && ( element.id === id || element.name === id ) ) {
|
||||
|
||||
return element;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a script output for the given name and value.
|
||||
*
|
||||
* @param {string} name - The name of the output.
|
||||
* @param {Node} value - The node value.
|
||||
* @return {ScriptableNode} A reference to this node.
|
||||
*/
|
||||
setOutput( name, value ) {
|
||||
|
||||
const outputs = this._outputs;
|
||||
|
||||
if ( outputs[ name ] === undefined ) {
|
||||
|
||||
outputs[ name ] = scriptableValue( value );
|
||||
|
||||
} else {
|
||||
|
||||
outputs[ name ].value = value;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a script output for the given name.
|
||||
*
|
||||
* @param {string} name - The name of the output.
|
||||
* @return {ScriptableValueNode} The node value.
|
||||
*/
|
||||
getOutput( name ) {
|
||||
|
||||
return this._outputs[ name ];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a parameter for the given name
|
||||
*
|
||||
* @param {string} name - The name of the parameter.
|
||||
* @return {ScriptableValueNode} The node value.
|
||||
*/
|
||||
getParameter( name ) {
|
||||
|
||||
return this.parameters[ name ];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value for the given parameter name.
|
||||
*
|
||||
* @param {string} name - The parameter name.
|
||||
* @param {any} value - The parameter value.
|
||||
* @return {ScriptableNode} A reference to this node.
|
||||
*/
|
||||
setParameter( name, value ) {
|
||||
|
||||
const parameters = this.parameters;
|
||||
|
||||
if ( value && value.isScriptableNode ) {
|
||||
|
||||
this.deleteParameter( name );
|
||||
|
||||
parameters[ name ] = value;
|
||||
parameters[ name ].getDefaultOutput().events.addEventListener( 'refresh', this.onRefresh );
|
||||
|
||||
} else if ( value && value.isScriptableValueNode ) {
|
||||
|
||||
this.deleteParameter( name );
|
||||
|
||||
parameters[ name ] = value;
|
||||
parameters[ name ].events.addEventListener( 'refresh', this.onRefresh );
|
||||
|
||||
} else if ( parameters[ name ] === undefined ) {
|
||||
|
||||
parameters[ name ] = scriptableValue( value );
|
||||
parameters[ name ].events.addEventListener( 'refresh', this.onRefresh );
|
||||
|
||||
} else {
|
||||
|
||||
parameters[ name ].value = value;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this node which is the value of
|
||||
* the default output.
|
||||
*
|
||||
* @return {Node} The value.
|
||||
*/
|
||||
getValue() {
|
||||
|
||||
return this.getDefaultOutput().getValue();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a parameter from the script.
|
||||
*
|
||||
* @param {string} name - The parameter to remove.
|
||||
* @return {ScriptableNode} A reference to this node.
|
||||
*/
|
||||
deleteParameter( name ) {
|
||||
|
||||
let valueNode = this.parameters[ name ];
|
||||
|
||||
if ( valueNode ) {
|
||||
|
||||
if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput();
|
||||
|
||||
valueNode.events.removeEventListener( 'refresh', this.onRefresh );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all parameters from the script.
|
||||
*
|
||||
* @return {ScriptableNode} A reference to this node.
|
||||
*/
|
||||
clearParameters() {
|
||||
|
||||
for ( const name of Object.keys( this.parameters ) ) {
|
||||
|
||||
this.deleteParameter( name );
|
||||
|
||||
}
|
||||
|
||||
this.needsUpdate = true;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a function from the script.
|
||||
*
|
||||
* @param {string} name - The function name.
|
||||
* @param {...any} params - A list of parameters.
|
||||
* @return {any} The result of the function call.
|
||||
*/
|
||||
call( name, ...params ) {
|
||||
|
||||
const object = this.getObject();
|
||||
const method = object[ name ];
|
||||
|
||||
if ( typeof method === 'function' ) {
|
||||
|
||||
return method( ...params );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously calls a function from the script.
|
||||
*
|
||||
* @param {string} name - The function name.
|
||||
* @param {...any} params - A list of parameters.
|
||||
* @return {Promise<any>} The result of the function call.
|
||||
*/
|
||||
async callAsync( name, ...params ) {
|
||||
|
||||
const object = this.getObject();
|
||||
const method = object[ name ];
|
||||
|
||||
if ( typeof method === 'function' ) {
|
||||
|
||||
return method.constructor.name === 'AsyncFunction' ? await method( ...params ) : method( ...params );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten since the node types is inferred from the script's output.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.getDefaultOutputNode().getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the script node.
|
||||
*
|
||||
* @param {?string} [output=null] - An optional output.
|
||||
*/
|
||||
refresh( output = null ) {
|
||||
|
||||
if ( output !== null ) {
|
||||
|
||||
this.getOutput( output ).refresh();
|
||||
|
||||
} else {
|
||||
|
||||
this._refresh();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object representation of the script.
|
||||
*
|
||||
* @return {Object} The result object.
|
||||
*/
|
||||
getObject() {
|
||||
|
||||
if ( this.needsUpdate ) this.dispose();
|
||||
if ( this._object !== null ) return this._object;
|
||||
|
||||
//
|
||||
|
||||
const refresh = () => this.refresh();
|
||||
const setOutput = ( id, value ) => this.setOutput( id, value );
|
||||
|
||||
const parameters = new Parameters( this );
|
||||
|
||||
const THREE = ScriptableNodeResources.get( 'THREE' );
|
||||
const TSL = ScriptableNodeResources.get( 'TSL' );
|
||||
|
||||
const method = this.getMethod();
|
||||
const params = [ parameters, this._local, ScriptableNodeResources, refresh, setOutput, THREE, TSL ];
|
||||
|
||||
this._object = method( ...params );
|
||||
|
||||
const layout = this._object.layout;
|
||||
|
||||
if ( layout ) {
|
||||
|
||||
if ( layout.cache === false ) {
|
||||
|
||||
this._local.clear();
|
||||
|
||||
}
|
||||
|
||||
// default output
|
||||
this._output.outputType = layout.outputType || null;
|
||||
|
||||
if ( Array.isArray( layout.elements ) ) {
|
||||
|
||||
for ( const element of layout.elements ) {
|
||||
|
||||
const id = element.id || element.name;
|
||||
|
||||
if ( element.inputType ) {
|
||||
|
||||
if ( this.getParameter( id ) === undefined ) this.setParameter( id, null );
|
||||
|
||||
this.getParameter( id ).inputType = element.inputType;
|
||||
|
||||
}
|
||||
|
||||
if ( element.outputType ) {
|
||||
|
||||
if ( this.getOutput( id ) === undefined ) this.setOutput( id, null );
|
||||
|
||||
this.getOutput( id ).outputType = element.outputType;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this._object;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
for ( const name in this.parameters ) {
|
||||
|
||||
let valueNode = this.parameters[ name ];
|
||||
|
||||
if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput();
|
||||
|
||||
valueNode.events.addEventListener( 'refresh', this.onRefresh );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the layout of the script.
|
||||
*
|
||||
* @return {Object} The script's layout.
|
||||
*/
|
||||
getLayout() {
|
||||
|
||||
return this.getObject().layout;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default node output of the script.
|
||||
*
|
||||
* @return {Node} The default node output.
|
||||
*/
|
||||
getDefaultOutputNode() {
|
||||
|
||||
const output = this.getDefaultOutput().value;
|
||||
|
||||
if ( output && output.isNode ) {
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
return float();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default output of the script.
|
||||
*
|
||||
* @return {ScriptableValueNode} The default output.
|
||||
*/
|
||||
getDefaultOutput() {
|
||||
|
||||
return this._exec()._output;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function created from the node's script.
|
||||
*
|
||||
* @return {Function} The function representing the node's code.
|
||||
*/
|
||||
getMethod() {
|
||||
|
||||
if ( this.needsUpdate ) this.dispose();
|
||||
if ( this._method !== null ) return this._method;
|
||||
|
||||
//
|
||||
|
||||
const parametersProps = [ 'parameters', 'local', 'global', 'refresh', 'setOutput', 'THREE', 'TSL' ];
|
||||
const interfaceProps = [ 'layout', 'init', 'main', 'dispose' ];
|
||||
|
||||
const properties = interfaceProps.join( ', ' );
|
||||
const declarations = 'var ' + properties + '; var output = {};\n';
|
||||
const returns = '\nreturn { ...output, ' + properties + ' };';
|
||||
|
||||
const code = declarations + this.codeNode.code + returns;
|
||||
|
||||
//
|
||||
|
||||
this._method = new Function( ...parametersProps, code );
|
||||
|
||||
return this._method;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees all internal resources.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
if ( this._method === null ) return;
|
||||
|
||||
if ( this._object && typeof this._object.dispose === 'function' ) {
|
||||
|
||||
this._object.dispose();
|
||||
|
||||
}
|
||||
|
||||
this._method = null;
|
||||
this._object = null;
|
||||
this._source = null;
|
||||
this._value = null;
|
||||
this._needsOutputUpdate = true;
|
||||
this._output.value = null;
|
||||
this._outputs = {};
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
return this.getDefaultOutputNode();
|
||||
|
||||
}
|
||||
|
||||
getCacheKey( force ) {
|
||||
|
||||
const values = [ hashString( this.source ), this.getDefaultOutputNode().getCacheKey( force ) ];
|
||||
|
||||
for ( const param in this.parameters ) {
|
||||
|
||||
values.push( this.parameters[ param ].getCacheKey( force ) );
|
||||
|
||||
}
|
||||
|
||||
return hashArray( values );
|
||||
|
||||
}
|
||||
|
||||
set needsUpdate( value ) {
|
||||
|
||||
if ( value === true ) this.dispose();
|
||||
|
||||
}
|
||||
|
||||
get needsUpdate() {
|
||||
|
||||
return this.source !== this._source;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the `main` function of the script.
|
||||
*
|
||||
* @private
|
||||
* @return {ScriptableNode} A reference to this node.
|
||||
*/
|
||||
_exec() {
|
||||
|
||||
if ( this.codeNode === null ) return this;
|
||||
|
||||
if ( this._needsOutputUpdate === true ) {
|
||||
|
||||
this._value = this.call( 'main' );
|
||||
|
||||
this._needsOutputUpdate = false;
|
||||
|
||||
}
|
||||
|
||||
this._output.value = this._value;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the refresh.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_refresh() {
|
||||
|
||||
this.needsUpdate = true;
|
||||
|
||||
this._exec();
|
||||
|
||||
this._output.refresh();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ScriptableNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a scriptable node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {CodeNode} [codeNode] - The code node.
|
||||
* @param {?Object} [parameters={}] - The parameters definition.
|
||||
* @returns {ScriptableNode}
|
||||
*/
|
||||
export const scriptable = /*@__PURE__*/ nodeProxy( ScriptableNode ).setParameterLength( 1, 2 );
|
||||
253
app/node_modules/three/src/nodes/code/ScriptableValueNode.js
generated
vendored
Normal file
253
app/node_modules/three/src/nodes/code/ScriptableValueNode.js
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { arrayBufferToBase64, base64ToArrayBuffer } from '../core/NodeUtils.js';
|
||||
import { nodeProxy, float } from '../tsl/TSLBase.js';
|
||||
|
||||
import { EventDispatcher } from '../../core/EventDispatcher.js';
|
||||
|
||||
/**
|
||||
* `ScriptableNode` uses this class to manage script inputs and outputs.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ScriptableValueNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ScriptableValueNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new scriptable node.
|
||||
*
|
||||
* @param {any} [value=null] - The value.
|
||||
*/
|
||||
constructor( value = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* A reference to the value.
|
||||
*
|
||||
* @private
|
||||
* @default null
|
||||
*/
|
||||
this._value = value;
|
||||
|
||||
/**
|
||||
* Depending on the type of `_value`, this property might cache parsed data.
|
||||
*
|
||||
* @private
|
||||
* @default null
|
||||
*/
|
||||
this._cache = null;
|
||||
|
||||
/**
|
||||
* If this node represents an input, this property represents the input type.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.inputType = null;
|
||||
|
||||
/**
|
||||
* If this node represents an output, this property represents the output type.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.outputType = null;
|
||||
|
||||
/**
|
||||
* An event dispatcher for managing events.
|
||||
*
|
||||
* @type {EventDispatcher}
|
||||
*/
|
||||
this.events = new EventDispatcher();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isScriptableValueNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this node represents an output or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
get isScriptableOutputNode() {
|
||||
|
||||
return this.outputType !== null;
|
||||
|
||||
}
|
||||
|
||||
set value( val ) {
|
||||
|
||||
if ( this._value === val ) return;
|
||||
|
||||
if ( this._cache && this.inputType === 'URL' && this.value.value instanceof ArrayBuffer ) {
|
||||
|
||||
URL.revokeObjectURL( this._cache );
|
||||
|
||||
this._cache = null;
|
||||
|
||||
}
|
||||
|
||||
this._value = val;
|
||||
|
||||
this.events.dispatchEvent( { type: 'change' } );
|
||||
|
||||
this.refresh();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The node's value.
|
||||
*
|
||||
* @type {any}
|
||||
*/
|
||||
get value() {
|
||||
|
||||
return this._value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the `refresh` event.
|
||||
*/
|
||||
refresh() {
|
||||
|
||||
this.events.dispatchEvent( { type: 'refresh' } );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The `value` property usually represents a node or even binary data in form of array buffers.
|
||||
* In this case, this method tries to return the actual value behind the complex type.
|
||||
*
|
||||
* @return {any} The value.
|
||||
*/
|
||||
getValue() {
|
||||
|
||||
const value = this.value;
|
||||
|
||||
if ( value && this._cache === null && this.inputType === 'URL' && value.value instanceof ArrayBuffer ) {
|
||||
|
||||
this._cache = URL.createObjectURL( new Blob( [ value.value ] ) );
|
||||
|
||||
} else if ( value && value.value !== null && value.value !== undefined && (
|
||||
( ( this.inputType === 'URL' || this.inputType === 'String' ) && typeof value.value === 'string' ) ||
|
||||
( this.inputType === 'Number' && typeof value.value === 'number' ) ||
|
||||
( this.inputType === 'Vector2' && value.value.isVector2 ) ||
|
||||
( this.inputType === 'Vector3' && value.value.isVector3 ) ||
|
||||
( this.inputType === 'Vector4' && value.value.isVector4 ) ||
|
||||
( this.inputType === 'Color' && value.value.isColor ) ||
|
||||
( this.inputType === 'Matrix3' && value.value.isMatrix3 ) ||
|
||||
( this.inputType === 'Matrix4' && value.value.isMatrix4 )
|
||||
) ) {
|
||||
|
||||
return value.value;
|
||||
|
||||
}
|
||||
|
||||
return this._cache || value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwritten since the node type is inferred from the value.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.value && this.value.isNode ? this.value.getNodeType( builder ) : 'float';
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
return this.value && this.value.isNode ? this.value : float();
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
if ( this.value !== null ) {
|
||||
|
||||
if ( this.inputType === 'ArrayBuffer' ) {
|
||||
|
||||
data.value = arrayBufferToBase64( this.value );
|
||||
|
||||
} else {
|
||||
|
||||
data.value = this.value ? this.value.toJSON( data.meta ).uuid : null;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
data.value = null;
|
||||
|
||||
}
|
||||
|
||||
data.inputType = this.inputType;
|
||||
data.outputType = this.outputType;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
let value = null;
|
||||
|
||||
if ( data.value !== null ) {
|
||||
|
||||
if ( data.inputType === 'ArrayBuffer' ) {
|
||||
|
||||
value = base64ToArrayBuffer( data.value );
|
||||
|
||||
} else if ( data.inputType === 'Texture' ) {
|
||||
|
||||
value = data.meta.textures[ data.value ];
|
||||
|
||||
} else {
|
||||
|
||||
value = data.meta.nodes[ data.value ] || null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.value = value;
|
||||
|
||||
this.inputType = data.inputType;
|
||||
this.outputType = data.outputType;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ScriptableValueNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a scriptable value node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {any} [value] - The value.
|
||||
* @returns {ScriptableValueNode}
|
||||
*/
|
||||
export const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ).setParameterLength( 1 );
|
||||
142
app/node_modules/three/src/nodes/core/ArrayNode.js
generated
vendored
Normal file
142
app/node_modules/three/src/nodes/core/ArrayNode.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
import TempNode from './TempNode.js';
|
||||
import { addMethodChaining, nodeObject } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* ArrayNode represents a collection of nodes, typically created using the {@link array} function.
|
||||
* ```js
|
||||
* const colors = array( [
|
||||
* vec3( 1, 0, 0 ),
|
||||
* vec3( 0, 1, 0 ),
|
||||
* vec3( 0, 0, 1 )
|
||||
* ] );
|
||||
*
|
||||
* const redColor = tintColors.element( 0 );
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class ArrayNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ArrayNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new array node.
|
||||
*
|
||||
* @param {?string} nodeType - The data type of the elements.
|
||||
* @param {number} count - Size of the array.
|
||||
* @param {?Array<Node>} [values=null] - Array default values.
|
||||
*/
|
||||
constructor( nodeType, count, values = null ) {
|
||||
|
||||
super( nodeType );
|
||||
|
||||
/**
|
||||
* Array size.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
this.count = count;
|
||||
|
||||
/**
|
||||
* Array default values.
|
||||
*
|
||||
* @type {?Array<Node>}
|
||||
*/
|
||||
this.values = values;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isArrayNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node's type.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The type of the node.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
if ( this.nodeType === null ) {
|
||||
|
||||
this.nodeType = this.values[ 0 ].getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
return this.nodeType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node's type.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The type of the node.
|
||||
*/
|
||||
getElementType( builder ) {
|
||||
|
||||
return this.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds the output node and returns the resulting array as a shader string.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The generated shader string.
|
||||
*/
|
||||
generate( builder ) {
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
|
||||
return builder.generateArray( type, this.count, this.values );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ArrayNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an array node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string|Array<Node>} nodeTypeOrValues - A string representing the element type (e.g., 'vec3')
|
||||
* or an array containing the default values (e.g., [ vec3() ]).
|
||||
* @param {?number} [count] - Size of the array.
|
||||
* @returns {ArrayNode}
|
||||
*/
|
||||
export const array = ( ...params ) => {
|
||||
|
||||
let node;
|
||||
|
||||
if ( params.length === 1 ) {
|
||||
|
||||
const values = params[ 0 ];
|
||||
|
||||
node = new ArrayNode( null, values.length, values );
|
||||
|
||||
} else {
|
||||
|
||||
const nodeType = params[ 0 ];
|
||||
const count = params[ 1 ];
|
||||
|
||||
node = new ArrayNode( nodeType, count );
|
||||
|
||||
}
|
||||
|
||||
return nodeObject( node );
|
||||
|
||||
};
|
||||
|
||||
addMethodChaining( 'toArray', ( node, count ) => array( Array( count ).fill( node ) ) );
|
||||
198
app/node_modules/three/src/nodes/core/AssignNode.js
generated
vendored
Normal file
198
app/node_modules/three/src/nodes/core/AssignNode.js
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
|
||||
import { vectorComponents } from '../core/constants.js';
|
||||
|
||||
/**
|
||||
* These node represents an assign operation. Meaning a node is assigned
|
||||
* to another node.
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class AssignNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'AssignNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new assign node.
|
||||
*
|
||||
* @param {Node} targetNode - The target node.
|
||||
* @param {Node} sourceNode - The source type.
|
||||
*/
|
||||
constructor( targetNode, sourceNode ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The target node.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.targetNode = targetNode;
|
||||
|
||||
/**
|
||||
* The source node.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.sourceNode = sourceNode;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isAssignNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this node is used more than once in context of other nodes. This method
|
||||
* is overwritten since it always returns `false` (assigns are unique).
|
||||
*
|
||||
* @return {boolean} A flag that indicates if there is more than one dependency to other nodes. Always `false`.
|
||||
*/
|
||||
hasDependencies() {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder, output ) {
|
||||
|
||||
return output !== 'void' ? this.targetNode.getNodeType( builder ) : 'void';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a split is required when assigning source to target. This can happen when the component length of
|
||||
* target and source data type does not match.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {boolean} Whether a split is required when assigning source to target.
|
||||
*/
|
||||
needsSplitAssign( builder ) {
|
||||
|
||||
const { targetNode } = this;
|
||||
|
||||
if ( builder.isAvailable( 'swizzleAssign' ) === false && targetNode.isSplitNode && targetNode.components.length > 1 ) {
|
||||
|
||||
const targetLength = builder.getTypeLength( targetNode.node.getNodeType( builder ) );
|
||||
const assignDifferentVector = vectorComponents.join( '' ).slice( 0, targetLength ) !== targetNode.components;
|
||||
|
||||
return assignDifferentVector;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const { targetNode, sourceNode } = this;
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
properties.sourceNode = sourceNode;
|
||||
properties.targetNode = targetNode.context( { assign: true } );
|
||||
|
||||
}
|
||||
|
||||
generate( builder, output ) {
|
||||
|
||||
const { targetNode, sourceNode } = builder.getNodeProperties( this );
|
||||
|
||||
const needsSplitAssign = this.needsSplitAssign( builder );
|
||||
|
||||
const targetType = targetNode.getNodeType( builder );
|
||||
|
||||
const target = targetNode.build( builder );
|
||||
const source = sourceNode.build( builder, targetType );
|
||||
|
||||
const sourceType = sourceNode.getNodeType( builder );
|
||||
|
||||
const nodeData = builder.getDataFromNode( this );
|
||||
|
||||
//
|
||||
|
||||
let snippet;
|
||||
|
||||
if ( nodeData.initialized === true ) {
|
||||
|
||||
if ( output !== 'void' ) {
|
||||
|
||||
snippet = target;
|
||||
|
||||
}
|
||||
|
||||
} else if ( needsSplitAssign ) {
|
||||
|
||||
const sourceVar = builder.getVarFromNode( this, null, targetType );
|
||||
const sourceProperty = builder.getPropertyName( sourceVar );
|
||||
|
||||
builder.addLineFlowCode( `${ sourceProperty } = ${ source }`, this );
|
||||
|
||||
const splitNode = targetNode.node;
|
||||
const splitTargetNode = splitNode.node.context( { assign: true } );
|
||||
|
||||
const targetRoot = splitTargetNode.build( builder );
|
||||
|
||||
for ( let i = 0; i < splitNode.components.length; i ++ ) {
|
||||
|
||||
const component = splitNode.components[ i ];
|
||||
|
||||
builder.addLineFlowCode( `${ targetRoot }.${ component } = ${ sourceProperty }[ ${ i } ]`, this );
|
||||
|
||||
}
|
||||
|
||||
if ( output !== 'void' ) {
|
||||
|
||||
snippet = target;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
snippet = `${ target } = ${ source }`;
|
||||
|
||||
if ( output === 'void' || sourceType === 'void' ) {
|
||||
|
||||
builder.addLineFlowCode( snippet, this );
|
||||
|
||||
if ( output !== 'void' ) {
|
||||
|
||||
snippet = target;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nodeData.initialized = true;
|
||||
|
||||
return builder.format( snippet, targetType, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default AssignNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an assign node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} targetNode - The target node.
|
||||
* @param {Node} sourceNode - The source type.
|
||||
* @returns {AssignNode}
|
||||
*/
|
||||
export const assign = /*@__PURE__*/ nodeProxy( AssignNode ).setParameterLength( 2 );
|
||||
|
||||
addMethodChaining( 'assign', assign );
|
||||
167
app/node_modules/three/src/nodes/core/AttributeNode.js
generated
vendored
Normal file
167
app/node_modules/three/src/nodes/core/AttributeNode.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
import Node from './Node.js';
|
||||
import { nodeObject, varying } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* Base class for representing shader attributes as nodes.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class AttributeNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'AttributeNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new attribute node.
|
||||
*
|
||||
* @param {string} attributeName - The name of the attribute.
|
||||
* @param {?string} nodeType - The node type.
|
||||
*/
|
||||
constructor( attributeName, nodeType = null ) {
|
||||
|
||||
super( nodeType );
|
||||
|
||||
/**
|
||||
* `AttributeNode` sets this property to `true` by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
this._attributeName = attributeName;
|
||||
|
||||
}
|
||||
|
||||
getHash( builder ) {
|
||||
|
||||
return this.getAttributeName( builder );
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
let nodeType = this.nodeType;
|
||||
|
||||
if ( nodeType === null ) {
|
||||
|
||||
const attributeName = this.getAttributeName( builder );
|
||||
|
||||
if ( builder.hasGeometryAttribute( attributeName ) ) {
|
||||
|
||||
const attribute = builder.geometry.getAttribute( attributeName );
|
||||
|
||||
nodeType = builder.getTypeFromAttribute( attribute );
|
||||
|
||||
} else {
|
||||
|
||||
nodeType = 'float';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nodeType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute name to the given value. The method can be
|
||||
* overwritten in derived classes if the final name must be computed
|
||||
* analytically.
|
||||
*
|
||||
* @param {string} attributeName - The name of the attribute.
|
||||
* @return {AttributeNode} A reference to this node.
|
||||
*/
|
||||
setAttributeName( attributeName ) {
|
||||
|
||||
this._attributeName = attributeName;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute name of this node. The method can be
|
||||
* overwritten in derived classes if the final name must be computed
|
||||
* analytically.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The attribute name.
|
||||
*/
|
||||
getAttributeName( /*builder*/ ) {
|
||||
|
||||
return this._attributeName;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const attributeName = this.getAttributeName( builder );
|
||||
const nodeType = this.getNodeType( builder );
|
||||
const geometryAttribute = builder.hasGeometryAttribute( attributeName );
|
||||
|
||||
if ( geometryAttribute === true ) {
|
||||
|
||||
const attribute = builder.geometry.getAttribute( attributeName );
|
||||
const attributeType = builder.getTypeFromAttribute( attribute );
|
||||
|
||||
const nodeAttribute = builder.getAttribute( attributeName, attributeType );
|
||||
|
||||
if ( builder.shaderStage === 'vertex' ) {
|
||||
|
||||
return builder.format( nodeAttribute.name, attributeType, nodeType );
|
||||
|
||||
} else {
|
||||
|
||||
const nodeVarying = varying( this );
|
||||
|
||||
return nodeVarying.build( builder, nodeType );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
console.warn( `AttributeNode: Vertex attribute "${ attributeName }" not found on geometry.` );
|
||||
|
||||
return builder.generateConst( nodeType );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.global = this.global;
|
||||
data._attributeName = this._attributeName;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.global = data.global;
|
||||
this._attributeName = data._attributeName;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default AttributeNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an attribute node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the attribute.
|
||||
* @param {?string} [nodeType=null] - The node type.
|
||||
* @returns {AttributeNode}
|
||||
*/
|
||||
export const attribute = ( name, nodeType = null ) => nodeObject( new AttributeNode( name, nodeType ) );
|
||||
93
app/node_modules/three/src/nodes/core/BypassNode.js
generated
vendored
Normal file
93
app/node_modules/three/src/nodes/core/BypassNode.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import Node from './Node.js';
|
||||
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* The class generates the code of a given node but returns another node in the output.
|
||||
* This can be used to call a method or node that does not return a value, i.e.
|
||||
* type `void` on an input where returning a value is required. Example:
|
||||
*
|
||||
* ```js
|
||||
* material.colorNode = myColor.bypass( runVoidFn() )
|
||||
*```
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class BypassNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'BypassNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new bypass node.
|
||||
*
|
||||
* @param {Node} outputNode - The output node.
|
||||
* @param {Node} callNode - The call node.
|
||||
*/
|
||||
constructor( outputNode, callNode ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isBypassNode = true;
|
||||
|
||||
/**
|
||||
* The output node.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.outputNode = outputNode;
|
||||
|
||||
/**
|
||||
* The call node.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.callNode = callNode;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.outputNode.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const snippet = this.callNode.build( builder, 'void' );
|
||||
|
||||
if ( snippet !== '' ) {
|
||||
|
||||
builder.addLineFlowCode( snippet, this );
|
||||
|
||||
}
|
||||
|
||||
return this.outputNode.build( builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BypassNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a bypass node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} outputNode - The output node.
|
||||
* @param {Node} callNode - The call node.
|
||||
* @returns {BypassNode}
|
||||
*/
|
||||
export const bypass = /*@__PURE__*/ nodeProxy( BypassNode ).setParameterLength( 2 );
|
||||
|
||||
addMethodChaining( 'bypass', bypass );
|
||||
100
app/node_modules/three/src/nodes/core/CacheNode.js
generated
vendored
Normal file
100
app/node_modules/three/src/nodes/core/CacheNode.js
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import Node from './Node.js';
|
||||
import { addMethodChaining, nodeObject } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* This node can be used as a cache management component for another node.
|
||||
* Caching is in general used by default in {@link NodeBuilder} but this node
|
||||
* allows the usage of a shared parent cache during the build process.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class CacheNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'CacheNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new cache node.
|
||||
*
|
||||
* @param {Node} node - The node that should be cached.
|
||||
* @param {boolean} [parent=true] - Whether this node refers to a shared parent cache or not.
|
||||
*/
|
||||
constructor( node, parent = true ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The node that should be cached.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* Whether this node refers to a shared parent cache or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.parent = parent;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isCacheNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
const previousCache = builder.getCache();
|
||||
const cache = builder.getCacheFromNode( this, this.parent );
|
||||
|
||||
builder.setCache( cache );
|
||||
|
||||
const nodeType = this.node.getNodeType( builder );
|
||||
|
||||
builder.setCache( previousCache );
|
||||
|
||||
return nodeType;
|
||||
|
||||
}
|
||||
|
||||
build( builder, ...params ) {
|
||||
|
||||
const previousCache = builder.getCache();
|
||||
const cache = builder.getCacheFromNode( this, this.parent );
|
||||
|
||||
builder.setCache( cache );
|
||||
|
||||
const data = this.node.build( builder, ...params );
|
||||
|
||||
builder.setCache( previousCache );
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CacheNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a cache node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node that should be cached.
|
||||
* @param {boolean} [parent] - Whether this node refers to a shared parent cache or not.
|
||||
* @returns {CacheNode}
|
||||
*/
|
||||
export const cache = ( node, parent ) => nodeObject( new CacheNode( nodeObject( node ), parent ) );
|
||||
|
||||
addMethodChaining( 'cache', cache );
|
||||
67
app/node_modules/three/src/nodes/core/ConstNode.js
generated
vendored
Normal file
67
app/node_modules/three/src/nodes/core/ConstNode.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
import InputNode from './InputNode.js';
|
||||
|
||||
const _regNum = /float|u?int/;
|
||||
|
||||
/**
|
||||
* Class for representing a constant value in the shader.
|
||||
*
|
||||
* @augments InputNode
|
||||
*/
|
||||
class ConstNode extends InputNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ConstNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new input node.
|
||||
*
|
||||
* @param {any} value - The value of this node. Usually a JS primitive or three.js object (vector, matrix, color).
|
||||
* @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.isConstNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the shader string of the value with the current node builder.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The generated value as a shader string.
|
||||
*/
|
||||
generateConst( builder ) {
|
||||
|
||||
return builder.generateConst( this.getNodeType( builder ), this.value );
|
||||
|
||||
}
|
||||
|
||||
generate( builder, output ) {
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
|
||||
if ( _regNum.test( type ) && _regNum.test( output ) ) {
|
||||
|
||||
return builder.generateConst( output, this.value );
|
||||
|
||||
}
|
||||
|
||||
return builder.format( this.generateConst( builder ), type, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ConstNode;
|
||||
146
app/node_modules/three/src/nodes/core/ContextNode.js
generated
vendored
Normal file
146
app/node_modules/three/src/nodes/core/ContextNode.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
import Node from './Node.js';
|
||||
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* This node can be used as a context management component for another node.
|
||||
* {@link NodeBuilder} performs its node building process in a specific context and
|
||||
* this node allows the modify the context. A typical use case is to overwrite `getUV()` e.g.:
|
||||
*
|
||||
* ```js
|
||||
*node.context( { getUV: () => customCoord } );
|
||||
*```
|
||||
* @augments Node
|
||||
*/
|
||||
class ContextNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ContextNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new context node.
|
||||
*
|
||||
* @param {Node} node - The node whose context should be modified.
|
||||
* @param {Object} [value={}] - The modified context data.
|
||||
*/
|
||||
constructor( node, value = {} ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isContextNode = true;
|
||||
|
||||
/**
|
||||
* The node whose context should be modified.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* The modified context data.
|
||||
*
|
||||
* @type {Object}
|
||||
* @default {}
|
||||
*/
|
||||
this.value = value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten to ensure it returns the reference to {@link ContextNode#node}.
|
||||
*
|
||||
* @return {Node} A reference to {@link ContextNode#node}.
|
||||
*/
|
||||
getScope() {
|
||||
|
||||
return this.node.getScope();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten to ensure it returns the type of {@link ContextNode#node}.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The node type.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.node.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
analyze( builder ) {
|
||||
|
||||
const previousContext = builder.getContext();
|
||||
|
||||
builder.setContext( { ...builder.context, ...this.value } );
|
||||
|
||||
this.node.build( builder );
|
||||
|
||||
builder.setContext( previousContext );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const previousContext = builder.getContext();
|
||||
|
||||
builder.setContext( { ...builder.context, ...this.value } );
|
||||
|
||||
this.node.build( builder );
|
||||
|
||||
builder.setContext( previousContext );
|
||||
|
||||
}
|
||||
|
||||
generate( builder, output ) {
|
||||
|
||||
const previousContext = builder.getContext();
|
||||
|
||||
builder.setContext( { ...builder.context, ...this.value } );
|
||||
|
||||
const snippet = this.node.build( builder, output );
|
||||
|
||||
builder.setContext( previousContext );
|
||||
|
||||
return snippet;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ContextNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a context node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node whose context should be modified.
|
||||
* @param {Object} [value={}] - The modified context data.
|
||||
* @returns {ContextNode}
|
||||
*/
|
||||
export const context = /*@__PURE__*/ nodeProxy( ContextNode ).setParameterLength( 1, 2 );
|
||||
|
||||
/**
|
||||
* TSL function for defining a label context value for a given node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node whose context should be modified.
|
||||
* @param {string} name - The name/label to set.
|
||||
* @returns {ContextNode}
|
||||
*/
|
||||
export const label = ( node, name ) => context( node, { label: name } );
|
||||
|
||||
addMethodChaining( 'context', context );
|
||||
addMethodChaining( 'label', label );
|
||||
164
app/node_modules/three/src/nodes/core/IndexNode.js
generated
vendored
Normal file
164
app/node_modules/three/src/nodes/core/IndexNode.js
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
import Node from './Node.js';
|
||||
import { nodeImmutable, varying } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* This class represents shader indices of different types. The following predefined node
|
||||
* objects cover frequent use cases:
|
||||
*
|
||||
* - `vertexIndex`: The index of a vertex within a mesh.
|
||||
* - `instanceIndex`: The index of either a mesh instance or an invocation of a compute shader.
|
||||
* - `drawIndex`: The index of a draw call.
|
||||
* - `invocationLocalIndex`: The index of a compute invocation within the scope of a workgroup load.
|
||||
* - `invocationSubgroupIndex`: The index of a compute invocation within the scope of a subgroup.
|
||||
* - `subgroupIndex`: The index of the subgroup the current compute invocation belongs to.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class IndexNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'IndexNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new index node.
|
||||
*
|
||||
* @param {('vertex'|'instance'|'subgroup'|'invocationLocal'|'invocationSubgroup'|'draw')} scope - The scope of the index node.
|
||||
*/
|
||||
constructor( scope ) {
|
||||
|
||||
super( 'uint' );
|
||||
|
||||
/**
|
||||
* The scope of the index node.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isIndexNode = true;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const nodeType = this.getNodeType( builder );
|
||||
const scope = this.scope;
|
||||
|
||||
let propertyName;
|
||||
|
||||
if ( scope === IndexNode.VERTEX ) {
|
||||
|
||||
propertyName = builder.getVertexIndex();
|
||||
|
||||
} else if ( scope === IndexNode.INSTANCE ) {
|
||||
|
||||
propertyName = builder.getInstanceIndex();
|
||||
|
||||
} else if ( scope === IndexNode.DRAW ) {
|
||||
|
||||
propertyName = builder.getDrawIndex();
|
||||
|
||||
} else if ( scope === IndexNode.INVOCATION_LOCAL ) {
|
||||
|
||||
propertyName = builder.getInvocationLocalIndex();
|
||||
|
||||
} else if ( scope === IndexNode.INVOCATION_SUBGROUP ) {
|
||||
|
||||
propertyName = builder.getInvocationSubgroupIndex();
|
||||
|
||||
} else if ( scope === IndexNode.SUBGROUP ) {
|
||||
|
||||
propertyName = builder.getSubgroupIndex();
|
||||
|
||||
} else {
|
||||
|
||||
throw new Error( 'THREE.IndexNode: Unknown scope: ' + scope );
|
||||
|
||||
}
|
||||
|
||||
let output;
|
||||
|
||||
if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) {
|
||||
|
||||
output = propertyName;
|
||||
|
||||
} else {
|
||||
|
||||
const nodeVarying = varying( this );
|
||||
|
||||
output = nodeVarying.build( builder, nodeType );
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IndexNode.VERTEX = 'vertex';
|
||||
IndexNode.INSTANCE = 'instance';
|
||||
IndexNode.SUBGROUP = 'subgroup';
|
||||
IndexNode.INVOCATION_LOCAL = 'invocationLocal';
|
||||
IndexNode.INVOCATION_SUBGROUP = 'invocationSubgroup';
|
||||
IndexNode.DRAW = 'draw';
|
||||
|
||||
export default IndexNode;
|
||||
|
||||
/**
|
||||
* TSL object that represents the index of a vertex within a mesh.
|
||||
*
|
||||
* @tsl
|
||||
* @type {IndexNode}
|
||||
*/
|
||||
export const vertexIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.VERTEX );
|
||||
|
||||
/**
|
||||
* TSL object that represents the index of either a mesh instance or an invocation of a compute shader.
|
||||
*
|
||||
* @tsl
|
||||
* @type {IndexNode}
|
||||
*/
|
||||
export const instanceIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INSTANCE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the index of the subgroup the current compute invocation belongs to.
|
||||
*
|
||||
* @tsl
|
||||
* @type {IndexNode}
|
||||
*/
|
||||
export const subgroupIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.SUBGROUP );
|
||||
|
||||
/**
|
||||
* TSL object that represents the index of a compute invocation within the scope of a subgroup.
|
||||
*
|
||||
* @tsl
|
||||
* @type {IndexNode}
|
||||
*/
|
||||
export const invocationSubgroupIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_SUBGROUP );
|
||||
|
||||
/**
|
||||
* TSL object that represents the index of a compute invocation within the scope of a workgroup load.
|
||||
*
|
||||
* @tsl
|
||||
* @type {IndexNode}
|
||||
*/
|
||||
export const invocationLocalIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_LOCAL );
|
||||
|
||||
/**
|
||||
* TSL object that represents the index of a draw call.
|
||||
*
|
||||
* @tsl
|
||||
* @type {IndexNode}
|
||||
*/
|
||||
export const drawIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.DRAW );
|
||||
135
app/node_modules/three/src/nodes/core/InputNode.js
generated
vendored
Normal file
135
app/node_modules/three/src/nodes/core/InputNode.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import Node from './Node.js';
|
||||
import { getValueType, getValueFromType, arrayBufferToBase64 } from './NodeUtils.js';
|
||||
|
||||
/**
|
||||
* Base class for representing data input nodes.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class InputNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'InputNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new input node.
|
||||
*
|
||||
* @param {any} value - The value of this node. This can be any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
|
||||
* @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( nodeType );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isInputNode = true;
|
||||
|
||||
/**
|
||||
* The value of this node. This can be any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
|
||||
*
|
||||
* @type {any}
|
||||
*/
|
||||
this.value = value;
|
||||
|
||||
/**
|
||||
* The precision of the value in the shader.
|
||||
*
|
||||
* @type {?('low'|'medium'|'high')}
|
||||
* @default null
|
||||
*/
|
||||
this.precision = null;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( /*builder*/ ) {
|
||||
|
||||
if ( this.nodeType === null ) {
|
||||
|
||||
return getValueType( this.value );
|
||||
|
||||
}
|
||||
|
||||
return this.nodeType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input type of the node which is by default the node type. Derived modules
|
||||
* might overwrite this method and use a fixed type or compute one analytically.
|
||||
*
|
||||
* A typical example for different input and node types are textures. The input type of a
|
||||
* normal RGBA texture is `texture` whereas its node type is `vec4`.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The input type.
|
||||
*/
|
||||
getInputType( builder ) {
|
||||
|
||||
return this.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the precision to the given value. The method can be
|
||||
* overwritten in derived classes if the final precision must be computed
|
||||
* analytically.
|
||||
*
|
||||
* @param {('low'|'medium'|'high')} precision - The precision of the input value in the shader.
|
||||
* @return {InputNode} A reference to this node.
|
||||
*/
|
||||
setPrecision( precision ) {
|
||||
|
||||
this.precision = precision;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.value = this.value;
|
||||
|
||||
if ( this.value && this.value.toArray ) data.value = this.value.toArray();
|
||||
|
||||
data.valueType = getValueType( this.value );
|
||||
data.nodeType = this.nodeType;
|
||||
|
||||
if ( data.valueType === 'ArrayBuffer' ) data.value = arrayBufferToBase64( data.value );
|
||||
|
||||
data.precision = this.precision;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.nodeType = data.nodeType;
|
||||
this.value = Array.isArray( data.value ) ? getValueFromType( data.valueType, ...data.value ) : data.value;
|
||||
|
||||
this.precision = data.precision || null;
|
||||
|
||||
if ( this.value && this.value.fromArray ) this.value = this.value.fromArray( data.value );
|
||||
|
||||
}
|
||||
|
||||
generate( /*builder, output*/ ) {
|
||||
|
||||
console.warn( 'Abstract function.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default InputNode;
|
||||
77
app/node_modules/three/src/nodes/core/LightingModel.js
generated
vendored
Normal file
77
app/node_modules/three/src/nodes/core/LightingModel.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Abstract class for implementing lighting models. The module defines
|
||||
* multiple methods that concrete lighting models can implement. These
|
||||
* methods are executed at different points during the light evaluation
|
||||
* process.
|
||||
*/
|
||||
class LightingModel {
|
||||
|
||||
/**
|
||||
* This method is intended for setting up lighting model and context data
|
||||
* which are later used in the evaluation process.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
start( builder ) {
|
||||
|
||||
// lights ( direct )
|
||||
|
||||
builder.lightsNode.setupLights( builder, builder.lightsNode.getLightNodes( builder ) );
|
||||
|
||||
// indirect
|
||||
|
||||
this.indirect( builder );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is intended for executing final tasks like final updates
|
||||
* to the outgoing light.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
finish( /*builder*/ ) { }
|
||||
|
||||
/**
|
||||
* This method is intended for implementing the direct light term and
|
||||
* executed during the build process of directional, point and spot light nodes.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Object} lightData - The light data.
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
direct( /*lightData, builder*/ ) { }
|
||||
|
||||
/**
|
||||
* This method is intended for implementing the direct light term for
|
||||
* rect area light nodes.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Object} lightData - The light data.
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
directRectArea( /*lightData, builder*/ ) {}
|
||||
|
||||
/**
|
||||
* This method is intended for implementing the indirect light term.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
indirect( /*builder*/ ) { }
|
||||
|
||||
/**
|
||||
* This method is intended for implementing the ambient occlusion term.
|
||||
* Unlike other methods, this method must be called manually by the lighting
|
||||
* model in its indirect term.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
*/
|
||||
ambientOcclusion( /*input, stack, builder*/ ) { }
|
||||
|
||||
}
|
||||
|
||||
export default LightingModel;
|
||||
150
app/node_modules/three/src/nodes/core/MRTNode.js
generated
vendored
Normal file
150
app/node_modules/three/src/nodes/core/MRTNode.js
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
import OutputStructNode from './OutputStructNode.js';
|
||||
import { nodeProxy, vec4 } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* Returns the MRT texture index for the given name.
|
||||
*
|
||||
* @param {Array<Texture>} textures - The textures of a MRT-configured render target.
|
||||
* @param {string} name - The name of the MRT texture which index is requested.
|
||||
* @return {number} The texture index.
|
||||
*/
|
||||
export function getTextureIndex( textures, name ) {
|
||||
|
||||
for ( let i = 0; i < textures.length; i ++ ) {
|
||||
|
||||
if ( textures[ i ].name === name ) {
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return - 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This node can be used setup a MRT context for rendering. A typical MRT setup for
|
||||
* post-processing is shown below:
|
||||
* ```js
|
||||
* const mrtNode = mrt( {
|
||||
* output: output,
|
||||
* normal: normalView
|
||||
* } ) );
|
||||
* ```
|
||||
* The MRT output is defined as a dictionary.
|
||||
*
|
||||
* @augments OutputStructNode
|
||||
*/
|
||||
class MRTNode extends OutputStructNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'MRTNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new output struct node.
|
||||
*
|
||||
* @param {Object<string, Node>} outputNodes - The MRT outputs.
|
||||
*/
|
||||
constructor( outputNodes ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* A dictionary representing the MRT outputs. The key
|
||||
* is the name of the output, the value the node which produces
|
||||
* the output result.
|
||||
*
|
||||
* @type {Object<string, Node>}
|
||||
*/
|
||||
this.outputNodes = outputNodes;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isMRTNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the MRT node has an output with the given name.
|
||||
*
|
||||
* @param {string} name - The name of the output.
|
||||
* @return {NodeBuilder} Whether the MRT node has an output for the given name or not.
|
||||
*/
|
||||
has( name ) {
|
||||
|
||||
return this.outputNodes[ name ] !== undefined;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output node for the given name.
|
||||
*
|
||||
* @param {string} name - The name of the output.
|
||||
* @return {Node} The output node.
|
||||
*/
|
||||
get( name ) {
|
||||
|
||||
return this.outputNodes[ name ];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the outputs of the given MRT node with the outputs of this node.
|
||||
*
|
||||
* @param {MRTNode} mrtNode - The MRT to merge.
|
||||
* @return {MRTNode} A new MRT node with merged outputs..
|
||||
*/
|
||||
merge( mrtNode ) {
|
||||
|
||||
const outputs = { ...this.outputNodes, ...mrtNode.outputNodes };
|
||||
|
||||
return mrt( outputs );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const outputNodes = this.outputNodes;
|
||||
const mrt = builder.renderer.getRenderTarget();
|
||||
|
||||
const members = [];
|
||||
|
||||
const textures = mrt.textures;
|
||||
|
||||
for ( const name in outputNodes ) {
|
||||
|
||||
const index = getTextureIndex( textures, name );
|
||||
|
||||
members[ index ] = vec4( outputNodes[ name ] );
|
||||
|
||||
}
|
||||
|
||||
this.members = members;
|
||||
|
||||
return super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MRTNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a MRT node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Object<string, Node>} outputNodes - The MRT outputs.
|
||||
* @returns {MRTNode}
|
||||
*/
|
||||
export const mrt = /*@__PURE__*/ nodeProxy( MRTNode );
|
||||
950
app/node_modules/three/src/nodes/core/Node.js
generated
vendored
Normal file
950
app/node_modules/three/src/nodes/core/Node.js
generated
vendored
Normal file
@@ -0,0 +1,950 @@
|
||||
import { NodeUpdateType } from './constants.js';
|
||||
import { getNodeChildren, getCacheKey, hash } from './NodeUtils.js';
|
||||
|
||||
import { EventDispatcher } from '../../core/EventDispatcher.js';
|
||||
import { MathUtils } from '../../math/MathUtils.js';
|
||||
|
||||
const _parentBuildStage = {
|
||||
analyze: 'setup',
|
||||
generate: 'analyze'
|
||||
};
|
||||
|
||||
let _nodeId = 0;
|
||||
|
||||
/**
|
||||
* Base class for all nodes.
|
||||
*
|
||||
* @augments EventDispatcher
|
||||
*/
|
||||
class Node extends EventDispatcher {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'Node';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new node.
|
||||
*
|
||||
* @param {?string} nodeType - The node type.
|
||||
*/
|
||||
constructor( nodeType = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The node type. This represents the result type of the node (e.g. `float` or `vec3`).
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.nodeType = nodeType;
|
||||
|
||||
/**
|
||||
* The update type of the node's {@link Node#update} method. Possible values are listed in {@link NodeUpdateType}.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'none'
|
||||
*/
|
||||
this.updateType = NodeUpdateType.NONE;
|
||||
|
||||
/**
|
||||
* The update type of the node's {@link Node#updateBefore} method. Possible values are listed in {@link NodeUpdateType}.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'none'
|
||||
*/
|
||||
this.updateBeforeType = NodeUpdateType.NONE;
|
||||
|
||||
/**
|
||||
* The update type of the node's {@link Node#updateAfter} method. Possible values are listed in {@link NodeUpdateType}.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'none'
|
||||
*/
|
||||
this.updateAfterType = NodeUpdateType.NONE;
|
||||
|
||||
/**
|
||||
* The UUID of the node.
|
||||
*
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
this.uuid = MathUtils.generateUUID();
|
||||
|
||||
/**
|
||||
* The version of the node. The version automatically is increased when {@link Node#needsUpdate} is set to `true`.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @default 0
|
||||
*/
|
||||
this.version = 0;
|
||||
|
||||
/**
|
||||
* Whether this node is global or not. This property is relevant for the internal
|
||||
* node caching system. All nodes which should be declared just once should
|
||||
* set this flag to `true` (a typical example is {@link AttributeNode}).
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.global = false;
|
||||
|
||||
/**
|
||||
* Create a list of parents for this node during the build process.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.parents = false;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isNode = true;
|
||||
|
||||
// private
|
||||
|
||||
/**
|
||||
* The cache key of this node.
|
||||
*
|
||||
* @private
|
||||
* @type {?number}
|
||||
* @default null
|
||||
*/
|
||||
this._cacheKey = null;
|
||||
|
||||
/**
|
||||
* The cache key 's version.
|
||||
*
|
||||
* @private
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this._cacheKeyVersion = 0;
|
||||
|
||||
Object.defineProperty( this, 'id', { value: _nodeId ++ } );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this property to `true` when the node should be regenerated.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
* @param {boolean} value
|
||||
*/
|
||||
set needsUpdate( value ) {
|
||||
|
||||
if ( value === true ) {
|
||||
|
||||
this.version ++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the class. The value is usually the constructor name.
|
||||
*
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get type() {
|
||||
|
||||
return this.constructor.type;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method for defining {@link Node#update}.
|
||||
*
|
||||
* @param {Function} callback - The update method.
|
||||
* @param {string} updateType - The update type.
|
||||
* @return {Node} A reference to this node.
|
||||
*/
|
||||
onUpdate( callback, updateType ) {
|
||||
|
||||
this.updateType = updateType;
|
||||
this.update = callback.bind( this.getSelf() );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but
|
||||
* this method automatically sets the update type to `FRAME`.
|
||||
*
|
||||
* @param {Function} callback - The update method.
|
||||
* @return {Node} A reference to this node.
|
||||
*/
|
||||
onFrameUpdate( callback ) {
|
||||
|
||||
return this.onUpdate( callback, NodeUpdateType.FRAME );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but
|
||||
* this method automatically sets the update type to `RENDER`.
|
||||
*
|
||||
* @param {Function} callback - The update method.
|
||||
* @return {Node} A reference to this node.
|
||||
*/
|
||||
onRenderUpdate( callback ) {
|
||||
|
||||
return this.onUpdate( callback, NodeUpdateType.RENDER );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method for defining {@link Node#update}. Similar to {@link Node#onUpdate}, but
|
||||
* this method automatically sets the update type to `OBJECT`.
|
||||
*
|
||||
* @param {Function} callback - The update method.
|
||||
* @return {Node} A reference to this node.
|
||||
*/
|
||||
onObjectUpdate( callback ) {
|
||||
|
||||
return this.onUpdate( callback, NodeUpdateType.OBJECT );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient method for defining {@link Node#updateReference}.
|
||||
*
|
||||
* @param {Function} callback - The update method.
|
||||
* @return {Node} A reference to this node.
|
||||
*/
|
||||
onReference( callback ) {
|
||||
|
||||
this.updateReference = callback.bind( this.getSelf() );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The `this` reference might point to a Proxy so this method can be used
|
||||
* to get the reference to the actual node instance.
|
||||
*
|
||||
* @return {Node} A reference to the node.
|
||||
*/
|
||||
getSelf() {
|
||||
|
||||
// Returns non-node object.
|
||||
|
||||
return this.self || this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Nodes might refer to other objects like materials. This method allows to dynamically update the reference
|
||||
* to such objects based on a given state (e.g. the current node frame or builder).
|
||||
*
|
||||
* @param {any} state - This method can be invocated in different contexts so `state` can refer to any object type.
|
||||
* @return {any} The updated reference.
|
||||
*/
|
||||
updateReference( /*state*/ ) {
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* By default this method returns the value of the {@link Node#global} flag. This method
|
||||
* can be overwritten in derived classes if an analytical way is required to determine the
|
||||
* global cache referring to the current shader-stage.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {boolean} Whether this node is global or not.
|
||||
*/
|
||||
isGlobal( /*builder*/ ) {
|
||||
|
||||
return this.global;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generator function that can be used to iterate over the child nodes.
|
||||
*
|
||||
* @generator
|
||||
* @yields {Node} A child node.
|
||||
*/
|
||||
* getChildren() {
|
||||
|
||||
for ( const { childNode } of getNodeChildren( this ) ) {
|
||||
|
||||
yield childNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling this method dispatches the `dispose` event. This event can be used
|
||||
* to register event listeners for clean up tasks.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.dispatchEvent( { type: 'dispose' } );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for {@link Node#traverse}.
|
||||
*
|
||||
* @callback traverseCallback
|
||||
* @param {Node} node - The current node.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Can be used to traverse through the node's hierarchy.
|
||||
*
|
||||
* @param {traverseCallback} callback - A callback that is executed per node.
|
||||
*/
|
||||
traverse( callback ) {
|
||||
|
||||
callback( this );
|
||||
|
||||
for ( const childNode of this.getChildren() ) {
|
||||
|
||||
childNode.traverse( callback );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache key for this node.
|
||||
*
|
||||
* @param {boolean} [force=false] - When set to `true`, a recomputation of the cache key is forced.
|
||||
* @return {number} The cache key of the node.
|
||||
*/
|
||||
getCacheKey( force = false ) {
|
||||
|
||||
force = force || this.version !== this._cacheKeyVersion;
|
||||
|
||||
if ( force === true || this._cacheKey === null ) {
|
||||
|
||||
this._cacheKey = hash( getCacheKey( this, force ), this.customCacheKey() );
|
||||
this._cacheKeyVersion = this.version;
|
||||
|
||||
}
|
||||
|
||||
return this._cacheKey;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a custom cache key for this node.
|
||||
*
|
||||
* @return {number} The cache key of the node.
|
||||
*/
|
||||
customCacheKey() {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the references to this node which is by default `this`.
|
||||
*
|
||||
* @return {Node} A reference to this node.
|
||||
*/
|
||||
getScope() {
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash of the node which is used to identify the node. By default it's
|
||||
* the {@link Node#uuid} however derived node classes might have to overwrite this method
|
||||
* depending on their implementation.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The hash.
|
||||
*/
|
||||
getHash( /*builder*/ ) {
|
||||
|
||||
return this.uuid;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the update type of {@link Node#update}.
|
||||
*
|
||||
* @return {NodeUpdateType} The update type.
|
||||
*/
|
||||
getUpdateType() {
|
||||
|
||||
return this.updateType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the update type of {@link Node#updateBefore}.
|
||||
*
|
||||
* @return {NodeUpdateType} The update type.
|
||||
*/
|
||||
getUpdateBeforeType() {
|
||||
|
||||
return this.updateBeforeType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the update type of {@link Node#updateAfter}.
|
||||
*
|
||||
* @return {NodeUpdateType} The update type.
|
||||
*/
|
||||
getUpdateAfterType() {
|
||||
|
||||
return this.updateAfterType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Certain types are composed of multiple elements. For example a `vec3`
|
||||
* is composed of three `float` values. This method returns the type of
|
||||
* these elements.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The type of the node.
|
||||
*/
|
||||
getElementType( builder ) {
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
const elementType = builder.getElementType( type );
|
||||
|
||||
return elementType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node member type for the given name.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} name - The name of the member.
|
||||
* @return {string} The type of the node.
|
||||
*/
|
||||
getMemberType( /*builder, name*/ ) {
|
||||
|
||||
return 'void';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node's type.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {string} The type of the node.
|
||||
*/
|
||||
getNodeType( builder ) {
|
||||
|
||||
const nodeProperties = builder.getNodeProperties( this );
|
||||
|
||||
if ( nodeProperties.outputNode ) {
|
||||
|
||||
return nodeProperties.outputNode.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
return this.nodeType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used during the build process of a node and ensures
|
||||
* equal nodes are not built multiple times but just once. For example if
|
||||
* `attribute( 'uv' )` is used multiple times by the user, the build
|
||||
* process makes sure to process just the first node.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {Node} The shared node if possible. Otherwise `this` is returned.
|
||||
*/
|
||||
getShared( builder ) {
|
||||
|
||||
const hash = this.getHash( builder );
|
||||
const nodeFromHash = builder.getNodeFromHash( hash );
|
||||
|
||||
return nodeFromHash || this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the setup stage which is the first step of the build process, see {@link Node#build} method.
|
||||
* This method is often overwritten in derived modules to prepare the node which is used as the output/result.
|
||||
* The output node must be returned in the `return` statement.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @return {?Node} The output node.
|
||||
*/
|
||||
setup( builder ) {
|
||||
|
||||
const nodeProperties = builder.getNodeProperties( this );
|
||||
|
||||
let index = 0;
|
||||
|
||||
for ( const childNode of this.getChildren() ) {
|
||||
|
||||
nodeProperties[ 'node' + index ++ ] = childNode;
|
||||
|
||||
}
|
||||
|
||||
// return a outputNode if exists or null
|
||||
|
||||
return nodeProperties.outputNode || null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the analyze stage which is the second step of the build process, see {@link Node#build} method.
|
||||
* This stage analyzes the node hierarchy and ensures descendent nodes are built.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {?Node} output - The target output node.
|
||||
*/
|
||||
analyze( builder, output = null ) {
|
||||
|
||||
const usageCount = builder.increaseUsage( this );
|
||||
|
||||
if ( this.parents === true ) {
|
||||
|
||||
const nodeData = builder.getDataFromNode( this, 'any' );
|
||||
nodeData.stages = nodeData.stages || {};
|
||||
nodeData.stages[ builder.shaderStage ] = nodeData.stages[ builder.shaderStage ] || [];
|
||||
nodeData.stages[ builder.shaderStage ].push( output );
|
||||
|
||||
}
|
||||
|
||||
if ( usageCount === 1 ) {
|
||||
|
||||
// node flow children
|
||||
|
||||
const nodeProperties = builder.getNodeProperties( this );
|
||||
|
||||
for ( const childNode of Object.values( nodeProperties ) ) {
|
||||
|
||||
if ( childNode && childNode.isNode === true ) {
|
||||
|
||||
childNode.build( builder, this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the generate stage which is the third step of the build process, see {@link Node#build} method.
|
||||
* This state builds the output node and returns the resulting shader string.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {?string} output - Can be used to define the output type.
|
||||
* @return {?string} The generated shader string.
|
||||
*/
|
||||
generate( builder, output ) {
|
||||
|
||||
const { outputNode } = builder.getNodeProperties( this );
|
||||
|
||||
if ( outputNode && outputNode.isNode === true ) {
|
||||
|
||||
return outputNode.build( builder, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The method can be implemented to update the node's internal state before it is used to render an object.
|
||||
* The {@link Node#updateBeforeType} property defines how often the update is executed.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
* @return {?boolean} An optional bool that indicates whether the implementation actually performed an update or not (e.g. due to caching).
|
||||
*/
|
||||
updateBefore( /*frame*/ ) {
|
||||
|
||||
console.warn( 'Abstract function.' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The method can be implemented to update the node's internal state after it was used to render an object.
|
||||
* The {@link Node#updateAfterType} property defines how often the update is executed.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
* @return {?boolean} An optional bool that indicates whether the implementation actually performed an update or not (e.g. due to caching).
|
||||
*/
|
||||
updateAfter( /*frame*/ ) {
|
||||
|
||||
console.warn( 'Abstract function.' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The method can be implemented to update the node's internal state when it is used to render an object.
|
||||
* The {@link Node#updateType} property defines how often the update is executed.
|
||||
*
|
||||
* @abstract
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
* @return {?boolean} An optional bool that indicates whether the implementation actually performed an update or not (e.g. due to caching).
|
||||
*/
|
||||
update( /*frame*/ ) {
|
||||
|
||||
console.warn( 'Abstract function.' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method performs the build of a node. The behavior and return value depend on the current build stage:
|
||||
* - **setup**: Prepares the node and its children for the build process. This process can also create new nodes. Returns the node itself or a variant.
|
||||
* - **analyze**: Analyzes the node hierarchy for optimizations in the code generation stage. Returns `null`.
|
||||
* - **generate**: Generates the shader code for the node. Returns the generated shader string.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string|Node|null} [output=null] - Can be used to define the output type.
|
||||
* @return {Node|string|null} The result of the build process, depending on the build stage.
|
||||
*/
|
||||
build( builder, output = null ) {
|
||||
|
||||
const refNode = this.getShared( builder );
|
||||
|
||||
if ( this !== refNode ) {
|
||||
|
||||
return refNode.build( builder, output );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const nodeData = builder.getDataFromNode( this );
|
||||
nodeData.buildStages = nodeData.buildStages || {};
|
||||
nodeData.buildStages[ builder.buildStage ] = true;
|
||||
|
||||
const parentBuildStage = _parentBuildStage[ builder.buildStage ];
|
||||
|
||||
if ( parentBuildStage && nodeData.buildStages[ parentBuildStage ] !== true ) {
|
||||
|
||||
// force parent build stage (setup or analyze)
|
||||
|
||||
const previousBuildStage = builder.getBuildStage();
|
||||
|
||||
builder.setBuildStage( parentBuildStage );
|
||||
|
||||
this.build( builder );
|
||||
|
||||
builder.setBuildStage( previousBuildStage );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
builder.addNode( this );
|
||||
builder.addChain( this );
|
||||
|
||||
/* Build stages expected results:
|
||||
- "setup" -> Node
|
||||
- "analyze" -> null
|
||||
- "generate" -> String
|
||||
*/
|
||||
let result = null;
|
||||
|
||||
const buildStage = builder.getBuildStage();
|
||||
|
||||
if ( buildStage === 'setup' ) {
|
||||
|
||||
this.updateReference( builder );
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
|
||||
if ( properties.initialized !== true ) {
|
||||
|
||||
//const stackNodesBeforeSetup = builder.stack.nodes.length;
|
||||
|
||||
properties.initialized = true;
|
||||
properties.outputNode = this.setup( builder ) || properties.outputNode || null;
|
||||
|
||||
/*if ( isNodeOutput && builder.stack.nodes.length !== stackNodesBeforeSetup ) {
|
||||
|
||||
// !! no outputNode !!
|
||||
//outputNode = builder.stack;
|
||||
|
||||
}*/
|
||||
|
||||
for ( const childNode of Object.values( properties ) ) {
|
||||
|
||||
if ( childNode && childNode.isNode === true ) {
|
||||
|
||||
if ( childNode.parents === true ) {
|
||||
|
||||
const childProperties = builder.getNodeProperties( childNode );
|
||||
childProperties.parents = childProperties.parents || [];
|
||||
childProperties.parents.push( this );
|
||||
|
||||
}
|
||||
|
||||
childNode.build( builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result = properties.outputNode;
|
||||
|
||||
} else if ( buildStage === 'analyze' ) {
|
||||
|
||||
this.analyze( builder, output );
|
||||
|
||||
} else if ( buildStage === 'generate' ) {
|
||||
|
||||
const isGenerateOnce = this.generate.length === 1;
|
||||
|
||||
if ( isGenerateOnce ) {
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
const nodeData = builder.getDataFromNode( this );
|
||||
|
||||
result = nodeData.snippet;
|
||||
|
||||
if ( result === undefined ) {
|
||||
|
||||
if ( nodeData.generated === undefined ) {
|
||||
|
||||
nodeData.generated = true;
|
||||
|
||||
result = this.generate( builder ) || '';
|
||||
|
||||
nodeData.snippet = result;
|
||||
|
||||
} else {
|
||||
|
||||
console.warn( 'THREE.Node: Recursion detected.', this );
|
||||
|
||||
result = '/* Recursion detected. */';
|
||||
|
||||
}
|
||||
|
||||
} else if ( nodeData.flowCodes !== undefined && builder.context.nodeBlock !== undefined ) {
|
||||
|
||||
builder.addFlowCodeHierarchy( this, builder.context.nodeBlock );
|
||||
|
||||
}
|
||||
|
||||
result = builder.format( result, type, output );
|
||||
|
||||
} else {
|
||||
|
||||
result = this.generate( builder, output ) || '';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
builder.removeChain( this );
|
||||
builder.addSequentialNode( this );
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child nodes as a JSON object.
|
||||
*
|
||||
* @return {Array<Object>} An iterable list of serialized child objects as JSON.
|
||||
*/
|
||||
getSerializeChildren() {
|
||||
|
||||
return getNodeChildren( this );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the node to JSON.
|
||||
*
|
||||
* @param {Object} json - The output JSON object.
|
||||
*/
|
||||
serialize( json ) {
|
||||
|
||||
const nodeChildren = this.getSerializeChildren();
|
||||
|
||||
const inputNodes = {};
|
||||
|
||||
for ( const { property, index, childNode } of nodeChildren ) {
|
||||
|
||||
if ( index !== undefined ) {
|
||||
|
||||
if ( inputNodes[ property ] === undefined ) {
|
||||
|
||||
inputNodes[ property ] = Number.isInteger( index ) ? [] : {};
|
||||
|
||||
}
|
||||
|
||||
inputNodes[ property ][ index ] = childNode.toJSON( json.meta ).uuid;
|
||||
|
||||
} else {
|
||||
|
||||
inputNodes[ property ] = childNode.toJSON( json.meta ).uuid;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( Object.keys( inputNodes ).length > 0 ) {
|
||||
|
||||
json.inputNodes = inputNodes;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the node from the given JSON.
|
||||
*
|
||||
* @param {Object} json - The JSON object.
|
||||
*/
|
||||
deserialize( json ) {
|
||||
|
||||
if ( json.inputNodes !== undefined ) {
|
||||
|
||||
const nodes = json.meta.nodes;
|
||||
|
||||
for ( const property in json.inputNodes ) {
|
||||
|
||||
if ( Array.isArray( json.inputNodes[ property ] ) ) {
|
||||
|
||||
const inputArray = [];
|
||||
|
||||
for ( const uuid of json.inputNodes[ property ] ) {
|
||||
|
||||
inputArray.push( nodes[ uuid ] );
|
||||
|
||||
}
|
||||
|
||||
this[ property ] = inputArray;
|
||||
|
||||
} else if ( typeof json.inputNodes[ property ] === 'object' ) {
|
||||
|
||||
const inputObject = {};
|
||||
|
||||
for ( const subProperty in json.inputNodes[ property ] ) {
|
||||
|
||||
const uuid = json.inputNodes[ property ][ subProperty ];
|
||||
|
||||
inputObject[ subProperty ] = nodes[ uuid ];
|
||||
|
||||
}
|
||||
|
||||
this[ property ] = inputObject;
|
||||
|
||||
} else {
|
||||
|
||||
const uuid = json.inputNodes[ property ];
|
||||
|
||||
this[ property ] = nodes[ uuid ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the node into the three.js JSON Object/Scene format.
|
||||
*
|
||||
* @param {?Object} meta - An optional JSON object that already holds serialized data from other scene objects.
|
||||
* @return {Object} The serialized node.
|
||||
*/
|
||||
toJSON( meta ) {
|
||||
|
||||
const { uuid, type } = this;
|
||||
const isRoot = ( meta === undefined || typeof meta === 'string' );
|
||||
|
||||
if ( isRoot ) {
|
||||
|
||||
meta = {
|
||||
textures: {},
|
||||
images: {},
|
||||
nodes: {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// serialize
|
||||
|
||||
let data = meta.nodes[ uuid ];
|
||||
|
||||
if ( data === undefined ) {
|
||||
|
||||
data = {
|
||||
uuid,
|
||||
type,
|
||||
meta,
|
||||
metadata: {
|
||||
version: 4.7,
|
||||
type: 'Node',
|
||||
generator: 'Node.toJSON'
|
||||
}
|
||||
};
|
||||
|
||||
if ( isRoot !== true ) meta.nodes[ data.uuid ] = data;
|
||||
|
||||
this.serialize( data );
|
||||
|
||||
delete data.meta;
|
||||
|
||||
}
|
||||
|
||||
// TODO: Copied from Object3D.toJSON
|
||||
|
||||
function extractFromCache( cache ) {
|
||||
|
||||
const values = [];
|
||||
|
||||
for ( const key in cache ) {
|
||||
|
||||
const data = cache[ key ];
|
||||
delete data.metadata;
|
||||
values.push( data );
|
||||
|
||||
}
|
||||
|
||||
return values;
|
||||
|
||||
}
|
||||
|
||||
if ( isRoot ) {
|
||||
|
||||
const textures = extractFromCache( meta.textures );
|
||||
const images = extractFromCache( meta.images );
|
||||
const nodes = extractFromCache( meta.nodes );
|
||||
|
||||
if ( textures.length > 0 ) data.textures = textures;
|
||||
if ( images.length > 0 ) data.images = images;
|
||||
if ( nodes.length > 0 ) data.nodes = nodes;
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Node;
|
||||
53
app/node_modules/three/src/nodes/core/NodeAttribute.js
generated
vendored
Normal file
53
app/node_modules/three/src/nodes/core/NodeAttribute.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* {@link NodeBuilder} is going to create instances of this class during the build process
|
||||
* of nodes. They represent the final shader attributes that are going to be generated
|
||||
* by the builder. Arrays of node attributes is maintained in {@link NodeBuilder#attributes}
|
||||
* and {@link NodeBuilder#bufferAttributes} for this purpose.
|
||||
*/
|
||||
class NodeAttribute {
|
||||
|
||||
/**
|
||||
* Constructs a new node attribute.
|
||||
*
|
||||
* @param {string} name - The name of the attribute.
|
||||
* @param {string} type - The type of the attribute.
|
||||
* @param {?Node} node - An optional reference to the node.
|
||||
*/
|
||||
constructor( name, type, node = null ) {
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isNodeAttribute = true;
|
||||
|
||||
/**
|
||||
* The name of the attribute.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The type of the attribute.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* An optional reference to the node.
|
||||
*
|
||||
* @type {?Node}
|
||||
* @default null
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeAttribute;
|
||||
2928
app/node_modules/three/src/nodes/core/NodeBuilder.js
generated
vendored
Normal file
2928
app/node_modules/three/src/nodes/core/NodeBuilder.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
75
app/node_modules/three/src/nodes/core/NodeCache.js
generated
vendored
Normal file
75
app/node_modules/three/src/nodes/core/NodeCache.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
let _id = 0;
|
||||
|
||||
/**
|
||||
* This utility class is used in {@link NodeBuilder} as an internal
|
||||
* cache data structure for node data.
|
||||
*/
|
||||
class NodeCache {
|
||||
|
||||
/**
|
||||
* Constructs a new node cache.
|
||||
*
|
||||
* @param {?NodeCache} parent - A reference to a parent cache.
|
||||
*/
|
||||
constructor( parent = null ) {
|
||||
|
||||
/**
|
||||
* The id of the cache.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
this.id = _id ++;
|
||||
|
||||
/**
|
||||
* A weak map for managing node data.
|
||||
*
|
||||
* @type {WeakMap<Node, Object>}
|
||||
*/
|
||||
this.nodesData = new WeakMap();
|
||||
|
||||
/**
|
||||
* Reference to a parent node cache.
|
||||
*
|
||||
* @type {?NodeCache}
|
||||
* @default null
|
||||
*/
|
||||
this.parent = parent;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data for the given node.
|
||||
*
|
||||
* @param {Node} node - The node.
|
||||
* @return {?Object} The data for the node.
|
||||
*/
|
||||
getData( node ) {
|
||||
|
||||
let data = this.nodesData.get( node );
|
||||
|
||||
if ( data === undefined && this.parent !== null ) {
|
||||
|
||||
data = this.parent.getData( node );
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data for a given node.
|
||||
*
|
||||
* @param {Node} node - The node.
|
||||
* @param {Object} data - The data that should be cached.
|
||||
*/
|
||||
setData( node, data ) {
|
||||
|
||||
this.nodesData.set( node, data );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeCache;
|
||||
46
app/node_modules/three/src/nodes/core/NodeCode.js
generated
vendored
Normal file
46
app/node_modules/three/src/nodes/core/NodeCode.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* {@link NodeBuilder} is going to create instances of this class during the build process
|
||||
* of nodes. They represent user-defined, native shader code portions that are going to be
|
||||
* injected by the builder. A dictionary of node codes is maintained in {@link NodeBuilder#codes}
|
||||
* for this purpose.
|
||||
*/
|
||||
class NodeCode {
|
||||
|
||||
/**
|
||||
* Constructs a new code node.
|
||||
*
|
||||
* @param {string} name - The name of the code.
|
||||
* @param {string} type - The node type.
|
||||
* @param {string} [code=''] - The native shader code.
|
||||
*/
|
||||
constructor( name, type, code = '' ) {
|
||||
|
||||
/**
|
||||
* The name of the code.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The node type.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* The native shader code.
|
||||
*
|
||||
* @type {string}
|
||||
* @default ''
|
||||
*/
|
||||
this.code = code;
|
||||
|
||||
Object.defineProperty( this, 'isNodeCode', { value: true } );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeCode;
|
||||
306
app/node_modules/three/src/nodes/core/NodeFrame.js
generated
vendored
Normal file
306
app/node_modules/three/src/nodes/core/NodeFrame.js
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
import { NodeUpdateType } from './constants.js';
|
||||
|
||||
/**
|
||||
* Management class for updating nodes. The module tracks metrics like
|
||||
* the elapsed time, delta time, the render and frame ID to correctly
|
||||
* call the node update methods {@link Node#updateBefore}, {@link Node#update}
|
||||
* and {@link Node#updateAfter} depending on the node's configuration.
|
||||
*/
|
||||
class NodeFrame {
|
||||
|
||||
/**
|
||||
* Constructs a new node fame.
|
||||
*/
|
||||
constructor() {
|
||||
|
||||
/**
|
||||
* The elapsed time in seconds.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.time = 0;
|
||||
|
||||
/**
|
||||
* The delta time in seconds.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.deltaTime = 0;
|
||||
|
||||
/**
|
||||
* The frame ID.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.frameId = 0;
|
||||
|
||||
/**
|
||||
* The render ID.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
this.renderId = 0;
|
||||
|
||||
/**
|
||||
* Used to control the {@link Node#update} call.
|
||||
*
|
||||
* @type {WeakMap<Node, Object>}
|
||||
*/
|
||||
this.updateMap = new WeakMap();
|
||||
|
||||
/**
|
||||
* Used to control the {@link Node#updateBefore} call.
|
||||
*
|
||||
* @type {WeakMap<Node, Object>}
|
||||
*/
|
||||
this.updateBeforeMap = new WeakMap();
|
||||
|
||||
/**
|
||||
* Used to control the {@link Node#updateAfter} call.
|
||||
*
|
||||
* @type {WeakMap<Node, Object>}
|
||||
*/
|
||||
this.updateAfterMap = new WeakMap();
|
||||
|
||||
/**
|
||||
* A reference to the current renderer.
|
||||
*
|
||||
* @type {?Renderer}
|
||||
* @default null
|
||||
*/
|
||||
this.renderer = null;
|
||||
|
||||
/**
|
||||
* A reference to the current material.
|
||||
*
|
||||
* @type {?Material}
|
||||
* @default null
|
||||
*/
|
||||
this.material = null;
|
||||
|
||||
/**
|
||||
* A reference to the current camera.
|
||||
*
|
||||
* @type {?Camera}
|
||||
* @default null
|
||||
*/
|
||||
this.camera = null;
|
||||
|
||||
/**
|
||||
* A reference to the current 3D object.
|
||||
*
|
||||
* @type {?Object3D}
|
||||
* @default null
|
||||
*/
|
||||
this.object = null;
|
||||
|
||||
/**
|
||||
* A reference to the current scene.
|
||||
*
|
||||
* @type {?Scene}
|
||||
* @default null
|
||||
*/
|
||||
this.scene = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a dictionary for a given node and update map which
|
||||
* is used to correctly call node update methods per frame or render.
|
||||
*
|
||||
* @private
|
||||
* @param {WeakMap<Node, Object>} referenceMap - The reference weak map.
|
||||
* @param {Node} nodeRef - The reference to the current node.
|
||||
* @return {Object<string,WeakMap>} The dictionary.
|
||||
*/
|
||||
_getMaps( referenceMap, nodeRef ) {
|
||||
|
||||
let maps = referenceMap.get( nodeRef );
|
||||
|
||||
if ( maps === undefined ) {
|
||||
|
||||
maps = {
|
||||
renderMap: new WeakMap(),
|
||||
frameMap: new WeakMap()
|
||||
};
|
||||
|
||||
referenceMap.set( nodeRef, maps );
|
||||
|
||||
}
|
||||
|
||||
return maps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method executes the {@link Node#updateBefore} for the given node.
|
||||
* It makes sure {@link Node#updateBeforeType} is honored meaning the update
|
||||
* is only executed once per frame, render or object depending on the update
|
||||
* type.
|
||||
*
|
||||
* @param {Node} node - The node that should be updated.
|
||||
*/
|
||||
updateBeforeNode( node ) {
|
||||
|
||||
const updateType = node.getUpdateBeforeType();
|
||||
const reference = node.updateReference( this );
|
||||
|
||||
if ( updateType === NodeUpdateType.FRAME ) {
|
||||
|
||||
const { frameMap } = this._getMaps( this.updateBeforeMap, reference );
|
||||
|
||||
if ( frameMap.get( reference ) !== this.frameId ) {
|
||||
|
||||
if ( node.updateBefore( this ) !== false ) {
|
||||
|
||||
frameMap.set( reference, this.frameId );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( updateType === NodeUpdateType.RENDER ) {
|
||||
|
||||
const { renderMap } = this._getMaps( this.updateBeforeMap, reference );
|
||||
|
||||
if ( renderMap.get( reference ) !== this.renderId ) {
|
||||
|
||||
if ( node.updateBefore( this ) !== false ) {
|
||||
|
||||
renderMap.set( reference, this.renderId );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( updateType === NodeUpdateType.OBJECT ) {
|
||||
|
||||
node.updateBefore( this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method executes the {@link Node#updateAfter} for the given node.
|
||||
* It makes sure {@link Node#updateAfterType} is honored meaning the update
|
||||
* is only executed once per frame, render or object depending on the update
|
||||
* type.
|
||||
*
|
||||
* @param {Node} node - The node that should be updated.
|
||||
*/
|
||||
updateAfterNode( node ) {
|
||||
|
||||
const updateType = node.getUpdateAfterType();
|
||||
const reference = node.updateReference( this );
|
||||
|
||||
if ( updateType === NodeUpdateType.FRAME ) {
|
||||
|
||||
const { frameMap } = this._getMaps( this.updateAfterMap, reference );
|
||||
|
||||
if ( frameMap.get( reference ) !== this.frameId ) {
|
||||
|
||||
if ( node.updateAfter( this ) !== false ) {
|
||||
|
||||
frameMap.set( reference, this.frameId );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( updateType === NodeUpdateType.RENDER ) {
|
||||
|
||||
const { renderMap } = this._getMaps( this.updateAfterMap, reference );
|
||||
|
||||
if ( renderMap.get( reference ) !== this.renderId ) {
|
||||
|
||||
if ( node.updateAfter( this ) !== false ) {
|
||||
|
||||
renderMap.set( reference, this.renderId );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( updateType === NodeUpdateType.OBJECT ) {
|
||||
|
||||
node.updateAfter( this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method executes the {@link Node#update} for the given node.
|
||||
* It makes sure {@link Node#updateType} is honored meaning the update
|
||||
* is only executed once per frame, render or object depending on the update
|
||||
* type.
|
||||
*
|
||||
* @param {Node} node - The node that should be updated.
|
||||
*/
|
||||
updateNode( node ) {
|
||||
|
||||
const updateType = node.getUpdateType();
|
||||
const reference = node.updateReference( this );
|
||||
|
||||
if ( updateType === NodeUpdateType.FRAME ) {
|
||||
|
||||
const { frameMap } = this._getMaps( this.updateMap, reference );
|
||||
|
||||
if ( frameMap.get( reference ) !== this.frameId ) {
|
||||
|
||||
if ( node.update( this ) !== false ) {
|
||||
|
||||
frameMap.set( reference, this.frameId );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( updateType === NodeUpdateType.RENDER ) {
|
||||
|
||||
const { renderMap } = this._getMaps( this.updateMap, reference );
|
||||
|
||||
if ( renderMap.get( reference ) !== this.renderId ) {
|
||||
|
||||
if ( node.update( this ) !== false ) {
|
||||
|
||||
renderMap.set( reference, this.renderId );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( updateType === NodeUpdateType.OBJECT ) {
|
||||
|
||||
node.update( this );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal state of the node frame. This method is
|
||||
* called by the renderer in its internal animation loop.
|
||||
*/
|
||||
update() {
|
||||
|
||||
this.frameId ++;
|
||||
|
||||
if ( this.lastTime === undefined ) this.lastTime = performance.now();
|
||||
|
||||
this.deltaTime = ( performance.now() - this.lastTime ) / 1000;
|
||||
|
||||
this.lastTime = performance.now();
|
||||
|
||||
this.time += this.deltaTime;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeFrame;
|
||||
68
app/node_modules/three/src/nodes/core/NodeFunction.js
generated
vendored
Normal file
68
app/node_modules/three/src/nodes/core/NodeFunction.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Base class for node functions. A derived module must be implemented
|
||||
* for each supported native shader language. Similar to other `Node*` modules,
|
||||
* this class is only relevant during the building process and not used
|
||||
* in user-level code.
|
||||
*/
|
||||
class NodeFunction {
|
||||
|
||||
/**
|
||||
* Constructs a new node function.
|
||||
*
|
||||
* @param {string} type - The node type. This type is the return type of the node function.
|
||||
* @param {Array<NodeFunctionInput>} inputs - The function's inputs.
|
||||
* @param {string} [name=''] - The function's name.
|
||||
* @param {string} [precision=''] - The precision qualifier.
|
||||
*/
|
||||
constructor( type, inputs, name = '', precision = '' ) {
|
||||
|
||||
/**
|
||||
* The node type. This type is the return type of the node function.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* The function's inputs.
|
||||
*
|
||||
* @type {Array<NodeFunctionInput>}
|
||||
*/
|
||||
this.inputs = inputs;
|
||||
|
||||
/**
|
||||
* The name of the uniform.
|
||||
*
|
||||
* @type {string}
|
||||
* @default ''
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The precision qualifier.
|
||||
*
|
||||
* @type {string}
|
||||
* @default ''
|
||||
*/
|
||||
this.precision = precision;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the native code of the node function.
|
||||
*
|
||||
* @abstract
|
||||
* @param {string} name - The function's name.
|
||||
* @return {string} A shader code.
|
||||
*/
|
||||
getCode( /*name = this.name*/ ) {
|
||||
|
||||
console.warn( 'Abstract function.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NodeFunction.isNodeFunction = true;
|
||||
|
||||
export default NodeFunction;
|
||||
61
app/node_modules/three/src/nodes/core/NodeFunctionInput.js
generated
vendored
Normal file
61
app/node_modules/three/src/nodes/core/NodeFunctionInput.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Describes the input of a {@link NodeFunction}.
|
||||
*/
|
||||
class NodeFunctionInput {
|
||||
|
||||
/**
|
||||
* Constructs a new node function input.
|
||||
*
|
||||
* @param {string} type - The input type.
|
||||
* @param {string} name - The input name.
|
||||
* @param {?number} [count=null] - If the input is an Array, count will be the length.
|
||||
* @param {('in'|'out'|'inout')} [qualifier=''] - The parameter qualifier (only relevant for GLSL).
|
||||
* @param {boolean} [isConst=false] - Whether the input uses a const qualifier or not (only relevant for GLSL).
|
||||
*/
|
||||
constructor( type, name, count = null, qualifier = '', isConst = false ) {
|
||||
|
||||
/**
|
||||
* The input type.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* The input name.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* If the input is an Array, count will be the length.
|
||||
*
|
||||
* @type {?number}
|
||||
* @default null
|
||||
*/
|
||||
this.count = count;
|
||||
|
||||
/**
|
||||
*The parameter qualifier (only relevant for GLSL).
|
||||
*
|
||||
* @type {('in'|'out'|'inout')}
|
||||
* @default ''
|
||||
*/
|
||||
this.qualifier = qualifier;
|
||||
|
||||
/**
|
||||
* Whether the input uses a const qualifier or not (only relevant for GLSL).
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.isConst = isConst;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NodeFunctionInput.isNodeFunctionInput = true;
|
||||
|
||||
export default NodeFunctionInput;
|
||||
22
app/node_modules/three/src/nodes/core/NodeParser.js
generated
vendored
Normal file
22
app/node_modules/three/src/nodes/core/NodeParser.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Base class for node parsers. A derived parser must be implemented
|
||||
* for each supported native shader language.
|
||||
*/
|
||||
class NodeParser {
|
||||
|
||||
/**
|
||||
* The method parses the given native code an returns a node function.
|
||||
*
|
||||
* @abstract
|
||||
* @param {string} source - The native shader code.
|
||||
* @return {NodeFunction} A node function.
|
||||
*/
|
||||
parseFunction( /*source*/ ) {
|
||||
|
||||
console.warn( 'Abstract function.' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeParser;
|
||||
91
app/node_modules/three/src/nodes/core/NodeUniform.js
generated
vendored
Normal file
91
app/node_modules/three/src/nodes/core/NodeUniform.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* {@link NodeBuilder} is going to create instances of this class during the build process
|
||||
* of nodes. They represent the final shader uniforms that are going to be generated
|
||||
* by the builder. A dictionary of node uniforms is maintained in {@link NodeBuilder#uniforms}
|
||||
* for this purpose.
|
||||
*/
|
||||
class NodeUniform {
|
||||
|
||||
/**
|
||||
* Constructs a new node uniform.
|
||||
*
|
||||
* @param {string} name - The name of the uniform.
|
||||
* @param {string} type - The type of the uniform.
|
||||
* @param {UniformNode} node - An reference to the node.
|
||||
*/
|
||||
constructor( name, type, node ) {
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isNodeUniform = true;
|
||||
|
||||
/**
|
||||
* The name of the uniform.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The type of the uniform.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* An reference to the node.
|
||||
*
|
||||
* @type {UniformNode}
|
||||
*/
|
||||
this.node = node.getSelf();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of the uniform node.
|
||||
*
|
||||
* @type {any}
|
||||
*/
|
||||
get value() {
|
||||
|
||||
return this.node.value;
|
||||
|
||||
}
|
||||
|
||||
set value( val ) {
|
||||
|
||||
this.node.value = val;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The id of the uniform node.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
get id() {
|
||||
|
||||
return this.node.id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The uniform node's group.
|
||||
*
|
||||
* @type {UniformGroupNode}
|
||||
*/
|
||||
get groupNode() {
|
||||
|
||||
return this.node.groupNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeUniform;
|
||||
477
app/node_modules/three/src/nodes/core/NodeUtils.js
generated
vendored
Normal file
477
app/node_modules/three/src/nodes/core/NodeUtils.js
generated
vendored
Normal file
@@ -0,0 +1,477 @@
|
||||
import { Color } from '../../math/Color.js';
|
||||
import { Matrix2 } from '../../math/Matrix2.js';
|
||||
import { Matrix3 } from '../../math/Matrix3.js';
|
||||
import { Matrix4 } from '../../math/Matrix4.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
|
||||
// cyrb53 (c) 2018 bryc (github.com/bryc). License: Public domain. Attribution appreciated.
|
||||
// A fast and simple 64-bit (or 53-bit) string hash function with decent collision resistance.
|
||||
// Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity.
|
||||
// See https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript/52171480#52171480
|
||||
// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js
|
||||
function cyrb53( value, seed = 0 ) {
|
||||
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
|
||||
if ( value instanceof Array ) {
|
||||
|
||||
for ( let i = 0, val; i < value.length; i ++ ) {
|
||||
|
||||
val = value[ i ];
|
||||
h1 = Math.imul( h1 ^ val, 2654435761 );
|
||||
h2 = Math.imul( h2 ^ val, 1597334677 );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for ( let i = 0, ch; i < value.length; i ++ ) {
|
||||
|
||||
ch = value.charCodeAt( i );
|
||||
h1 = Math.imul( h1 ^ ch, 2654435761 );
|
||||
h2 = Math.imul( h2 ^ ch, 1597334677 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
h1 = Math.imul( h1 ^ ( h1 >>> 16 ), 2246822507 );
|
||||
h1 ^= Math.imul( h2 ^ ( h2 >>> 13 ), 3266489909 );
|
||||
h2 = Math.imul( h2 ^ ( h2 >>> 16 ), 2246822507 );
|
||||
h2 ^= Math.imul( h1 ^ ( h1 >>> 13 ), 3266489909 );
|
||||
|
||||
return 4294967296 * ( 2097151 & h2 ) + ( h1 >>> 0 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hash for the given string.
|
||||
*
|
||||
* @method
|
||||
* @param {string} str - The string to be hashed.
|
||||
* @return {number} The hash.
|
||||
*/
|
||||
export const hashString = ( str ) => cyrb53( str );
|
||||
|
||||
/**
|
||||
* Computes a hash for the given array.
|
||||
*
|
||||
* @method
|
||||
* @param {Array<number>} array - The array to be hashed.
|
||||
* @return {number} The hash.
|
||||
*/
|
||||
export const hashArray = ( array ) => cyrb53( array );
|
||||
|
||||
/**
|
||||
* Computes a hash for the given list of parameters.
|
||||
*
|
||||
* @method
|
||||
* @param {...number} params - A list of parameters.
|
||||
* @return {number} The hash.
|
||||
*/
|
||||
export const hash = ( ...params ) => cyrb53( params );
|
||||
|
||||
/**
|
||||
* Computes a cache key for the given node.
|
||||
*
|
||||
* @method
|
||||
* @param {Object|Node} object - The object to be hashed.
|
||||
* @param {boolean} [force=false] - Whether to force a cache key computation or not.
|
||||
* @return {number} The hash.
|
||||
*/
|
||||
export function getCacheKey( object, force = false ) {
|
||||
|
||||
const values = [];
|
||||
|
||||
if ( object.isNode === true ) {
|
||||
|
||||
values.push( object.id );
|
||||
object = object.getSelf();
|
||||
|
||||
}
|
||||
|
||||
for ( const { property, childNode } of getNodeChildren( object ) ) {
|
||||
|
||||
values.push( cyrb53( property.slice( 0, - 4 ) ), childNode.getCacheKey( force ) );
|
||||
|
||||
}
|
||||
|
||||
return cyrb53( values );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This generator function can be used to iterate over the node children
|
||||
* of the given object.
|
||||
*
|
||||
* @generator
|
||||
* @param {Object} node - The object to be hashed.
|
||||
* @param {boolean} [toJSON=false] - Whether to return JSON or not.
|
||||
* @yields {Object} A result node holding the property, index (if available) and the child node.
|
||||
*/
|
||||
export function* getNodeChildren( node, toJSON = false ) {
|
||||
|
||||
for ( const property in node ) {
|
||||
|
||||
// Ignore private properties.
|
||||
if ( property.startsWith( '_' ) === true ) continue;
|
||||
|
||||
const object = node[ property ];
|
||||
|
||||
if ( Array.isArray( object ) === true ) {
|
||||
|
||||
for ( let i = 0; i < object.length; i ++ ) {
|
||||
|
||||
const child = object[ i ];
|
||||
|
||||
if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) {
|
||||
|
||||
yield { property, index: i, childNode: child };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if ( object && object.isNode === true ) {
|
||||
|
||||
yield { property, childNode: object };
|
||||
|
||||
} else if ( typeof object === 'object' ) {
|
||||
|
||||
for ( const subProperty in object ) {
|
||||
|
||||
const child = object[ subProperty ];
|
||||
|
||||
if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) {
|
||||
|
||||
yield { property, index: subProperty, childNode: child };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const typeFromLength = /*@__PURE__*/ new Map( [
|
||||
[ 1, 'float' ],
|
||||
[ 2, 'vec2' ],
|
||||
[ 3, 'vec3' ],
|
||||
[ 4, 'vec4' ],
|
||||
[ 9, 'mat3' ],
|
||||
[ 16, 'mat4' ]
|
||||
] );
|
||||
|
||||
const dataFromObject = /*@__PURE__*/ new WeakMap();
|
||||
|
||||
/**
|
||||
* Returns the data type for the given the length.
|
||||
*
|
||||
* @method
|
||||
* @param {number} length - The length.
|
||||
* @return {string} The data type.
|
||||
*/
|
||||
export function getTypeFromLength( length ) {
|
||||
|
||||
return typeFromLength.get( length );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the typed array for the given data type.
|
||||
*
|
||||
* @method
|
||||
* @param {string} type - The data type.
|
||||
* @return {TypedArray} The typed array.
|
||||
*/
|
||||
export function getTypedArrayFromType( type ) {
|
||||
|
||||
// Handle component type for vectors and matrices
|
||||
if ( /[iu]?vec\d/.test( type ) ) {
|
||||
|
||||
// Handle int vectors
|
||||
if ( type.startsWith( 'ivec' ) ) return Int32Array;
|
||||
// Handle uint vectors
|
||||
if ( type.startsWith( 'uvec' ) ) return Uint32Array;
|
||||
// Default to float vectors
|
||||
return Float32Array;
|
||||
|
||||
}
|
||||
|
||||
// Handle matrices (always float)
|
||||
if ( /mat\d/.test( type ) ) return Float32Array;
|
||||
|
||||
// Basic types
|
||||
if ( /float/.test( type ) ) return Float32Array;
|
||||
if ( /uint/.test( type ) ) return Uint32Array;
|
||||
if ( /int/.test( type ) ) return Int32Array;
|
||||
|
||||
throw new Error( `THREE.NodeUtils: Unsupported type: ${type}` );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length for the given data type.
|
||||
*
|
||||
* @method
|
||||
* @param {string} type - The data type.
|
||||
* @return {number} The length.
|
||||
*/
|
||||
export function getLengthFromType( type ) {
|
||||
|
||||
if ( /float|int|uint/.test( type ) ) return 1;
|
||||
if ( /vec2/.test( type ) ) return 2;
|
||||
if ( /vec3/.test( type ) ) return 3;
|
||||
if ( /vec4/.test( type ) ) return 4;
|
||||
if ( /mat2/.test( type ) ) return 4;
|
||||
if ( /mat3/.test( type ) ) return 9;
|
||||
if ( /mat4/.test( type ) ) return 16;
|
||||
|
||||
console.error( 'THREE.TSL: Unsupported type:', type );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the gpu memory length for the given data type.
|
||||
*
|
||||
* @method
|
||||
* @param {string} type - The data type.
|
||||
* @return {number} The length.
|
||||
*/
|
||||
export function getMemoryLengthFromType( type ) {
|
||||
|
||||
if ( /float|int|uint/.test( type ) ) return 1;
|
||||
if ( /vec2/.test( type ) ) return 2;
|
||||
if ( /vec3/.test( type ) ) return 3;
|
||||
if ( /vec4/.test( type ) ) return 4;
|
||||
if ( /mat2/.test( type ) ) return 4;
|
||||
if ( /mat3/.test( type ) ) return 12;
|
||||
if ( /mat4/.test( type ) ) return 16;
|
||||
|
||||
console.error( 'THREE.TSL: Unsupported type:', type );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte boundary for the given data type.
|
||||
*
|
||||
* @method
|
||||
* @param {string} type - The data type.
|
||||
* @return {number} The byte boundary.
|
||||
*/
|
||||
export function getByteBoundaryFromType( type ) {
|
||||
|
||||
if ( /float|int|uint/.test( type ) ) return 4;
|
||||
if ( /vec2/.test( type ) ) return 8;
|
||||
if ( /vec3/.test( type ) ) return 16;
|
||||
if ( /vec4/.test( type ) ) return 16;
|
||||
if ( /mat2/.test( type ) ) return 8;
|
||||
if ( /mat3/.test( type ) ) return 48;
|
||||
if ( /mat4/.test( type ) ) return 64;
|
||||
|
||||
console.error( 'THREE.TSL: Unsupported type:', type );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data type for the given value.
|
||||
*
|
||||
* @method
|
||||
* @param {any} value - The value.
|
||||
* @return {?string} The data type.
|
||||
*/
|
||||
export function getValueType( value ) {
|
||||
|
||||
if ( value === undefined || value === null ) return null;
|
||||
|
||||
const typeOf = typeof value;
|
||||
|
||||
if ( value.isNode === true ) {
|
||||
|
||||
return 'node';
|
||||
|
||||
} else if ( typeOf === 'number' ) {
|
||||
|
||||
return 'float';
|
||||
|
||||
} else if ( typeOf === 'boolean' ) {
|
||||
|
||||
return 'bool';
|
||||
|
||||
} else if ( typeOf === 'string' ) {
|
||||
|
||||
return 'string';
|
||||
|
||||
} else if ( typeOf === 'function' ) {
|
||||
|
||||
return 'shader';
|
||||
|
||||
} else if ( value.isVector2 === true ) {
|
||||
|
||||
return 'vec2';
|
||||
|
||||
} else if ( value.isVector3 === true ) {
|
||||
|
||||
return 'vec3';
|
||||
|
||||
} else if ( value.isVector4 === true ) {
|
||||
|
||||
return 'vec4';
|
||||
|
||||
} else if ( value.isMatrix2 === true ) {
|
||||
|
||||
return 'mat2';
|
||||
|
||||
} else if ( value.isMatrix3 === true ) {
|
||||
|
||||
return 'mat3';
|
||||
|
||||
} else if ( value.isMatrix4 === true ) {
|
||||
|
||||
return 'mat4';
|
||||
|
||||
} else if ( value.isColor === true ) {
|
||||
|
||||
return 'color';
|
||||
|
||||
} else if ( value instanceof ArrayBuffer ) {
|
||||
|
||||
return 'ArrayBuffer';
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value/object for the given data type and parameters.
|
||||
*
|
||||
* @method
|
||||
* @param {string} type - The given type.
|
||||
* @param {...any} params - A parameter list.
|
||||
* @return {any} The value/object.
|
||||
*/
|
||||
export function getValueFromType( type, ...params ) {
|
||||
|
||||
const last4 = type ? type.slice( - 4 ) : undefined;
|
||||
|
||||
if ( params.length === 1 ) { // ensure same behaviour as in NodeBuilder.format()
|
||||
|
||||
if ( last4 === 'vec2' ) params = [ params[ 0 ], params[ 0 ] ];
|
||||
else if ( last4 === 'vec3' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ] ];
|
||||
else if ( last4 === 'vec4' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ], params[ 0 ] ];
|
||||
|
||||
}
|
||||
|
||||
if ( type === 'color' ) {
|
||||
|
||||
return new Color( ...params );
|
||||
|
||||
} else if ( last4 === 'vec2' ) {
|
||||
|
||||
return new Vector2( ...params );
|
||||
|
||||
} else if ( last4 === 'vec3' ) {
|
||||
|
||||
return new Vector3( ...params );
|
||||
|
||||
} else if ( last4 === 'vec4' ) {
|
||||
|
||||
return new Vector4( ...params );
|
||||
|
||||
} else if ( last4 === 'mat2' ) {
|
||||
|
||||
return new Matrix2( ...params );
|
||||
|
||||
} else if ( last4 === 'mat3' ) {
|
||||
|
||||
return new Matrix3( ...params );
|
||||
|
||||
} else if ( last4 === 'mat4' ) {
|
||||
|
||||
return new Matrix4( ...params );
|
||||
|
||||
} else if ( type === 'bool' ) {
|
||||
|
||||
return params[ 0 ] || false;
|
||||
|
||||
} else if ( ( type === 'float' ) || ( type === 'int' ) || ( type === 'uint' ) ) {
|
||||
|
||||
return params[ 0 ] || 0;
|
||||
|
||||
} else if ( type === 'string' ) {
|
||||
|
||||
return params[ 0 ] || '';
|
||||
|
||||
} else if ( type === 'ArrayBuffer' ) {
|
||||
|
||||
return base64ToArrayBuffer( params[ 0 ] );
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object data that can be shared between different rendering steps.
|
||||
*
|
||||
* @param {Object} object - The object to get the data for.
|
||||
* @return {Object} The object data.
|
||||
*/
|
||||
export function getDataFromObject( object ) {
|
||||
|
||||
let data = dataFromObject.get( object );
|
||||
|
||||
if ( data === undefined ) {
|
||||
|
||||
data = {};
|
||||
dataFromObject.set( object, data );
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given array buffer to a Base64 string.
|
||||
*
|
||||
* @method
|
||||
* @param {ArrayBuffer} arrayBuffer - The array buffer.
|
||||
* @return {string} The Base64 string.
|
||||
*/
|
||||
export function arrayBufferToBase64( arrayBuffer ) {
|
||||
|
||||
let chars = '';
|
||||
|
||||
const array = new Uint8Array( arrayBuffer );
|
||||
|
||||
for ( let i = 0; i < array.length; i ++ ) {
|
||||
|
||||
chars += String.fromCharCode( array[ i ] );
|
||||
|
||||
}
|
||||
|
||||
return btoa( chars );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given Base64 string to an array buffer.
|
||||
*
|
||||
* @method
|
||||
* @param {string} base64 - The Base64 string.
|
||||
* @return {ArrayBuffer} The array buffer.
|
||||
*/
|
||||
export function base64ToArrayBuffer( base64 ) {
|
||||
|
||||
return Uint8Array.from( atob( base64 ), c => c.charCodeAt( 0 ) ).buffer;
|
||||
|
||||
}
|
||||
60
app/node_modules/three/src/nodes/core/NodeVar.js
generated
vendored
Normal file
60
app/node_modules/three/src/nodes/core/NodeVar.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* {@link NodeBuilder} is going to create instances of this class during the build process
|
||||
* of nodes. They represent the final shader variables that are going to be generated
|
||||
* by the builder. A dictionary of node variables is maintained in {@link NodeBuilder#vars} for
|
||||
* this purpose.
|
||||
*/
|
||||
class NodeVar {
|
||||
|
||||
/**
|
||||
* Constructs a new node variable.
|
||||
*
|
||||
* @param {string} name - The name of the variable.
|
||||
* @param {string} type - The type of the variable.
|
||||
* @param {boolean} [readOnly=false] - The read-only flag.
|
||||
* @param {?number} [count=null] - The size.
|
||||
*/
|
||||
constructor( name, type, readOnly = false, count = null ) {
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isNodeVar = true;
|
||||
|
||||
/**
|
||||
* The name of the variable.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The type of the variable.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* The read-only flag.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.readOnly = readOnly;
|
||||
|
||||
/**
|
||||
* The size.
|
||||
*
|
||||
* @type {?number}
|
||||
*/
|
||||
this.count = count;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeVar;
|
||||
63
app/node_modules/three/src/nodes/core/NodeVarying.js
generated
vendored
Normal file
63
app/node_modules/three/src/nodes/core/NodeVarying.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import NodeVar from './NodeVar.js';
|
||||
|
||||
/**
|
||||
* {@link NodeBuilder} is going to create instances of this class during the build process
|
||||
* of nodes. They represent the final shader varyings that are going to be generated
|
||||
* by the builder. An array of node varyings is maintained in {@link NodeBuilder#varyings} for
|
||||
* this purpose.
|
||||
*
|
||||
* @augments NodeVar
|
||||
*/
|
||||
class NodeVarying extends NodeVar {
|
||||
|
||||
/**
|
||||
* Constructs a new node varying.
|
||||
*
|
||||
* @param {string} name - The name of the varying.
|
||||
* @param {string} type - The type of the varying.
|
||||
* @param {?string} interpolationType - The interpolation type of the varying.
|
||||
* @param {?string} interpolationSampling - The interpolation sampling type of the varying.
|
||||
*/
|
||||
constructor( name, type, interpolationType = null, interpolationSampling = null ) {
|
||||
|
||||
super( name, type );
|
||||
|
||||
/**
|
||||
* Whether this varying requires interpolation or not. This property can be used
|
||||
* to check if the varying can be optimized for a variable.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.needsInterpolation = false;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isNodeVarying = true;
|
||||
|
||||
/**
|
||||
* The interpolation type of the varying data.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.interpolationType = interpolationType;
|
||||
|
||||
/**
|
||||
* The interpolation sampling type of varying data.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.interpolationSampling = interpolationSampling;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeVarying;
|
||||
103
app/node_modules/three/src/nodes/core/OutputStructNode.js
generated
vendored
Normal file
103
app/node_modules/three/src/nodes/core/OutputStructNode.js
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
import Node from './Node.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* This node can be used to define multiple outputs in a shader programs.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class OutputStructNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'OutputStructNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new output struct node. The constructor can be invoked with an
|
||||
* arbitrary number of nodes representing the members.
|
||||
*
|
||||
* @param {...Node} members - A parameter list of nodes.
|
||||
*/
|
||||
constructor( ...members ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* An array of nodes which defines the output.
|
||||
*
|
||||
* @type {Array<Node>}
|
||||
*/
|
||||
this.members = members;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isOutputStructNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
const properties = builder.getNodeProperties( this );
|
||||
|
||||
if ( properties.membersLayout === undefined ) {
|
||||
|
||||
const members = this.members;
|
||||
const membersLayout = [];
|
||||
|
||||
for ( let i = 0; i < members.length; i ++ ) {
|
||||
|
||||
const name = 'm' + i;
|
||||
const type = members[ i ].getNodeType( builder );
|
||||
|
||||
membersLayout.push( { name, type, index: i } );
|
||||
|
||||
}
|
||||
|
||||
properties.membersLayout = membersLayout;
|
||||
properties.structType = builder.getOutputStructTypeFromNode( this, properties.membersLayout );
|
||||
|
||||
}
|
||||
|
||||
return properties.structType.name;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const propertyName = builder.getOutputStructName();
|
||||
const members = this.members;
|
||||
|
||||
const structPrefix = propertyName !== '' ? propertyName + '.' : '';
|
||||
|
||||
for ( let i = 0; i < members.length; i ++ ) {
|
||||
|
||||
const snippet = members[ i ].build( builder );
|
||||
|
||||
builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }`, this );
|
||||
|
||||
}
|
||||
|
||||
return propertyName;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default OutputStructNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating an output struct node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {...Node} members - A parameter list of nodes.
|
||||
* @returns {OutputStructNode}
|
||||
*/
|
||||
export const outputStruct = /*@__PURE__*/ nodeProxy( OutputStructNode );
|
||||
63
app/node_modules/three/src/nodes/core/ParameterNode.js
generated
vendored
Normal file
63
app/node_modules/three/src/nodes/core/ParameterNode.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
import PropertyNode from './PropertyNode.js';
|
||||
|
||||
/**
|
||||
* Special version of {@link PropertyNode} which is used for parameters.
|
||||
*
|
||||
* @augments PropertyNode
|
||||
*/
|
||||
class ParameterNode extends PropertyNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ParameterNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new parameter node.
|
||||
*
|
||||
* @param {string} nodeType - The type of the node.
|
||||
* @param {?string} [name=null] - The name of the parameter in the shader.
|
||||
*/
|
||||
constructor( nodeType, name = null ) {
|
||||
|
||||
super( nodeType, name );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isParameterNode = true;
|
||||
|
||||
}
|
||||
|
||||
getHash() {
|
||||
|
||||
return this.uuid;
|
||||
|
||||
}
|
||||
|
||||
generate() {
|
||||
|
||||
return this.name;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ParameterNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a parameter node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} type - The type of the node.
|
||||
* @param {?string} name - The name of the parameter in the shader.
|
||||
* @returns {ParameterNode}
|
||||
*/
|
||||
export const parameter = ( type, name ) => nodeObject( new ParameterNode( type, name ) );
|
||||
344
app/node_modules/three/src/nodes/core/PropertyNode.js
generated
vendored
Normal file
344
app/node_modules/three/src/nodes/core/PropertyNode.js
generated
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
import Node from './Node.js';
|
||||
import { nodeImmutable, nodeObject } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* This class represents a shader property. It can be used
|
||||
* to explicitly define a property and assign a value to it.
|
||||
*
|
||||
* ```js
|
||||
* const threshold = property( 'float', 'threshold' ).assign( THRESHOLD );
|
||||
*```
|
||||
* `PropertyNode` is used by the engine to predefined common material properties
|
||||
* for TSL code.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class PropertyNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PropertyNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new property node.
|
||||
*
|
||||
* @param {string} nodeType - The type of the node.
|
||||
* @param {?string} [name=null] - The name of the property in the shader.
|
||||
* @param {boolean} [varying=false] - Whether this property is a varying or not.
|
||||
*/
|
||||
constructor( nodeType, name = null, varying = false ) {
|
||||
|
||||
super( nodeType );
|
||||
|
||||
/**
|
||||
* The name of the property in the shader. If no name is defined,
|
||||
* the node system auto-generates one.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* Whether this property is a varying or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.varying = varying;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isPropertyNode = true;
|
||||
|
||||
/**
|
||||
* This flag is used for global cache.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
}
|
||||
|
||||
getHash( builder ) {
|
||||
|
||||
return this.name || super.getHash( builder );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
let nodeVar;
|
||||
|
||||
if ( this.varying === true ) {
|
||||
|
||||
nodeVar = builder.getVaryingFromNode( this, this.name );
|
||||
nodeVar.needsInterpolation = true;
|
||||
|
||||
} else {
|
||||
|
||||
nodeVar = builder.getVarFromNode( this, this.name );
|
||||
|
||||
}
|
||||
|
||||
return builder.getPropertyName( nodeVar );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PropertyNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a property node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} type - The type of the node.
|
||||
* @param {?string} [name=null] - The name of the property in the shader.
|
||||
* @returns {PropertyNode}
|
||||
*/
|
||||
export const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) );
|
||||
|
||||
/**
|
||||
* TSL function for creating a varying property node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} type - The type of the node.
|
||||
* @param {?string} [name=null] - The name of the varying in the shader.
|
||||
* @returns {PropertyNode}
|
||||
*/
|
||||
export const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `DiffuseColor`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<vec4>}
|
||||
*/
|
||||
export const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `EmissiveColor`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<vec3>}
|
||||
*/
|
||||
export const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Roughness`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Metalness`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Clearcoat`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `ClearcoatRoughness`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Sheen`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<vec3>}
|
||||
*/
|
||||
export const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `SheenRoughness`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Iridescence`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `IridescenceIOR`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `IridescenceThickness`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `AlphaT`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Anisotropy`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `AnisotropyT`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<vec3>}
|
||||
*/
|
||||
export const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `AnisotropyB`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<vec3>}
|
||||
*/
|
||||
export const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `SpecularColor`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<color>}
|
||||
*/
|
||||
export const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `SpecularF90`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Shininess`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Output`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<vec4>}
|
||||
*/
|
||||
export const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `dashSize`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `gapSize`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `pointWidth`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `IOR`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Transmission`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Thickness`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `AttenuationDistance`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `AttenuationColor`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<color>}
|
||||
*/
|
||||
export const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' );
|
||||
|
||||
/**
|
||||
* TSL object that represents the shader variable `Dispersion`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {PropertyNode<float>}
|
||||
*/
|
||||
export const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' );
|
||||
308
app/node_modules/three/src/nodes/core/StackNode.js
generated
vendored
Normal file
308
app/node_modules/three/src/nodes/core/StackNode.js
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
import Node from './Node.js';
|
||||
import { select } from '../math/ConditionalNode.js';
|
||||
import { ShaderNode, nodeProxy, getCurrentStack, setCurrentStack, nodeObject } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* Stack is a helper for Nodes that need to produce stack-based code instead of continuous flow.
|
||||
* They are usually needed in cases like `If`, `Else`.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class StackNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'StackNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new stack node.
|
||||
*
|
||||
* @param {?StackNode} [parent=null] - The parent stack node.
|
||||
*/
|
||||
constructor( parent = null ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* List of nodes.
|
||||
*
|
||||
* @type {Array<Node>}
|
||||
*/
|
||||
this.nodes = [];
|
||||
|
||||
/**
|
||||
* The output node.
|
||||
*
|
||||
* @type {?Node}
|
||||
* @default null
|
||||
*/
|
||||
this.outputNode = null;
|
||||
|
||||
/**
|
||||
* The parent stack node.
|
||||
*
|
||||
* @type {?StackNode}
|
||||
* @default null
|
||||
*/
|
||||
this.parent = parent;
|
||||
|
||||
/**
|
||||
* The current conditional node.
|
||||
*
|
||||
* @private
|
||||
* @type {ConditionalNode}
|
||||
* @default null
|
||||
*/
|
||||
this._currentCond = null;
|
||||
|
||||
/**
|
||||
* The expression node. Only
|
||||
* relevant for Switch/Case.
|
||||
*
|
||||
* @private
|
||||
* @type {Node}
|
||||
* @default null
|
||||
*/
|
||||
this._expressionNode = null;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isStackNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.outputNode ? this.outputNode.getNodeType( builder ) : 'void';
|
||||
|
||||
}
|
||||
|
||||
getMemberType( builder, name ) {
|
||||
|
||||
return this.outputNode ? this.outputNode.getMemberType( builder, name ) : 'void';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a node to this stack.
|
||||
*
|
||||
* @param {Node} node - The node to add.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
add( node ) {
|
||||
|
||||
this.nodes.push( node );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent an `if` statement in TSL.
|
||||
*
|
||||
* @param {Node} boolNode - Represents the condition.
|
||||
* @param {Function} method - TSL code which is executed if the condition evaluates to `true`.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
If( boolNode, method ) {
|
||||
|
||||
const methodNode = new ShaderNode( method );
|
||||
this._currentCond = select( boolNode, methodNode );
|
||||
|
||||
return this.add( this._currentCond );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent an `elseif` statement in TSL.
|
||||
*
|
||||
* @param {Node} boolNode - Represents the condition.
|
||||
* @param {Function} method - TSL code which is executed if the condition evaluates to `true`.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
ElseIf( boolNode, method ) {
|
||||
|
||||
const methodNode = new ShaderNode( method );
|
||||
const ifNode = select( boolNode, methodNode );
|
||||
|
||||
this._currentCond.elseNode = ifNode;
|
||||
this._currentCond = ifNode;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent an `else` statement in TSL.
|
||||
*
|
||||
* @param {Function} method - TSL code which is executed in the `else` case.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
Else( method ) {
|
||||
|
||||
this._currentCond.elseNode = new ShaderNode( method );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a `switch` statement in TSL.
|
||||
*
|
||||
* @param {any} expression - Represents the expression.
|
||||
* @param {Function} method - TSL code which is executed if the condition evaluates to `true`.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
Switch( expression ) {
|
||||
|
||||
this._expressionNode = nodeObject( expression );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a `case` statement in TSL. The TSL version accepts an arbitrary numbers of values.
|
||||
* The last parameter must be the callback method that should be executed in the `true` case.
|
||||
*
|
||||
* @param {...any} params - The values of the `Case()` statement as well as the callback method.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
Case( ...params ) {
|
||||
|
||||
const caseNodes = [];
|
||||
|
||||
// extract case nodes from the parameter list
|
||||
|
||||
if ( params.length >= 2 ) {
|
||||
|
||||
for ( let i = 0; i < params.length - 1; i ++ ) {
|
||||
|
||||
caseNodes.push( this._expressionNode.equal( nodeObject( params[ i ] ) ) );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
throw new Error( 'TSL: Invalid parameter length. Case() requires at least two parameters.' );
|
||||
|
||||
}
|
||||
|
||||
// extract method
|
||||
|
||||
const method = params[ params.length - 1 ];
|
||||
const methodNode = new ShaderNode( method );
|
||||
|
||||
// chain multiple cases when using Case( 1, 2, 3, () => {} )
|
||||
|
||||
let caseNode = caseNodes[ 0 ];
|
||||
|
||||
for ( let i = 1; i < caseNodes.length; i ++ ) {
|
||||
|
||||
caseNode = caseNode.or( caseNodes[ i ] );
|
||||
|
||||
}
|
||||
|
||||
// build condition
|
||||
|
||||
const condNode = select( caseNode, methodNode );
|
||||
|
||||
if ( this._currentCond === null ) {
|
||||
|
||||
this._currentCond = condNode;
|
||||
|
||||
return this.add( this._currentCond );
|
||||
|
||||
} else {
|
||||
|
||||
this._currentCond.elseNode = condNode;
|
||||
this._currentCond = condNode;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the default code block of a Switch/Case statement.
|
||||
*
|
||||
* @param {Function} method - TSL code which is executed in the `else` case.
|
||||
* @return {StackNode} A reference to this stack node.
|
||||
*/
|
||||
Default( method ) {
|
||||
|
||||
this.Else( method );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
build( builder, ...params ) {
|
||||
|
||||
const previousBuildStack = builder.currentStack;
|
||||
const previousStack = getCurrentStack();
|
||||
|
||||
setCurrentStack( this );
|
||||
|
||||
builder.currentStack = this;
|
||||
|
||||
const buildStage = builder.buildStage;
|
||||
|
||||
for ( const node of this.nodes ) {
|
||||
|
||||
if ( buildStage === 'setup' ) {
|
||||
|
||||
node.build( builder );
|
||||
|
||||
} else if ( buildStage === 'analyze' ) {
|
||||
|
||||
node.build( builder, this );
|
||||
|
||||
} else if ( buildStage === 'generate' ) {
|
||||
|
||||
const stages = builder.getDataFromNode( node, 'any' ).stages;
|
||||
const parents = stages && stages[ builder.shaderStage ];
|
||||
|
||||
if ( node.isVarNode && parents && parents.length === 1 && parents[ 0 ] && parents[ 0 ].isStackNode ) {
|
||||
|
||||
continue; // skip var nodes that are only used in .toVarying()
|
||||
|
||||
}
|
||||
|
||||
node.build( builder, 'void' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const result = this.outputNode ? this.outputNode.build( builder, ...params ) : super.build( builder, ...params );
|
||||
|
||||
setCurrentStack( previousStack );
|
||||
|
||||
builder.currentStack = previousBuildStack;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default StackNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a stack node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {?StackNode} [parent=null] - The parent stack node.
|
||||
* @returns {StackNode}
|
||||
*/
|
||||
export const stack = /*@__PURE__*/ nodeProxy( StackNode ).setParameterLength( 0, 1 );
|
||||
120
app/node_modules/three/src/nodes/core/StructNode.js
generated
vendored
Normal file
120
app/node_modules/three/src/nodes/core/StructNode.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
import Node from './Node.js';
|
||||
import StructTypeNode from './StructTypeNode.js';
|
||||
import { nodeObject } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* StructNode allows to create custom structures with multiple members.
|
||||
* This can also be used to define structures in attribute and uniform data.
|
||||
*
|
||||
* ```js
|
||||
* // Define a custom struct
|
||||
* const BoundingBox = struct( { min: 'vec3', max: 'vec3' } );
|
||||
*
|
||||
* // Create a new instance of the struct
|
||||
* const bb = BoundingBox( vec3( 0 ), vec3( 1 ) ); // style 1
|
||||
* const bb = BoundingBox( { min: vec3( 0 ), max: vec3( 1 ) } ); // style 2
|
||||
*
|
||||
* // Access the struct members
|
||||
* const min = bb.get( 'min' );
|
||||
*
|
||||
* // Assign a new value to a member
|
||||
* min.assign( vec3() );
|
||||
* ```
|
||||
* @augments Node
|
||||
*/
|
||||
class StructNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'StructNode';
|
||||
|
||||
}
|
||||
|
||||
constructor( structLayoutNode, values ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
this.structLayoutNode = structLayoutNode;
|
||||
this.values = values;
|
||||
|
||||
this.isStructNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.structLayoutNode.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
getMemberType( builder, name ) {
|
||||
|
||||
return this.structLayoutNode.getMemberType( builder, name );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const nodeVar = builder.getVarFromNode( this );
|
||||
const structType = nodeVar.type;
|
||||
const propertyName = builder.getPropertyName( nodeVar );
|
||||
|
||||
builder.addLineFlowCode( `${ propertyName } = ${ builder.generateStruct( structType, this.structLayoutNode.membersLayout, this.values ) }`, this );
|
||||
|
||||
return nodeVar.name;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default StructNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a struct node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Object} membersLayout - The layout of the struct members.
|
||||
* @param {?string} [name=null] - The name of the struct.
|
||||
* @returns {Function} The struct function.
|
||||
*/
|
||||
export const struct = ( membersLayout, name = null ) => {
|
||||
|
||||
const structLayout = new StructTypeNode( membersLayout, name );
|
||||
|
||||
const struct = ( ...params ) => {
|
||||
|
||||
let values = null;
|
||||
|
||||
if ( params.length > 0 ) {
|
||||
|
||||
if ( params[ 0 ].isNode ) {
|
||||
|
||||
values = {};
|
||||
|
||||
const names = Object.keys( membersLayout );
|
||||
|
||||
for ( let i = 0; i < params.length; i ++ ) {
|
||||
|
||||
values[ names[ i ] ] = params[ i ];
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
values = params[ 0 ];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nodeObject( new StructNode( structLayout, values ) );
|
||||
|
||||
};
|
||||
|
||||
struct.layout = structLayout;
|
||||
struct.isStruct = true;
|
||||
|
||||
return struct;
|
||||
|
||||
};
|
||||
13
app/node_modules/three/src/nodes/core/StructType.js
generated
vendored
Normal file
13
app/node_modules/three/src/nodes/core/StructType.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
class StructType {
|
||||
|
||||
constructor( name, members ) {
|
||||
|
||||
this.name = name;
|
||||
this.members = members;
|
||||
this.output = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default StructType;
|
||||
153
app/node_modules/three/src/nodes/core/StructTypeNode.js
generated
vendored
Normal file
153
app/node_modules/three/src/nodes/core/StructTypeNode.js
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
import Node from './Node.js';
|
||||
import { getByteBoundaryFromType, getMemoryLengthFromType } from './NodeUtils.js';
|
||||
|
||||
/**
|
||||
* Generates a layout for struct members.
|
||||
* This function takes an object representing struct members and returns an array of member layouts.
|
||||
* Each member layout includes the member's name, type, and whether it is atomic.
|
||||
*
|
||||
* @param {Object.<string, string|Object>} members - An object where keys are member names and values are either types (as strings) or objects with type and atomic properties.
|
||||
* @returns {Array.<{name: string, type: string, atomic: boolean}>} An array of member layouts.
|
||||
*/
|
||||
function getMembersLayout( members ) {
|
||||
|
||||
return Object.entries( members ).map( ( [ name, value ] ) => {
|
||||
|
||||
if ( typeof value === 'string' ) {
|
||||
|
||||
return { name, type: value, atomic: false };
|
||||
|
||||
}
|
||||
|
||||
return { name, type: value.type, atomic: value.atomic || false };
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a struct type node in the node-based system.
|
||||
* This class is used to define and manage the layout and types of struct members.
|
||||
* It extends the base Node class and provides methods to get the length of the struct,
|
||||
* retrieve member types, and generate the struct type for a builder.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class StructTypeNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'StructTypeNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of StructTypeNode.
|
||||
*
|
||||
* @param {Object} membersLayout - The layout of the members for the struct.
|
||||
* @param {?string} [name=null] - The optional name of the struct.
|
||||
*/
|
||||
constructor( membersLayout, name = null ) {
|
||||
|
||||
super( 'struct' );
|
||||
|
||||
/**
|
||||
* The layout of the members for the struct
|
||||
*
|
||||
* @type {Array.<{name: string, type: string, atomic: boolean}>}
|
||||
*/
|
||||
this.membersLayout = getMembersLayout( membersLayout );
|
||||
|
||||
/**
|
||||
* The name of the struct.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isStructLayoutNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the struct.
|
||||
* The length is calculated by summing the lengths of the struct's members.
|
||||
*
|
||||
* @returns {number} The length of the struct.
|
||||
*/
|
||||
getLength() {
|
||||
|
||||
const GPU_CHUNK_BYTES = 8;
|
||||
const BYTES_PER_ELEMENT = Float32Array.BYTES_PER_ELEMENT;
|
||||
|
||||
let offset = 0; // global buffer offset in bytes
|
||||
|
||||
for ( const member of this.membersLayout ) {
|
||||
|
||||
const type = member.type;
|
||||
|
||||
const itemSize = getMemoryLengthFromType( type ) * BYTES_PER_ELEMENT;
|
||||
const boundary = getByteBoundaryFromType( type );
|
||||
|
||||
const chunkOffset = offset % GPU_CHUNK_BYTES; // offset in the current chunk
|
||||
const chunkPadding = chunkOffset % boundary; // required padding to match boundary
|
||||
const chunkStart = chunkOffset + chunkPadding; // start position in the current chunk for the data
|
||||
|
||||
offset += chunkPadding;
|
||||
|
||||
// Check for chunk overflow
|
||||
if ( chunkStart !== 0 && ( GPU_CHUNK_BYTES - chunkStart ) < itemSize ) {
|
||||
|
||||
// Add padding to the end of the chunk
|
||||
offset += ( GPU_CHUNK_BYTES - chunkStart );
|
||||
|
||||
}
|
||||
|
||||
offset += itemSize;
|
||||
|
||||
}
|
||||
|
||||
return ( Math.ceil( offset / GPU_CHUNK_BYTES ) * GPU_CHUNK_BYTES ) / BYTES_PER_ELEMENT;
|
||||
|
||||
}
|
||||
|
||||
getMemberType( builder, name ) {
|
||||
|
||||
const member = this.membersLayout.find( m => m.name === name );
|
||||
|
||||
return member ? member.type : 'void';
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
const structType = builder.getStructTypeFromNode( this, this.membersLayout, this.name );
|
||||
|
||||
return structType.name;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
builder.addInclude( this );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
return this.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default StructTypeNode;
|
||||
89
app/node_modules/three/src/nodes/core/SubBuildNode.js
generated
vendored
Normal file
89
app/node_modules/three/src/nodes/core/SubBuildNode.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import Node from './Node.js';
|
||||
import { nodeObject } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* This node is used to build a sub-build in the node system.
|
||||
*
|
||||
* @augments Node
|
||||
* @param {Node} node - The node to be built in the sub-build.
|
||||
* @param {string} name - The name of the sub-build.
|
||||
* @param {string|null} [nodeType=null] - The type of the node, if known.
|
||||
*/
|
||||
class SubBuildNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'SubBuild';
|
||||
|
||||
}
|
||||
|
||||
constructor( node, name, nodeType = null ) {
|
||||
|
||||
super( nodeType );
|
||||
|
||||
/**
|
||||
* The node to be built in the sub-build.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* The name of the sub-build.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isSubBuildNode = true;
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
if ( this.nodeType !== null ) return this.nodeType;
|
||||
|
||||
builder.addSubBuild( this.name );
|
||||
|
||||
const nodeType = this.node.getNodeType( builder );
|
||||
|
||||
builder.removeSubBuild();
|
||||
|
||||
return nodeType;
|
||||
|
||||
}
|
||||
|
||||
build( builder, ...params ) {
|
||||
|
||||
builder.addSubBuild( this.name );
|
||||
|
||||
const data = this.node.build( builder, ...params );
|
||||
|
||||
builder.removeSubBuild();
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SubBuildNode;
|
||||
|
||||
/**
|
||||
* Creates a new sub-build node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node to be built in the sub-build.
|
||||
* @param {string} name - The name of the sub-build.
|
||||
* @param {string|null} [type=null] - The type of the node, if known.
|
||||
* @returns {Node} A node object wrapping the SubBuildNode instance.
|
||||
*/
|
||||
export const subBuild = ( node, name, type = null ) => nodeObject( new SubBuildNode( nodeObject( node ), name, type ) );
|
||||
88
app/node_modules/three/src/nodes/core/TempNode.js
generated
vendored
Normal file
88
app/node_modules/three/src/nodes/core/TempNode.js
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
import Node from './Node.js';
|
||||
|
||||
/**
|
||||
* This module uses cache management to create temporary variables
|
||||
* if the node is used more than once to prevent duplicate calculations.
|
||||
*
|
||||
* The class acts as a base class for many other nodes types.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class TempNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'TempNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a temp node.
|
||||
*
|
||||
* @param {?string} nodeType - The node type.
|
||||
*/
|
||||
constructor( nodeType = null ) {
|
||||
|
||||
super( nodeType );
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isTempNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this node is used more than once in context of other nodes.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The node builder.
|
||||
* @return {boolean} A flag that indicates if there is more than one dependency to other nodes.
|
||||
*/
|
||||
hasDependencies( builder ) {
|
||||
|
||||
return builder.getDataFromNode( this ).usageCount > 1;
|
||||
|
||||
}
|
||||
|
||||
build( builder, output ) {
|
||||
|
||||
const buildStage = builder.getBuildStage();
|
||||
|
||||
if ( buildStage === 'generate' ) {
|
||||
|
||||
const type = builder.getVectorType( this.getNodeType( builder, output ) );
|
||||
const nodeData = builder.getDataFromNode( this );
|
||||
|
||||
if ( nodeData.propertyName !== undefined ) {
|
||||
|
||||
return builder.format( nodeData.propertyName, type, output );
|
||||
|
||||
} else if ( type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) {
|
||||
|
||||
const snippet = super.build( builder, type );
|
||||
|
||||
const nodeVar = builder.getVarFromNode( this, null, type );
|
||||
const propertyName = builder.getPropertyName( nodeVar );
|
||||
|
||||
builder.addLineFlowCode( `${ propertyName } = ${ snippet }`, this );
|
||||
|
||||
nodeData.snippet = snippet;
|
||||
nodeData.propertyName = propertyName;
|
||||
|
||||
return builder.format( nodeData.propertyName, type, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return super.build( builder, output );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TempNode;
|
||||
137
app/node_modules/three/src/nodes/core/UniformGroupNode.js
generated
vendored
Normal file
137
app/node_modules/three/src/nodes/core/UniformGroupNode.js
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
import Node from './Node.js';
|
||||
|
||||
/**
|
||||
* This node can be used to group single instances of {@link UniformNode}
|
||||
* and manage them as a uniform buffer.
|
||||
*
|
||||
* In most cases, the predefined nodes `objectGroup`, `renderGroup` and `frameGroup`
|
||||
* will be used when defining the {@link UniformNode#groupNode} property.
|
||||
*
|
||||
* - `objectGroup`: Uniform buffer per object.
|
||||
* - `renderGroup`: Shared uniform buffer, updated once per render call.
|
||||
* - `frameGroup`: Shared uniform buffer, updated once per frame.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class UniformGroupNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'UniformGroupNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new uniform group node.
|
||||
*
|
||||
* @param {string} name - The name of the uniform group node.
|
||||
* @param {boolean} [shared=false] - Whether this uniform group node is shared or not.
|
||||
* @param {number} [order=1] - Influences the internal sorting.
|
||||
*/
|
||||
constructor( name, shared = false, order = 1 ) {
|
||||
|
||||
super( 'string' );
|
||||
|
||||
/**
|
||||
* The name of the uniform group node.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* Whether this uniform group node is shared or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.shared = shared;
|
||||
|
||||
/**
|
||||
* Influences the internal sorting.
|
||||
* TODO: Add details when this property should be changed.
|
||||
*
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this.order = order;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isUniformGroup = true;
|
||||
|
||||
}
|
||||
|
||||
serialize( data ) {
|
||||
|
||||
super.serialize( data );
|
||||
|
||||
data.name = this.name;
|
||||
data.version = this.version;
|
||||
data.shared = this.shared;
|
||||
|
||||
}
|
||||
|
||||
deserialize( data ) {
|
||||
|
||||
super.deserialize( data );
|
||||
|
||||
this.name = data.name;
|
||||
this.version = data.version;
|
||||
this.shared = data.shared;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default UniformGroupNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a uniform group node with the given name.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the uniform group node.
|
||||
* @returns {UniformGroupNode}
|
||||
*/
|
||||
export const uniformGroup = ( name ) => new UniformGroupNode( name );
|
||||
|
||||
/**
|
||||
* TSL function for creating a shared uniform group node with the given name and order.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {string} name - The name of the uniform group node.
|
||||
* @param {number} [order=0] - Influences the internal sorting.
|
||||
* @returns {UniformGroupNode}
|
||||
*/
|
||||
export const sharedUniformGroup = ( name, order = 0 ) => new UniformGroupNode( name, true, order );
|
||||
|
||||
/**
|
||||
* TSL object that represents a shared uniform group node which is updated once per frame.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformGroupNode}
|
||||
*/
|
||||
export const frameGroup = /*@__PURE__*/ sharedUniformGroup( 'frame' );
|
||||
|
||||
/**
|
||||
* TSL object that represents a shared uniform group node which is updated once per render.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformGroupNode}
|
||||
*/
|
||||
export const renderGroup = /*@__PURE__*/ sharedUniformGroup( 'render' );
|
||||
|
||||
/**
|
||||
* TSL object that represents a uniform group node which is updated once per object.
|
||||
*
|
||||
* @tsl
|
||||
* @type {UniformGroupNode}
|
||||
*/
|
||||
export const objectGroup = /*@__PURE__*/ uniformGroup( 'object' );
|
||||
177
app/node_modules/three/src/nodes/core/UniformNode.js
generated
vendored
Normal file
177
app/node_modules/three/src/nodes/core/UniformNode.js
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
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 ) );
|
||||
|
||||
};
|
||||
216
app/node_modules/three/src/nodes/core/VarNode.js
generated
vendored
Normal file
216
app/node_modules/three/src/nodes/core/VarNode.js
generated
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
import Node from './Node.js';
|
||||
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* Class for representing shader variables as nodes. Variables are created from
|
||||
* existing nodes like the following:
|
||||
*
|
||||
* ```js
|
||||
* const depth = sampleDepth( uvNode ).toVar( 'depth' );
|
||||
* ```
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class VarNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'VarNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new variable node.
|
||||
*
|
||||
* @param {Node} node - The node for which a variable should be created.
|
||||
* @param {?string} [name=null] - The name of the variable in the shader.
|
||||
* @param {boolean} [readOnly=false] - The read-only flag.
|
||||
*/
|
||||
constructor( node, name = null, readOnly = false ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The node for which a variable should be created.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* The name of the variable in the shader. If no name is defined,
|
||||
* the node system auto-generates one.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* `VarNode` sets this property to `true` by default.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isVarNode = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* The read-only flag.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.readOnly = readOnly;
|
||||
|
||||
/**
|
||||
*
|
||||
* Add this flag to the node system to indicate that this node require parents.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.parents = true;
|
||||
|
||||
}
|
||||
|
||||
getMemberType( builder, name ) {
|
||||
|
||||
return this.node.getMemberType( builder, name );
|
||||
|
||||
}
|
||||
|
||||
getElementType( builder ) {
|
||||
|
||||
return this.node.getElementType( builder );
|
||||
|
||||
}
|
||||
|
||||
getNodeType( builder ) {
|
||||
|
||||
return this.node.getNodeType( builder );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const { node, name, readOnly } = this;
|
||||
const { renderer } = builder;
|
||||
|
||||
const isWebGPUBackend = renderer.backend.isWebGPUBackend === true;
|
||||
|
||||
let isDeterministic = false;
|
||||
let shouldTreatAsReadOnly = false;
|
||||
|
||||
if ( readOnly ) {
|
||||
|
||||
isDeterministic = builder.isDeterministic( node );
|
||||
|
||||
shouldTreatAsReadOnly = isWebGPUBackend ? readOnly : isDeterministic;
|
||||
|
||||
}
|
||||
|
||||
const vectorType = builder.getVectorType( this.getNodeType( builder ) );
|
||||
const snippet = node.build( builder, vectorType );
|
||||
|
||||
const nodeVar = builder.getVarFromNode( this, name, vectorType, undefined, shouldTreatAsReadOnly );
|
||||
|
||||
const propertyName = builder.getPropertyName( nodeVar );
|
||||
|
||||
let declarationPrefix = propertyName;
|
||||
|
||||
if ( shouldTreatAsReadOnly ) {
|
||||
|
||||
if ( isWebGPUBackend ) {
|
||||
|
||||
declarationPrefix = isDeterministic
|
||||
? `const ${ propertyName }`
|
||||
: `let ${ propertyName }`;
|
||||
|
||||
} else {
|
||||
|
||||
const count = builder.getArrayCount( node );
|
||||
|
||||
declarationPrefix = `const ${ builder.getVar( nodeVar.type, propertyName, count ) }`;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
builder.addLineFlowCode( `${ declarationPrefix } = ${ snippet }`, this );
|
||||
|
||||
return propertyName;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default VarNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a var node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node for which a variable should be created.
|
||||
* @param {?string} name - The name of the variable in the shader.
|
||||
* @returns {VarNode}
|
||||
*/
|
||||
const createVar = /*@__PURE__*/ nodeProxy( VarNode );
|
||||
|
||||
/**
|
||||
* TSL function for creating a var node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node for which a variable should be created.
|
||||
* @param {?string} name - The name of the variable in the shader.
|
||||
* @returns {VarNode}
|
||||
*/
|
||||
export const Var = ( node, name = null ) => createVar( node, name ).toStack();
|
||||
|
||||
/**
|
||||
* TSL function for creating a const node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - The node for which a constant should be created.
|
||||
* @param {?string} name - The name of the constant in the shader.
|
||||
* @returns {VarNode}
|
||||
*/
|
||||
export const Const = ( node, name = null ) => createVar( node, name, true ).toStack();
|
||||
|
||||
// Method chaining
|
||||
|
||||
addMethodChaining( 'toVar', Var );
|
||||
addMethodChaining( 'toConst', Const );
|
||||
|
||||
// Deprecated
|
||||
|
||||
/**
|
||||
* @tsl
|
||||
* @function
|
||||
* @deprecated since r170. Use `Var( node )` or `node.toVar()` instead.
|
||||
*
|
||||
* @param {any} node
|
||||
* @returns {VarNode}
|
||||
*/
|
||||
export const temp = ( node ) => { // @deprecated, r170
|
||||
|
||||
console.warn( 'TSL: "temp( node )" is deprecated. Use "Var( node )" or "node.toVar()" instead.' );
|
||||
|
||||
return createVar( node );
|
||||
|
||||
};
|
||||
|
||||
addMethodChaining( 'temp', temp );
|
||||
|
||||
226
app/node_modules/three/src/nodes/core/VaryingNode.js
generated
vendored
Normal file
226
app/node_modules/three/src/nodes/core/VaryingNode.js
generated
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
import Node from './Node.js';
|
||||
import { NodeShaderStage } from './constants.js';
|
||||
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
|
||||
import { subBuild } from './SubBuildNode.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 interpolation type of the varying data.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.interpolationType = null;
|
||||
|
||||
/**
|
||||
* The interpolation sampling type of varying data.
|
||||
*
|
||||
* @type {?string}
|
||||
* @default null
|
||||
*/
|
||||
this.interpolationSampling = null;
|
||||
|
||||
/**
|
||||
* This flag is used for global cache.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the interpolation type of the varying.
|
||||
*
|
||||
* @param {string} type - The interpolation type.
|
||||
* @param {?string} sampling - The interpolation sampling type
|
||||
* @return {VaryingNode} A reference to this node.
|
||||
*/
|
||||
setInterpolation( type, sampling = null ) {
|
||||
|
||||
this.interpolationType = type;
|
||||
this.interpolationSampling = sampling;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
const interpolationType = this.interpolationType;
|
||||
const interpolationSampling = this.interpolationSampling;
|
||||
|
||||
properties.varying = varying = builder.getVaryingFromNode( this, name, type, interpolationType, interpolationSampling );
|
||||
properties.node = subBuild( this.node, 'VERTEX' );
|
||||
|
||||
}
|
||||
|
||||
// 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 );
|
||||
|
||||
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
|
||||
|
||||
}
|
||||
|
||||
analyze( builder ) {
|
||||
|
||||
this.setupVarying( builder );
|
||||
|
||||
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node );
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
const propertyKey = builder.getSubBuildProperty( 'property', builder.currentStack );
|
||||
const properties = builder.getNodeProperties( this );
|
||||
const varying = this.setupVarying( builder );
|
||||
|
||||
if ( properties[ propertyKey ] === undefined ) {
|
||||
|
||||
const type = this.getNodeType( builder );
|
||||
const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX );
|
||||
|
||||
// force node run in vertex stage
|
||||
builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, properties.node, type, propertyName );
|
||||
|
||||
properties[ propertyKey ] = propertyName;
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
} );
|
||||
68
app/node_modules/three/src/nodes/core/constants.js
generated
vendored
Normal file
68
app/node_modules/three/src/nodes/core/constants.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Possible shader stages.
|
||||
*
|
||||
* @property {string} VERTEX The vertex shader stage.
|
||||
* @property {string} FRAGMENT The fragment shader stage.
|
||||
*/
|
||||
export const NodeShaderStage = {
|
||||
VERTEX: 'vertex',
|
||||
FRAGMENT: 'fragment'
|
||||
};
|
||||
|
||||
/**
|
||||
* Update types of a node.
|
||||
*
|
||||
* @property {string} NONE The update method is not executed.
|
||||
* @property {string} FRAME The update method is executed per frame.
|
||||
* @property {string} RENDER The update method is executed per render. A frame might be produced by multiple render calls so this value allows more detailed updates than FRAME.
|
||||
* @property {string} OBJECT The update method is executed per {@link Object3D} that uses the node for rendering.
|
||||
*/
|
||||
export const NodeUpdateType = {
|
||||
NONE: 'none',
|
||||
FRAME: 'frame',
|
||||
RENDER: 'render',
|
||||
OBJECT: 'object'
|
||||
};
|
||||
|
||||
/**
|
||||
* Data types of a node.
|
||||
*
|
||||
* @property {string} BOOLEAN Boolean type.
|
||||
* @property {string} INTEGER Integer type.
|
||||
* @property {string} FLOAT Float type.
|
||||
* @property {string} VECTOR2 Two-dimensional vector type.
|
||||
* @property {string} VECTOR3 Three-dimensional vector type.
|
||||
* @property {string} VECTOR4 Four-dimensional vector type.
|
||||
* @property {string} MATRIX2 2x2 matrix type.
|
||||
* @property {string} MATRIX3 3x3 matrix type.
|
||||
* @property {string} MATRIX4 4x4 matrix type.
|
||||
*/
|
||||
export const NodeType = {
|
||||
BOOLEAN: 'bool',
|
||||
INTEGER: 'int',
|
||||
FLOAT: 'float',
|
||||
VECTOR2: 'vec2',
|
||||
VECTOR3: 'vec3',
|
||||
VECTOR4: 'vec4',
|
||||
MATRIX2: 'mat2',
|
||||
MATRIX3: 'mat3',
|
||||
MATRIX4: 'mat4'
|
||||
};
|
||||
|
||||
/**
|
||||
* Access types of a node. These are relevant for compute and storage usage.
|
||||
*
|
||||
* @property {string} READ_ONLY Read-only access
|
||||
* @property {string} WRITE_ONLY Write-only access.
|
||||
* @property {string} READ_WRITE Read and write access.
|
||||
*/
|
||||
export const NodeAccess = {
|
||||
READ_ONLY: 'readOnly',
|
||||
WRITE_ONLY: 'writeOnly',
|
||||
READ_WRITE: 'readWrite',
|
||||
};
|
||||
|
||||
export const defaultShaderStages = [ 'fragment', 'vertex' ];
|
||||
export const defaultBuildStages = [ 'setup', 'analyze', 'generate' ];
|
||||
export const shaderStages = [ ...defaultShaderStages, 'compute' ];
|
||||
export const vectorComponents = [ 'x', 'y', 'z', 'w' ];
|
||||
234
app/node_modules/three/src/nodes/display/BlendModes.js
generated
vendored
Normal file
234
app/node_modules/three/src/nodes/display/BlendModes.js
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
import { Fn, If, vec4 } from '../tsl/TSLBase.js';
|
||||
import { mix, min, step } from '../math/MathNode.js';
|
||||
|
||||
/**
|
||||
* Represents a "Color Burn" blend mode.
|
||||
*
|
||||
* It's designed to darken the base layer's colors based on the color of the blend layer.
|
||||
* It significantly increases the contrast of the base layer, making the colors more vibrant and saturated.
|
||||
* The darker the color in the blend layer, the stronger the darkening and contrast effect on the base layer.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} base - The base color.
|
||||
* @param {Node<vec3>} blend - The blend color. A white (#ffffff) blend color does not alter the base color.
|
||||
* @return {Node<vec3>} The result.
|
||||
*/
|
||||
export const blendBurn = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
|
||||
|
||||
return min( 1.0, base.oneMinus().div( blend ) ).oneMinus();
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'blendBurn',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Represents a "Color Dodge" blend mode.
|
||||
*
|
||||
* It's designed to lighten the base layer's colors based on the color of the blend layer.
|
||||
* It significantly increases the brightness of the base layer, making the colors lighter and more vibrant.
|
||||
* The brighter the color in the blend layer, the stronger the lightening and contrast effect on the base layer.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} base - The base color.
|
||||
* @param {Node<vec3>} blend - The blend color. A black (#000000) blend color does not alter the base color.
|
||||
* @return {Node<vec3>} The result.
|
||||
*/
|
||||
export const blendDodge = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
|
||||
|
||||
return min( base.div( blend.oneMinus() ), 1.0 );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'blendDodge',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Represents a "Screen" blend mode.
|
||||
*
|
||||
* Similar to `blendDodge()`, this mode also lightens the base layer's colors based on the color of the blend layer.
|
||||
* The "Screen" blend mode is better for general brightening whereas the "Dodge" results in more subtle and nuanced
|
||||
* effects.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} base - The base color.
|
||||
* @param {Node<vec3>} blend - The blend color. A black (#000000) blend color does not alter the base color.
|
||||
* @return {Node<vec3>} The result.
|
||||
*/
|
||||
export const blendScreen = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
|
||||
|
||||
return base.oneMinus().mul( blend.oneMinus() ).oneMinus();
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'blendScreen',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Represents a "Overlay" blend mode.
|
||||
*
|
||||
* It's designed to increase the contrast of the base layer based on the color of the blend layer.
|
||||
* It amplifies the existing colors and contrast in the base layer, making lighter areas lighter and darker areas darker.
|
||||
* The color of the blend layer significantly influences the resulting contrast and color shift in the base layer.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} base - The base color.
|
||||
* @param {Node<vec3>} blend - The blend color
|
||||
* @return {Node<vec3>} The result.
|
||||
*/
|
||||
export const blendOverlay = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
|
||||
|
||||
return mix( base.mul( 2.0 ).mul( blend ), base.oneMinus().mul( 2.0 ).mul( blend.oneMinus() ).oneMinus(), step( 0.5, base ) );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'blendOverlay',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec3' },
|
||||
{ name: 'blend', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* This function blends two color based on their alpha values by replicating the behavior of `THREE.NormalBlending`.
|
||||
* It assumes both input colors have non-premultiplied alpha.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec4>} base - The base color.
|
||||
* @param {Node<vec4>} blend - The blend color
|
||||
* @return {Node<vec4>} The result.
|
||||
*/
|
||||
export const blendColor = /*@__PURE__*/ Fn( ( [ base, blend ] ) => {
|
||||
|
||||
const outAlpha = blend.a.add( base.a.mul( blend.a.oneMinus() ) );
|
||||
|
||||
return vec4( blend.rgb.mul( blend.a ).add( base.rgb.mul( base.a ).mul( blend.a.oneMinus() ) ).div( outAlpha ), outAlpha );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'blendColor',
|
||||
type: 'vec4',
|
||||
inputs: [
|
||||
{ name: 'base', type: 'vec4' },
|
||||
{ name: 'blend', type: 'vec4' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Premultiplies the RGB channels of a color by its alpha channel.
|
||||
*
|
||||
* This function is useful for converting a non-premultiplied alpha color
|
||||
* into a premultiplied alpha format, where the RGB values are scaled
|
||||
* by the alpha value. Premultiplied alpha is often used in graphics
|
||||
* rendering for certain operations, such as compositing and image processing.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec4>} color - The input color with non-premultiplied alpha.
|
||||
* @return {Node<vec4>} The color with premultiplied alpha.
|
||||
*/
|
||||
export const premultiplyAlpha = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
||||
|
||||
return vec4( color.rgb.mul( color.a ), color.a );
|
||||
|
||||
}, { color: 'vec4', return: 'vec4' } );
|
||||
|
||||
/**
|
||||
* Unpremultiplies the RGB channels of a color by its alpha channel.
|
||||
*
|
||||
* This function is useful for converting a premultiplied alpha color
|
||||
* back into a non-premultiplied alpha format, where the RGB values are
|
||||
* divided by the alpha value. Unpremultiplied alpha is often used in graphics
|
||||
* rendering for certain operations, such as compositing and image processing.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec4>} color - The input color with premultiplied alpha.
|
||||
* @return {Node<vec4>} The color with non-premultiplied alpha.
|
||||
*/
|
||||
export const unpremultiplyAlpha = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
||||
|
||||
If( color.a.equal( 0.0 ), () => vec4( 0.0 ) );
|
||||
|
||||
return vec4( color.rgb.div( color.a ), color.a );
|
||||
|
||||
}, { color: 'vec4', return: 'vec4' } );
|
||||
|
||||
|
||||
// Deprecated
|
||||
|
||||
/**
|
||||
* @tsl
|
||||
* @function
|
||||
* @deprecated since r171. Use {@link blendBurn} instead.
|
||||
*
|
||||
* @param {...any} params
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const burn = ( ...params ) => { // @deprecated, r171
|
||||
|
||||
console.warn( 'THREE.TSL: "burn" has been renamed. Use "blendBurn" instead.' );
|
||||
return blendBurn( params );
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @tsl
|
||||
* @function
|
||||
* @deprecated since r171. Use {@link blendDodge} instead.
|
||||
*
|
||||
* @param {...any} params
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const dodge = ( ...params ) => { // @deprecated, r171
|
||||
|
||||
console.warn( 'THREE.TSL: "dodge" has been renamed. Use "blendDodge" instead.' );
|
||||
return blendDodge( params );
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @tsl
|
||||
* @function
|
||||
* @deprecated since r171. Use {@link blendScreen} instead.
|
||||
*
|
||||
* @param {...any} params
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const screen = ( ...params ) => { // @deprecated, r171
|
||||
|
||||
console.warn( 'THREE.TSL: "screen" has been renamed. Use "blendScreen" instead.' );
|
||||
return blendScreen( params );
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @tsl
|
||||
* @function
|
||||
* @deprecated since r171. Use {@link blendOverlay} instead.
|
||||
*
|
||||
* @param {...any} params
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const overlay = ( ...params ) => { // @deprecated, r171
|
||||
|
||||
console.warn( 'THREE.TSL: "overlay" has been renamed. Use "blendOverlay" instead.' );
|
||||
return blendOverlay( params );
|
||||
|
||||
};
|
||||
117
app/node_modules/three/src/nodes/display/BumpMapNode.js
generated
vendored
Normal file
117
app/node_modules/three/src/nodes/display/BumpMapNode.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { uv } from '../accessors/UV.js';
|
||||
import { normalView } from '../accessors/Normal.js';
|
||||
import { positionView } from '../accessors/Position.js';
|
||||
import { faceDirection } from './FrontFacingNode.js';
|
||||
import { Fn, nodeProxy, float, vec2 } from '../tsl/TSLBase.js';
|
||||
|
||||
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
|
||||
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
|
||||
|
||||
const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => {
|
||||
|
||||
// It's used to preserve the same TextureNode instance
|
||||
const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } );
|
||||
|
||||
const Hll = float( sampleTexture( ( uvNode ) => uvNode ) );
|
||||
|
||||
return vec2(
|
||||
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
|
||||
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
|
||||
).mul( bumpScale );
|
||||
|
||||
} );
|
||||
|
||||
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
|
||||
|
||||
const perturbNormalArb = Fn( ( inputs ) => {
|
||||
|
||||
const { surf_pos, surf_norm, dHdxy } = inputs;
|
||||
|
||||
// normalize is done to ensure that the bump map looks the same regardless of the texture's scale
|
||||
const vSigmaX = surf_pos.dFdx().normalize();
|
||||
const vSigmaY = surf_pos.dFdy().normalize();
|
||||
const vN = surf_norm; // normalized
|
||||
|
||||
const R1 = vSigmaY.cross( vN );
|
||||
const R2 = vN.cross( vSigmaX );
|
||||
|
||||
const fDet = vSigmaX.dot( R1 ).mul( faceDirection );
|
||||
|
||||
const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) );
|
||||
|
||||
return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize();
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* This class can be used for applying bump maps to materials.
|
||||
*
|
||||
* ```js
|
||||
* material.normalNode = bumpMap( texture( bumpTex ) );
|
||||
* ```
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class BumpMapNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'BumpMapNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new bump map node.
|
||||
*
|
||||
* @param {Node<float>} textureNode - Represents the bump map data.
|
||||
* @param {?Node<float>} [scaleNode=null] - Controls the intensity of the bump effect.
|
||||
*/
|
||||
constructor( textureNode, scaleNode = null ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
/**
|
||||
* Represents the bump map data.
|
||||
*
|
||||
* @type {Node<float>}
|
||||
*/
|
||||
this.textureNode = textureNode;
|
||||
|
||||
/**
|
||||
* Controls the intensity of the bump effect.
|
||||
*
|
||||
* @type {?Node<float>}
|
||||
* @default null
|
||||
*/
|
||||
this.scaleNode = scaleNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
|
||||
const dHdxy = dHdxy_fwd( { textureNode: this.textureNode, bumpScale } );
|
||||
|
||||
return perturbNormalArb( {
|
||||
surf_pos: positionView,
|
||||
surf_norm: normalView,
|
||||
dHdxy
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BumpMapNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a bump map node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<float>} textureNode - Represents the bump map data.
|
||||
* @param {?Node<float>} [scaleNode=null] - Controls the intensity of the bump effect.
|
||||
* @returns {BumpMapNode}
|
||||
*/
|
||||
export const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ).setParameterLength( 1, 2 );
|
||||
141
app/node_modules/three/src/nodes/display/ColorAdjustment.js
generated
vendored
Normal file
141
app/node_modules/three/src/nodes/display/ColorAdjustment.js
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
import { dot, max, mix } from '../math/MathNode.js';
|
||||
import { add } from '../math/OperatorNode.js';
|
||||
import { Fn, If, float, vec3, vec4 } from '../tsl/TSLBase.js';
|
||||
import { ColorManagement } from '../../math/ColorManagement.js';
|
||||
import { Vector3 } from '../../math/Vector3.js';
|
||||
import { LinearSRGBColorSpace } from '../../constants.js';
|
||||
|
||||
/**
|
||||
* Computes a grayscale value for the given RGB color value.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color value to compute the grayscale for.
|
||||
* @return {Node<vec3>} The grayscale color.
|
||||
*/
|
||||
export const grayscale = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
||||
|
||||
return luminance( color.rgb );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Super-saturates or desaturates the given RGB color.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The input color.
|
||||
* @param {Node<float>} [adjustment=1] - Specifies the amount of the conversion. A value under `1` desaturates the color, a value over `1` super-saturates it.
|
||||
* @return {Node<vec3>} The saturated color.
|
||||
*/
|
||||
export const saturation = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => {
|
||||
|
||||
return adjustment.mix( luminance( color.rgb ), color.rgb );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Selectively enhance the intensity of less saturated RGB colors. Can result
|
||||
* in a more natural and visually appealing image with enhanced color depth
|
||||
* compared to {@link ColorAdjustment#saturation}.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The input color.
|
||||
* @param {Node<float>} [adjustment=1] - Controls the intensity of the vibrance effect.
|
||||
* @return {Node<vec3>} The updated color.
|
||||
*/
|
||||
export const vibrance = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => {
|
||||
|
||||
const average = add( color.r, color.g, color.b ).div( 3.0 );
|
||||
|
||||
const mx = color.r.max( color.g.max( color.b ) );
|
||||
const amt = mx.sub( average ).mul( adjustment ).mul( - 3.0 );
|
||||
|
||||
return mix( color.rgb, mx, amt );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Updates the hue component of the given RGB color while preserving its luminance and saturation.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The input color.
|
||||
* @param {Node<float>} [adjustment=1] - Defines the degree of hue rotation in radians. A positive value rotates the hue clockwise, while a negative value rotates it counterclockwise.
|
||||
* @return {Node<vec3>} The updated color.
|
||||
*/
|
||||
export const hue = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => {
|
||||
|
||||
const k = vec3( 0.57735, 0.57735, 0.57735 );
|
||||
|
||||
const cosAngle = adjustment.cos();
|
||||
|
||||
return vec3( color.rgb.mul( cosAngle ).add( k.cross( color.rgb ).mul( adjustment.sin() ).add( k.mul( dot( k, color.rgb ).mul( cosAngle.oneMinus() ) ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* Computes the luminance for the given RGB color value.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color value to compute the luminance for.
|
||||
* @param {?Node<vec3>} luminanceCoefficients - The luminance coefficients. By default predefined values of the current working color space are used.
|
||||
* @return {Node<vec3>} The luminance.
|
||||
*/
|
||||
export const luminance = (
|
||||
color,
|
||||
luminanceCoefficients = vec3( ColorManagement.getLuminanceCoefficients( new Vector3() ) )
|
||||
) => dot( color, luminanceCoefficients );
|
||||
|
||||
/**
|
||||
* Color Decision List (CDL) v1.2
|
||||
*
|
||||
* Compact representation of color grading information, defined by slope, offset, power, and
|
||||
* saturation. The CDL should be typically be given input in a log space (such as LogC, ACEScc,
|
||||
* or AgX Log), and will return output in the same space. Output may require clamping >=0.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec4>} color Input (-Infinity < input < +Infinity)
|
||||
* @param {Node<vec3>} slope Slope (0 ≤ slope < +Infinity)
|
||||
* @param {Node<vec3>} offset Offset (-Infinity < offset < +Infinity; typically -1 < offset < 1)
|
||||
* @param {Node<vec3>} power Power (0 < power < +Infinity)
|
||||
* @param {Node<float>} saturation Saturation (0 ≤ saturation < +Infinity; typically 0 ≤ saturation < 4)
|
||||
* @param {Node<vec3>} luminanceCoefficients Luminance coefficients for saturation term, typically Rec. 709
|
||||
* @return {Node<vec4>} Output, -Infinity < output < +Infinity
|
||||
*
|
||||
* References:
|
||||
* - ASC CDL v1.2
|
||||
* - {@link https://blender.stackexchange.com/a/55239/43930}
|
||||
* - {@link https://docs.acescentral.com/specifications/acescc/}
|
||||
*/
|
||||
export const cdl = /*@__PURE__*/ Fn( ( [
|
||||
color,
|
||||
slope = vec3( 1 ),
|
||||
offset = vec3( 0 ),
|
||||
power = vec3( 1 ),
|
||||
saturation = float( 1 ),
|
||||
// ASC CDL v1.2 explicitly requires Rec. 709 luminance coefficients.
|
||||
luminanceCoefficients = vec3( ColorManagement.getLuminanceCoefficients( new Vector3(), LinearSRGBColorSpace ) )
|
||||
] ) => {
|
||||
|
||||
// NOTE: The ASC CDL v1.2 defines a [0, 1] clamp on the slope+offset term, and another on the
|
||||
// saturation term. Per the ACEScc specification and Filament, limits may be omitted to support
|
||||
// values outside [0, 1], requiring a workaround for negative values in the power expression.
|
||||
|
||||
const luma = color.rgb.dot( vec3( luminanceCoefficients ) );
|
||||
|
||||
const v = max( color.rgb.mul( slope ).add( offset ), 0.0 ).toVar();
|
||||
const pv = v.pow( power ).toVar();
|
||||
|
||||
If( v.r.greaterThan( 0.0 ), () => { v.r.assign( pv.r ); } ); // eslint-disable-line
|
||||
If( v.g.greaterThan( 0.0 ), () => { v.g.assign( pv.g ); } ); // eslint-disable-line
|
||||
If( v.b.greaterThan( 0.0 ), () => { v.b.assign( pv.b ); } ); // eslint-disable-line
|
||||
|
||||
v.assign( luma.add( v.sub( luma ).mul( saturation ) ) );
|
||||
|
||||
return vec4( v.rgb, color.a );
|
||||
|
||||
} );
|
||||
54
app/node_modules/three/src/nodes/display/ColorSpaceFunctions.js
generated
vendored
Normal file
54
app/node_modules/three/src/nodes/display/ColorSpaceFunctions.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { mix } from '../math/MathNode.js';
|
||||
import { Fn } from '../tsl/TSLCore.js';
|
||||
|
||||
/**
|
||||
* Converts the given color value from sRGB to linear-sRGB color space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The sRGB color.
|
||||
* @return {Node<vec3>} The linear-sRGB color.
|
||||
*/
|
||||
export const sRGBTransferEOTF = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
||||
|
||||
const a = color.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 );
|
||||
const b = color.mul( 0.0773993808 );
|
||||
const factor = color.lessThanEqual( 0.04045 );
|
||||
|
||||
const rgbResult = mix( a, b, factor );
|
||||
|
||||
return rgbResult;
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'sRGBTransferEOTF',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Converts the given color value from linear-sRGB to sRGB color space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The linear-sRGB color.
|
||||
* @return {Node<vec3>} The sRGB color.
|
||||
*/
|
||||
export const sRGBTransferOETF = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
||||
|
||||
const a = color.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 );
|
||||
const b = color.mul( 12.92 );
|
||||
const factor = color.lessThanEqual( 0.0031308 );
|
||||
|
||||
const rgbResult = mix( a, b, factor );
|
||||
|
||||
return rgbResult;
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'sRGBTransferOETF',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' }
|
||||
]
|
||||
} );
|
||||
164
app/node_modules/three/src/nodes/display/ColorSpaceNode.js
generated
vendored
Normal file
164
app/node_modules/three/src/nodes/display/ColorSpaceNode.js
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addMethodChaining, mat3, nodeObject, vec4 } from '../tsl/TSLCore.js';
|
||||
|
||||
import { SRGBTransfer } from '../../constants.js';
|
||||
import { ColorManagement } from '../../math/ColorManagement.js';
|
||||
import { sRGBTransferEOTF, sRGBTransferOETF } from './ColorSpaceFunctions.js';
|
||||
import { Matrix3 } from '../../math/Matrix3.js';
|
||||
|
||||
const WORKING_COLOR_SPACE = 'WorkingColorSpace';
|
||||
const OUTPUT_COLOR_SPACE = 'OutputColorSpace';
|
||||
|
||||
/**
|
||||
* This node represents a color space conversion. Meaning it converts
|
||||
* a color value from a source to a target color space.
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class ColorSpaceNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ColorSpaceNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new color space node.
|
||||
*
|
||||
* @param {Node} colorNode - Represents the color to convert.
|
||||
* @param {string} source - The source color space.
|
||||
* @param {string} target - The target color space.
|
||||
*/
|
||||
constructor( colorNode, source, target ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
/**
|
||||
* Represents the color to convert.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.colorNode = colorNode;
|
||||
|
||||
/**
|
||||
* The source color space.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.source = source;
|
||||
|
||||
/**
|
||||
* The target color space.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.target = target;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method resolves the constants `WORKING_COLOR_SPACE` and
|
||||
* `OUTPUT_COLOR_SPACE` based on the current configuration of the
|
||||
* color management and renderer.
|
||||
*
|
||||
* @param {NodeBuilder} builder - The current node builder.
|
||||
* @param {string} colorSpace - The color space to resolve.
|
||||
* @return {string} The resolved color space.
|
||||
*/
|
||||
resolveColorSpace( builder, colorSpace ) {
|
||||
|
||||
if ( colorSpace === WORKING_COLOR_SPACE ) {
|
||||
|
||||
return ColorManagement.workingColorSpace;
|
||||
|
||||
} else if ( colorSpace === OUTPUT_COLOR_SPACE ) {
|
||||
|
||||
return builder.context.outputColorSpace || builder.renderer.outputColorSpace;
|
||||
|
||||
}
|
||||
|
||||
return colorSpace;
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
const { colorNode } = this;
|
||||
|
||||
const source = this.resolveColorSpace( builder, this.source );
|
||||
const target = this.resolveColorSpace( builder, this.target );
|
||||
|
||||
let outputNode = colorNode;
|
||||
|
||||
if ( ColorManagement.enabled === false || source === target || ! source || ! target ) {
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
if ( ColorManagement.getTransfer( source ) === SRGBTransfer ) {
|
||||
|
||||
outputNode = vec4( sRGBTransferEOTF( outputNode.rgb ), outputNode.a );
|
||||
|
||||
}
|
||||
|
||||
if ( ColorManagement.getPrimaries( source ) !== ColorManagement.getPrimaries( target ) ) {
|
||||
|
||||
outputNode = vec4(
|
||||
mat3( ColorManagement._getMatrix( new Matrix3(), source, target ) ).mul( outputNode.rgb ),
|
||||
outputNode.a
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if ( ColorManagement.getTransfer( target ) === SRGBTransfer ) {
|
||||
|
||||
outputNode = vec4( sRGBTransferOETF( outputNode.rgb ), outputNode.a );
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ColorSpaceNode;
|
||||
|
||||
/**
|
||||
* TSL function for converting a given color node from the current working color space to the given color space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - Represents the node to convert.
|
||||
* @param {string} targetColorSpace - The target color space.
|
||||
* @returns {ColorSpaceNode}
|
||||
*/
|
||||
export const workingToColorSpace = ( node, targetColorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), WORKING_COLOR_SPACE, targetColorSpace ) );
|
||||
|
||||
/**
|
||||
* TSL function for converting a given color node from the given color space to the current working color space.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - Represents the node to convert.
|
||||
* @param {string} sourceColorSpace - The source color space.
|
||||
* @returns {ColorSpaceNode}
|
||||
*/
|
||||
export const colorSpaceToWorking = ( node, sourceColorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), sourceColorSpace, WORKING_COLOR_SPACE ) );
|
||||
|
||||
/**
|
||||
* TSL function for converting a given color node from one color space to another one.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} node - Represents the node to convert.
|
||||
* @param {string} sourceColorSpace - The source color space.
|
||||
* @param {string} targetColorSpace - The target color space.
|
||||
* @returns {ColorSpaceNode}
|
||||
*/
|
||||
export const convertColorSpace = ( node, sourceColorSpace, targetColorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), sourceColorSpace, targetColorSpace ) );
|
||||
|
||||
addMethodChaining( 'workingToColorSpace', workingToColorSpace );
|
||||
addMethodChaining( 'colorSpaceToWorking', colorSpaceToWorking );
|
||||
106
app/node_modules/three/src/nodes/display/FrontFacingNode.js
generated
vendored
Normal file
106
app/node_modules/three/src/nodes/display/FrontFacingNode.js
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { nodeImmutable, float, Fn } from '../tsl/TSLBase.js';
|
||||
|
||||
import { BackSide, DoubleSide, WebGLCoordinateSystem } 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 { renderer, material } = builder;
|
||||
|
||||
if ( renderer.coordinateSystem === WebGLCoordinateSystem ) {
|
||||
|
||||
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 );
|
||||
|
||||
/**
|
||||
* Converts a direction vector to a face direction vector based on the material's side.
|
||||
*
|
||||
* If the material is set to `BackSide`, the direction is inverted.
|
||||
* If the material is set to `DoubleSide`, the direction is multiplied by `faceDirection`.
|
||||
*
|
||||
* @tsl
|
||||
* @param {Node<vec3>} direction - The direction vector to convert.
|
||||
* @returns {Node<vec3>} The converted direction vector.
|
||||
*/
|
||||
export const directionToFaceDirection = /*@__PURE__*/ Fn( ( [ direction ], { material } ) => {
|
||||
|
||||
const side = material.side;
|
||||
|
||||
if ( side === BackSide ) {
|
||||
|
||||
direction = direction.mul( - 1.0 );
|
||||
|
||||
} else if ( side === DoubleSide ) {
|
||||
|
||||
direction = direction.mul( faceDirection );
|
||||
|
||||
}
|
||||
|
||||
return direction;
|
||||
|
||||
} );
|
||||
117
app/node_modules/three/src/nodes/display/NormalMapNode.js
generated
vendored
Normal file
117
app/node_modules/three/src/nodes/display/NormalMapNode.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
|
||||
import { normalView, transformNormalToView } from '../accessors/Normal.js';
|
||||
import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
|
||||
import { nodeProxy, vec3 } from '../tsl/TSLBase.js';
|
||||
|
||||
import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from '../../constants.js';
|
||||
import { directionToFaceDirection } from './FrontFacingNode.js';
|
||||
|
||||
/**
|
||||
* This class can be used for applying normals maps to materials.
|
||||
*
|
||||
* ```js
|
||||
* material.normalNode = normalMap( texture( normalTex ) );
|
||||
* ```
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class NormalMapNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'NormalMapNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new normal map node.
|
||||
*
|
||||
* @param {Node<vec3>} node - Represents the normal map data.
|
||||
* @param {?Node<vec2>} [scaleNode=null] - Controls the intensity of the effect.
|
||||
*/
|
||||
constructor( node, scaleNode = null ) {
|
||||
|
||||
super( 'vec3' );
|
||||
|
||||
/**
|
||||
* Represents the normal map data.
|
||||
*
|
||||
* @type {Node<vec3>}
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* Controls the intensity of the effect.
|
||||
*
|
||||
* @type {?Node<vec2>}
|
||||
* @default null
|
||||
*/
|
||||
this.scaleNode = scaleNode;
|
||||
|
||||
/**
|
||||
* The normal map type.
|
||||
*
|
||||
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
|
||||
* @default TangentSpaceNormalMap
|
||||
*/
|
||||
this.normalMapType = TangentSpaceNormalMap;
|
||||
|
||||
}
|
||||
|
||||
setup( { material } ) {
|
||||
|
||||
const { normalMapType, scaleNode } = this;
|
||||
|
||||
let normalMap = this.node.mul( 2.0 ).sub( 1.0 );
|
||||
|
||||
if ( scaleNode !== null ) {
|
||||
|
||||
let scale = scaleNode;
|
||||
|
||||
if ( material.flatShading === true ) {
|
||||
|
||||
scale = directionToFaceDirection( scale );
|
||||
|
||||
}
|
||||
|
||||
normalMap = vec3( normalMap.xy.mul( scale ), normalMap.z );
|
||||
|
||||
}
|
||||
|
||||
let output = null;
|
||||
|
||||
if ( normalMapType === ObjectSpaceNormalMap ) {
|
||||
|
||||
output = transformNormalToView( normalMap );
|
||||
|
||||
} else if ( normalMapType === TangentSpaceNormalMap ) {
|
||||
|
||||
output = TBNViewMatrix.mul( normalMap ).normalize();
|
||||
|
||||
} else {
|
||||
|
||||
console.error( `THREE.NodeMaterial: Unsupported normal map type: ${ normalMapType }` );
|
||||
|
||||
output = normalView; // Fallback to default normal view
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NormalMapNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a normal map node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} node - Represents the normal map data.
|
||||
* @param {?Node<vec2>} [scaleNode=null] - Controls the intensity of the effect.
|
||||
* @returns {NormalMapNode}
|
||||
*/
|
||||
export const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ).setParameterLength( 1, 2 );
|
||||
759
app/node_modules/three/src/nodes/display/PassNode.js
generated
vendored
Normal file
759
app/node_modules/three/src/nodes/display/PassNode.js
generated
vendored
Normal file
@@ -0,0 +1,759 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { default as TextureNode/*, texture*/ } from '../accessors/TextureNode.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { nodeObject } from '../tsl/TSLBase.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { viewZToOrthographicDepth, perspectiveDepthToViewZ } from './ViewportDepthNode.js';
|
||||
|
||||
import { HalfFloatType/*, FloatType*/ } from '../../constants.js';
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { DepthTexture } from '../../textures/DepthTexture.js';
|
||||
import { RenderTarget } from '../../core/RenderTarget.js';
|
||||
|
||||
const _size = /*@__PURE__*/ new Vector2();
|
||||
|
||||
/**
|
||||
* Represents the texture of a pass node.
|
||||
*
|
||||
* @augments TextureNode
|
||||
*/
|
||||
class PassTextureNode extends TextureNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PassTextureNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new pass texture node.
|
||||
*
|
||||
* @param {PassNode} passNode - The pass node.
|
||||
* @param {Texture} texture - The output texture.
|
||||
*/
|
||||
constructor( passNode, texture ) {
|
||||
|
||||
super( texture );
|
||||
|
||||
/**
|
||||
* A reference to the pass node.
|
||||
*
|
||||
* @type {PassNode}
|
||||
*/
|
||||
this.passNode = passNode;
|
||||
|
||||
this.setUpdateMatrix( false );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
if ( builder.object.isQuadMesh ) this.passNode.build( builder );
|
||||
|
||||
return super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
return new this.constructor( this.passNode, this.value );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of `PassTextureNode` which allows to manage more than one
|
||||
* internal texture. Relevant for the `getPreviousTexture()` related API.
|
||||
*
|
||||
* @augments PassTextureNode
|
||||
*/
|
||||
class PassMultipleTextureNode extends PassTextureNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PassMultipleTextureNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new pass texture node.
|
||||
*
|
||||
* @param {PassNode} passNode - The pass node.
|
||||
* @param {string} textureName - The output texture name.
|
||||
* @param {boolean} [previousTexture=false] - Whether previous frame data should be used or not.
|
||||
*/
|
||||
constructor( passNode, textureName, previousTexture = false ) {
|
||||
|
||||
// null is passed to the super call since this class does not
|
||||
// use an external texture for rendering pass data into. Instead
|
||||
// the texture is managed by the pass node itself
|
||||
|
||||
super( passNode, null );
|
||||
|
||||
/**
|
||||
* The output texture name.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
this.textureName = textureName;
|
||||
|
||||
/**
|
||||
* Whether previous frame data should be used or not.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.previousTexture = previousTexture;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the texture reference of this node.
|
||||
*/
|
||||
updateTexture() {
|
||||
|
||||
this.value = this.previousTexture ? this.passNode.getPreviousTexture( this.textureName ) : this.passNode.getTexture( this.textureName );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
this.updateTexture();
|
||||
|
||||
return super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
const newNode = new this.constructor( this.passNode, this.textureName, this.previousTexture );
|
||||
newNode.uvNode = this.uvNode;
|
||||
newNode.levelNode = this.levelNode;
|
||||
newNode.biasNode = this.biasNode;
|
||||
newNode.sampler = this.sampler;
|
||||
newNode.depthNode = this.depthNode;
|
||||
newNode.compareNode = this.compareNode;
|
||||
newNode.gradNode = this.gradNode;
|
||||
|
||||
return newNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a render pass (sometimes called beauty pass) in context of post processing.
|
||||
* This pass produces a render for the given scene and camera and can provide multiple outputs
|
||||
* via MRT for further processing.
|
||||
*
|
||||
* ```js
|
||||
* const postProcessing = new PostProcessing( renderer );
|
||||
*
|
||||
* const scenePass = pass( scene, camera );
|
||||
*
|
||||
* postProcessing.outputNode = scenePass;
|
||||
* ```
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class PassNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PassNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new pass node.
|
||||
*
|
||||
* @param {('color'|'depth')} scope - The scope of the pass. The scope determines whether the node outputs color or depth.
|
||||
* @param {Scene} scene - A reference to the scene.
|
||||
* @param {Camera} camera - A reference to the camera.
|
||||
* @param {Object} options - Options for the internal render target.
|
||||
*/
|
||||
constructor( scope, scene, camera, options = {} ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
/**
|
||||
* The scope of the pass. The scope determines whether the node outputs color or depth.
|
||||
*
|
||||
* @type {('color'|'depth')}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
/**
|
||||
* A reference to the scene.
|
||||
*
|
||||
* @type {Scene}
|
||||
*/
|
||||
this.scene = scene;
|
||||
|
||||
/**
|
||||
* A reference to the camera.
|
||||
*
|
||||
* @type {Camera}
|
||||
*/
|
||||
this.camera = camera;
|
||||
|
||||
/**
|
||||
* Options for the internal render target.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.options = options;
|
||||
|
||||
/**
|
||||
* The pass's pixel ratio. Will be kept automatically kept in sync with the renderer's pixel ratio.
|
||||
*
|
||||
* @private
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this._pixelRatio = 1;
|
||||
|
||||
/**
|
||||
* The pass's pixel width. Will be kept automatically kept in sync with the renderer's width.
|
||||
* @private
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this._width = 1;
|
||||
|
||||
/**
|
||||
* The pass's pixel height. Will be kept automatically kept in sync with the renderer's height.
|
||||
* @private
|
||||
* @type {number}
|
||||
* @default 1
|
||||
*/
|
||||
this._height = 1;
|
||||
|
||||
const depthTexture = new DepthTexture();
|
||||
depthTexture.isRenderTargetTexture = true;
|
||||
//depthTexture.type = FloatType;
|
||||
depthTexture.name = 'depth';
|
||||
|
||||
const renderTarget = new RenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType, ...options, } );
|
||||
renderTarget.texture.name = 'output';
|
||||
renderTarget.depthTexture = depthTexture;
|
||||
|
||||
/**
|
||||
* The pass's render target.
|
||||
*
|
||||
* @type {RenderTarget}
|
||||
*/
|
||||
this.renderTarget = renderTarget;
|
||||
|
||||
/**
|
||||
* A dictionary holding the internal result textures.
|
||||
*
|
||||
* @private
|
||||
* @type {Object<string, Texture>}
|
||||
*/
|
||||
this._textures = {
|
||||
output: renderTarget.texture,
|
||||
depth: depthTexture
|
||||
};
|
||||
|
||||
/**
|
||||
* A dictionary holding the internal texture nodes.
|
||||
*
|
||||
* @private
|
||||
* @type {Object<string, TextureNode>}
|
||||
*/
|
||||
this._textureNodes = {};
|
||||
|
||||
/**
|
||||
* A dictionary holding the internal depth nodes.
|
||||
*
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._linearDepthNodes = {};
|
||||
|
||||
/**
|
||||
* A dictionary holding the internal viewZ nodes.
|
||||
*
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._viewZNodes = {};
|
||||
|
||||
/**
|
||||
* A dictionary holding the texture data of the previous frame.
|
||||
* Used for computing velocity/motion vectors.
|
||||
*
|
||||
* @private
|
||||
* @type {Object<string, Texture>}
|
||||
*/
|
||||
this._previousTextures = {};
|
||||
|
||||
/**
|
||||
* A dictionary holding the texture nodes of the previous frame.
|
||||
* Used for computing velocity/motion vectors.
|
||||
*
|
||||
* @private
|
||||
* @type {Object<string, TextureNode>}
|
||||
*/
|
||||
this._previousTextureNodes = {};
|
||||
|
||||
/**
|
||||
* The `near` property of the camera as a uniform.
|
||||
*
|
||||
* @private
|
||||
* @type {UniformNode}
|
||||
*/
|
||||
this._cameraNear = uniform( 0 );
|
||||
|
||||
/**
|
||||
* The `far` property of the camera as a uniform.
|
||||
*
|
||||
* @private
|
||||
* @type {UniformNode}
|
||||
*/
|
||||
this._cameraFar = uniform( 0 );
|
||||
|
||||
/**
|
||||
* A MRT node configuring the MRT settings.
|
||||
*
|
||||
* @private
|
||||
* @type {?MRTNode}
|
||||
* @default null
|
||||
*/
|
||||
this._mrt = null;
|
||||
|
||||
this._layers = null;
|
||||
|
||||
this._resolution = 1;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isPassNode = true;
|
||||
|
||||
/**
|
||||
* The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders the
|
||||
* scene once per frame in its {@link PassNode#updateBefore} method.
|
||||
*
|
||||
* @type {string}
|
||||
* @default 'frame'
|
||||
*/
|
||||
this.updateBeforeType = NodeUpdateType.FRAME;
|
||||
|
||||
/**
|
||||
* This flag is used for global cache.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @default true
|
||||
*/
|
||||
this.global = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resolution for the pass.
|
||||
* The resolution is a factor that is multiplied with the renderer's width and height.
|
||||
*
|
||||
* @param {number} resolution - The resolution to set. A value of `1` means full resolution.
|
||||
* @return {PassNode} A reference to this pass.
|
||||
*/
|
||||
setResolution( resolution ) {
|
||||
|
||||
this._resolution = resolution;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current resolution of the pass.
|
||||
*
|
||||
* @return {number} The current resolution. A value of `1` means full resolution.
|
||||
* @default 1
|
||||
*/
|
||||
getResolution() {
|
||||
|
||||
return this._resolution;
|
||||
|
||||
}
|
||||
|
||||
setLayers( layers ) {
|
||||
|
||||
this._layers = layers;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
getLayers() {
|
||||
|
||||
return this._layers;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given MRT node to setup MRT for this pass.
|
||||
*
|
||||
* @param {MRTNode} mrt - The MRT object.
|
||||
* @return {PassNode} A reference to this pass.
|
||||
*/
|
||||
setMRT( mrt ) {
|
||||
|
||||
this._mrt = mrt;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current MRT node.
|
||||
*
|
||||
* @return {MRTNode} The current MRT node.
|
||||
*/
|
||||
getMRT() {
|
||||
|
||||
return this._mrt;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the texture for the given output name.
|
||||
*
|
||||
* @param {string} name - The output name to get the texture for.
|
||||
* @return {Texture} The texture.
|
||||
*/
|
||||
getTexture( name ) {
|
||||
|
||||
let texture = this._textures[ name ];
|
||||
|
||||
if ( texture === undefined ) {
|
||||
|
||||
const refTexture = this.renderTarget.texture;
|
||||
|
||||
texture = refTexture.clone();
|
||||
texture.name = name;
|
||||
|
||||
this._textures[ name ] = texture;
|
||||
|
||||
this.renderTarget.textures.push( texture );
|
||||
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the texture holding the data of the previous frame for the given output name.
|
||||
*
|
||||
* @param {string} name - The output name to get the texture for.
|
||||
* @return {Texture} The texture holding the data of the previous frame.
|
||||
*/
|
||||
getPreviousTexture( name ) {
|
||||
|
||||
let texture = this._previousTextures[ name ];
|
||||
|
||||
if ( texture === undefined ) {
|
||||
|
||||
texture = this.getTexture( name ).clone();
|
||||
|
||||
this._previousTextures[ name ] = texture;
|
||||
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches current and previous textures for the given output name.
|
||||
*
|
||||
* @param {string} name - The output name.
|
||||
*/
|
||||
toggleTexture( name ) {
|
||||
|
||||
const prevTexture = this._previousTextures[ name ];
|
||||
|
||||
if ( prevTexture !== undefined ) {
|
||||
|
||||
const texture = this._textures[ name ];
|
||||
|
||||
const index = this.renderTarget.textures.indexOf( texture );
|
||||
this.renderTarget.textures[ index ] = prevTexture;
|
||||
|
||||
this._textures[ name ] = prevTexture;
|
||||
this._previousTextures[ name ] = texture;
|
||||
|
||||
this._textureNodes[ name ].updateTexture();
|
||||
this._previousTextureNodes[ name ].updateTexture();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the texture node for the given output name.
|
||||
*
|
||||
* @param {string} [name='output'] - The output name to get the texture node for.
|
||||
* @return {TextureNode} The texture node.
|
||||
*/
|
||||
getTextureNode( name = 'output' ) {
|
||||
|
||||
let textureNode = this._textureNodes[ name ];
|
||||
|
||||
if ( textureNode === undefined ) {
|
||||
|
||||
textureNode = nodeObject( new PassMultipleTextureNode( this, name ) );
|
||||
textureNode.updateTexture();
|
||||
this._textureNodes[ name ] = textureNode;
|
||||
|
||||
}
|
||||
|
||||
return textureNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous texture node for the given output name.
|
||||
*
|
||||
* @param {string} [name='output'] - The output name to get the previous texture node for.
|
||||
* @return {TextureNode} The previous texture node.
|
||||
*/
|
||||
getPreviousTextureNode( name = 'output' ) {
|
||||
|
||||
let textureNode = this._previousTextureNodes[ name ];
|
||||
|
||||
if ( textureNode === undefined ) {
|
||||
|
||||
if ( this._textureNodes[ name ] === undefined ) this.getTextureNode( name );
|
||||
|
||||
textureNode = nodeObject( new PassMultipleTextureNode( this, name, true ) );
|
||||
textureNode.updateTexture();
|
||||
this._previousTextureNodes[ name ] = textureNode;
|
||||
|
||||
}
|
||||
|
||||
return textureNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a viewZ node of this pass.
|
||||
*
|
||||
* @param {string} [name='depth'] - The output name to get the viewZ node for. In most cases the default `'depth'` can be used however the parameter exists for custom depth outputs.
|
||||
* @return {Node} The viewZ node.
|
||||
*/
|
||||
getViewZNode( name = 'depth' ) {
|
||||
|
||||
let viewZNode = this._viewZNodes[ name ];
|
||||
|
||||
if ( viewZNode === undefined ) {
|
||||
|
||||
const cameraNear = this._cameraNear;
|
||||
const cameraFar = this._cameraFar;
|
||||
|
||||
this._viewZNodes[ name ] = viewZNode = perspectiveDepthToViewZ( this.getTextureNode( name ), cameraNear, cameraFar );
|
||||
|
||||
}
|
||||
|
||||
return viewZNode;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a linear depth node of this pass.
|
||||
*
|
||||
* @param {string} [name='depth'] - The output name to get the linear depth node for. In most cases the default `'depth'` can be used however the parameter exists for custom depth outputs.
|
||||
* @return {Node} The linear depth node.
|
||||
*/
|
||||
getLinearDepthNode( name = 'depth' ) {
|
||||
|
||||
let linearDepthNode = this._linearDepthNodes[ name ];
|
||||
|
||||
if ( linearDepthNode === undefined ) {
|
||||
|
||||
const cameraNear = this._cameraNear;
|
||||
const cameraFar = this._cameraFar;
|
||||
const viewZNode = this.getViewZNode( name );
|
||||
|
||||
// TODO: just if ( builder.camera.isPerspectiveCamera )
|
||||
|
||||
this._linearDepthNodes[ name ] = linearDepthNode = viewZToOrthographicDepth( viewZNode, cameraNear, cameraFar );
|
||||
|
||||
}
|
||||
|
||||
return linearDepthNode;
|
||||
|
||||
}
|
||||
|
||||
setup( { renderer } ) {
|
||||
|
||||
this.renderTarget.samples = this.options.samples === undefined ? renderer.samples : this.options.samples;
|
||||
|
||||
this.renderTarget.texture.type = renderer.getColorBufferType();
|
||||
|
||||
return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode();
|
||||
|
||||
}
|
||||
|
||||
updateBefore( frame ) {
|
||||
|
||||
const { renderer } = frame;
|
||||
const { scene } = this;
|
||||
|
||||
let camera;
|
||||
let pixelRatio;
|
||||
|
||||
const outputRenderTarget = renderer.getOutputRenderTarget();
|
||||
|
||||
if ( outputRenderTarget && outputRenderTarget.isXRRenderTarget === true ) {
|
||||
|
||||
pixelRatio = 1;
|
||||
camera = renderer.xr.getCamera();
|
||||
|
||||
renderer.xr.updateCamera( camera );
|
||||
|
||||
_size.set( outputRenderTarget.width, outputRenderTarget.height );
|
||||
|
||||
} else {
|
||||
|
||||
camera = this.camera;
|
||||
pixelRatio = renderer.getPixelRatio();
|
||||
|
||||
renderer.getSize( _size );
|
||||
|
||||
}
|
||||
|
||||
this._pixelRatio = pixelRatio;
|
||||
|
||||
this.setSize( _size.width, _size.height );
|
||||
|
||||
const currentRenderTarget = renderer.getRenderTarget();
|
||||
const currentMRT = renderer.getMRT();
|
||||
const currentMask = camera.layers.mask;
|
||||
|
||||
this._cameraNear.value = camera.near;
|
||||
this._cameraFar.value = camera.far;
|
||||
|
||||
if ( this._layers !== null ) {
|
||||
|
||||
camera.layers.mask = this._layers.mask;
|
||||
|
||||
}
|
||||
|
||||
for ( const name in this._previousTextures ) {
|
||||
|
||||
this.toggleTexture( name );
|
||||
|
||||
}
|
||||
|
||||
renderer.setRenderTarget( this.renderTarget );
|
||||
renderer.setMRT( this._mrt );
|
||||
|
||||
renderer.render( scene, camera );
|
||||
|
||||
renderer.setRenderTarget( currentRenderTarget );
|
||||
renderer.setMRT( currentMRT );
|
||||
|
||||
camera.layers.mask = currentMask;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the pass's render target. Honors the pixel ratio.
|
||||
*
|
||||
* @param {number} width - The width to set.
|
||||
* @param {number} height - The height to set.
|
||||
*/
|
||||
setSize( width, height ) {
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
const effectiveWidth = this._width * this._pixelRatio * this._resolution;
|
||||
const effectiveHeight = this._height * this._pixelRatio * this._resolution;
|
||||
|
||||
this.renderTarget.setSize( effectiveWidth, effectiveHeight );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pixel ratio the pass's render target and updates the size.
|
||||
*
|
||||
* @param {number} pixelRatio - The pixel ratio to set.
|
||||
*/
|
||||
setPixelRatio( pixelRatio ) {
|
||||
|
||||
this._pixelRatio = pixelRatio;
|
||||
|
||||
this.setSize( this._width, this._height );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees internal resources. Should be called when the node is no longer in use.
|
||||
*/
|
||||
dispose() {
|
||||
|
||||
this.renderTarget.dispose();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @type {'color'}
|
||||
* @default 'color'
|
||||
*/
|
||||
PassNode.COLOR = 'color';
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @type {'depth'}
|
||||
* @default 'depth'
|
||||
*/
|
||||
PassNode.DEPTH = 'depth';
|
||||
|
||||
export default PassNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a pass node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Scene} scene - A reference to the scene.
|
||||
* @param {Camera} camera - A reference to the camera.
|
||||
* @param {Object} options - Options for the internal render target.
|
||||
* @returns {PassNode}
|
||||
*/
|
||||
export const pass = ( scene, camera, options ) => nodeObject( new PassNode( PassNode.COLOR, scene, camera, options ) );
|
||||
|
||||
/**
|
||||
* TSL function for creating a pass texture node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {PassNode} pass - The pass node.
|
||||
* @param {Texture} texture - The output texture.
|
||||
* @returns {PassTextureNode}
|
||||
*/
|
||||
export const passTexture = ( pass, texture ) => nodeObject( new PassTextureNode( pass, texture ) );
|
||||
|
||||
/**
|
||||
* TSL function for creating a depth pass node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Scene} scene - A reference to the scene.
|
||||
* @param {Camera} camera - A reference to the camera.
|
||||
* @param {Object} options - Options for the internal render target.
|
||||
* @returns {PassNode}
|
||||
*/
|
||||
export const depthPass = ( scene, camera, options ) => nodeObject( new PassNode( PassNode.DEPTH, scene, camera, options ) );
|
||||
65
app/node_modules/three/src/nodes/display/PosterizeNode.js
generated
vendored
Normal file
65
app/node_modules/three/src/nodes/display/PosterizeNode.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { nodeProxy } from '../tsl/TSLBase.js';
|
||||
|
||||
/**
|
||||
* Represents a posterize effect which reduces the number of colors
|
||||
* in an image, resulting in a more blocky and stylized appearance.
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class PosterizeNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'PosterizeNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new posterize node.
|
||||
*
|
||||
* @param {Node} sourceNode - The input color.
|
||||
* @param {Node} stepsNode - Controls the intensity of the posterization effect. A lower number results in a more blocky appearance.
|
||||
*/
|
||||
constructor( sourceNode, stepsNode ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The input color.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.sourceNode = sourceNode;
|
||||
|
||||
/**
|
||||
* Controls the intensity of the posterization effect. A lower number results in a more blocky appearance.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.stepsNode = stepsNode;
|
||||
|
||||
}
|
||||
|
||||
setup() {
|
||||
|
||||
const { sourceNode, stepsNode } = this;
|
||||
|
||||
return sourceNode.mul( stepsNode ).floor().div( stepsNode );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PosterizeNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a posterize node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} sourceNode - The input color.
|
||||
* @param {Node} stepsNode - Controls the intensity of the posterization effect. A lower number results in a more blocky appearance.
|
||||
* @returns {PosterizeNode}
|
||||
*/
|
||||
export const posterize = /*@__PURE__*/ nodeProxy( PosterizeNode ).setParameterLength( 2 );
|
||||
124
app/node_modules/three/src/nodes/display/RenderOutputNode.js
generated
vendored
Normal file
124
app/node_modules/three/src/nodes/display/RenderOutputNode.js
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
import TempNode from '../core/TempNode.js';
|
||||
import { addMethodChaining, nodeObject } from '../tsl/TSLCore.js';
|
||||
|
||||
import { NoColorSpace, NoToneMapping } from '../../constants.js';
|
||||
import { ColorManagement } from '../../math/ColorManagement.js';
|
||||
|
||||
/**
|
||||
* Normally, tone mapping and color conversion happens automatically
|
||||
* before outputting pixel too the default (screen) framebuffer. In certain
|
||||
* post processing setups this happens to late because certain effects
|
||||
* require e.g. sRGB input. For such scenarios, `RenderOutputNode` can be used
|
||||
* to apply tone mapping and color space conversion at an arbitrary point
|
||||
* in the effect chain.
|
||||
*
|
||||
* When applying tone mapping and color space conversion manually with this node,
|
||||
* you have to set {@link PostProcessing#outputColorTransform} to `false`.
|
||||
*
|
||||
* ```js
|
||||
* const postProcessing = new PostProcessing( renderer );
|
||||
* postProcessing.outputColorTransform = false;
|
||||
*
|
||||
* const scenePass = pass( scene, camera );
|
||||
* const outputPass = renderOutput( scenePass );
|
||||
*
|
||||
* postProcessing.outputNode = outputPass;
|
||||
* ```
|
||||
*
|
||||
* @augments TempNode
|
||||
*/
|
||||
class RenderOutputNode extends TempNode {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'RenderOutputNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new render output node.
|
||||
*
|
||||
* @param {Node} colorNode - The color node to process.
|
||||
* @param {?number} toneMapping - The tone mapping type.
|
||||
* @param {?string} outputColorSpace - The output color space.
|
||||
*/
|
||||
constructor( colorNode, toneMapping, outputColorSpace ) {
|
||||
|
||||
super( 'vec4' );
|
||||
|
||||
/**
|
||||
* The color node to process.
|
||||
*
|
||||
* @type {Node}
|
||||
*/
|
||||
this.colorNode = colorNode;
|
||||
|
||||
/**
|
||||
* The tone mapping type.
|
||||
*
|
||||
* @type {?number}
|
||||
*/
|
||||
this.toneMapping = toneMapping;
|
||||
|
||||
/**
|
||||
* The output color space.
|
||||
*
|
||||
* @type {?string}
|
||||
*/
|
||||
this.outputColorSpace = outputColorSpace;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isRenderOutputNode = true;
|
||||
|
||||
}
|
||||
|
||||
setup( { context } ) {
|
||||
|
||||
let outputNode = this.colorNode || context.color;
|
||||
|
||||
// tone mapping
|
||||
|
||||
const toneMapping = ( this.toneMapping !== null ? this.toneMapping : context.toneMapping ) || NoToneMapping;
|
||||
const outputColorSpace = ( this.outputColorSpace !== null ? this.outputColorSpace : context.outputColorSpace ) || NoColorSpace;
|
||||
|
||||
if ( toneMapping !== NoToneMapping ) {
|
||||
|
||||
outputNode = outputNode.toneMapping( toneMapping );
|
||||
|
||||
}
|
||||
|
||||
// working to output color space
|
||||
|
||||
if ( outputColorSpace !== NoColorSpace && outputColorSpace !== ColorManagement.workingColorSpace ) {
|
||||
|
||||
outputNode = outputNode.workingToColorSpace( outputColorSpace );
|
||||
|
||||
}
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RenderOutputNode;
|
||||
|
||||
/**
|
||||
* TSL function for creating a posterize node.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node} color - The color node to process.
|
||||
* @param {?number} [toneMapping=null] - The tone mapping type.
|
||||
* @param {?string} [outputColorSpace=null] - The output color space.
|
||||
* @returns {RenderOutputNode}
|
||||
*/
|
||||
export const renderOutput = ( color, toneMapping = null, outputColorSpace = null ) => nodeObject( new RenderOutputNode( nodeObject( color ), toneMapping, outputColorSpace ) );
|
||||
|
||||
addMethodChaining( 'renderOutput', renderOutput );
|
||||
260
app/node_modules/three/src/nodes/display/ScreenNode.js
generated
vendored
Normal file
260
app/node_modules/three/src/nodes/display/ScreenNode.js
generated
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
import Node from '../core/Node.js';
|
||||
import { NodeUpdateType } from '../core/constants.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { Fn, nodeImmutable, vec2 } from '../tsl/TSLBase.js';
|
||||
|
||||
import { Vector2 } from '../../math/Vector2.js';
|
||||
import { Vector4 } from '../../math/Vector4.js';
|
||||
|
||||
let screenSizeVec, viewportVec;
|
||||
|
||||
/**
|
||||
* This node provides a collection of screen related metrics.
|
||||
* Depending on {@link ScreenNode#scope}, the nodes can represent
|
||||
* resolution or viewport data as well as fragment or uv coordinates.
|
||||
*
|
||||
* @augments Node
|
||||
*/
|
||||
class ScreenNode extends Node {
|
||||
|
||||
static get type() {
|
||||
|
||||
return 'ScreenNode';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new screen node.
|
||||
*
|
||||
* @param {('coordinate'|'viewport'|'size'|'uv')} scope - The node's scope.
|
||||
*/
|
||||
constructor( scope ) {
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* The node represents different metric depending on which scope is selected.
|
||||
*
|
||||
* - `ScreenNode.COORDINATE`: Window-relative coordinates of the current fragment according to WebGPU standards.
|
||||
* - `ScreenNode.VIEWPORT`: The current viewport defined as a four-dimensional vector.
|
||||
* - `ScreenNode.SIZE`: The dimensions of the current bound framebuffer.
|
||||
* - `ScreenNode.UV`: Normalized coordinates.
|
||||
*
|
||||
* @type {('coordinate'|'viewport'|'size'|'uv')}
|
||||
*/
|
||||
this.scope = scope;
|
||||
|
||||
/**
|
||||
* This flag can be used for type testing.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @default true
|
||||
*/
|
||||
this.isViewportNode = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node type depends on the selected scope.
|
||||
*
|
||||
* @return {('vec2'|'vec4')} The node type.
|
||||
*/
|
||||
getNodeType() {
|
||||
|
||||
if ( this.scope === ScreenNode.VIEWPORT ) return 'vec4';
|
||||
else return 'vec2';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is overwritten since the node's update type depends on the selected scope.
|
||||
*
|
||||
* @return {NodeUpdateType} The update type.
|
||||
*/
|
||||
getUpdateType() {
|
||||
|
||||
let updateType = NodeUpdateType.NONE;
|
||||
|
||||
if ( this.scope === ScreenNode.SIZE || this.scope === ScreenNode.VIEWPORT ) {
|
||||
|
||||
updateType = NodeUpdateType.RENDER;
|
||||
|
||||
}
|
||||
|
||||
this.updateType = updateType;
|
||||
|
||||
return updateType;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* `ScreenNode` implements {@link Node#update} to retrieve viewport and size information
|
||||
* from the current renderer.
|
||||
*
|
||||
* @param {NodeFrame} frame - A reference to the current node frame.
|
||||
*/
|
||||
update( { renderer } ) {
|
||||
|
||||
const renderTarget = renderer.getRenderTarget();
|
||||
|
||||
if ( this.scope === ScreenNode.VIEWPORT ) {
|
||||
|
||||
if ( renderTarget !== null ) {
|
||||
|
||||
viewportVec.copy( renderTarget.viewport );
|
||||
|
||||
} else {
|
||||
|
||||
renderer.getViewport( viewportVec );
|
||||
|
||||
viewportVec.multiplyScalar( renderer.getPixelRatio() );
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( renderTarget !== null ) {
|
||||
|
||||
screenSizeVec.width = renderTarget.width;
|
||||
screenSizeVec.height = renderTarget.height;
|
||||
|
||||
} else {
|
||||
|
||||
renderer.getDrawingBufferSize( screenSizeVec );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setup( /*builder*/ ) {
|
||||
|
||||
const scope = this.scope;
|
||||
|
||||
let output = null;
|
||||
|
||||
if ( scope === ScreenNode.SIZE ) {
|
||||
|
||||
output = uniform( screenSizeVec || ( screenSizeVec = new Vector2() ) );
|
||||
|
||||
} else if ( scope === ScreenNode.VIEWPORT ) {
|
||||
|
||||
output = uniform( viewportVec || ( viewportVec = new Vector4() ) );
|
||||
|
||||
} else {
|
||||
|
||||
output = vec2( screenCoordinate.div( screenSize ) );
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
generate( builder ) {
|
||||
|
||||
if ( this.scope === ScreenNode.COORDINATE ) {
|
||||
|
||||
let coord = builder.getFragCoord();
|
||||
|
||||
if ( builder.isFlipY() ) {
|
||||
|
||||
// follow webgpu standards
|
||||
|
||||
const size = builder.getNodeProperties( screenSize ).outputNode.build( builder );
|
||||
|
||||
coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ size }.y - ${ coord }.y )`;
|
||||
|
||||
}
|
||||
|
||||
return coord;
|
||||
|
||||
}
|
||||
|
||||
return super.generate( builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ScreenNode.COORDINATE = 'coordinate';
|
||||
ScreenNode.VIEWPORT = 'viewport';
|
||||
ScreenNode.SIZE = 'size';
|
||||
ScreenNode.UV = 'uv';
|
||||
|
||||
export default ScreenNode;
|
||||
|
||||
// Screen
|
||||
|
||||
/**
|
||||
* TSL object that represents normalized screen coordinates, unitless in `[0, 1]`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec2>}
|
||||
*/
|
||||
export const screenUV = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.UV );
|
||||
|
||||
/**
|
||||
* TSL object that represents the screen resolution in physical pixel units.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec2>}
|
||||
*/
|
||||
export const screenSize = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.SIZE );
|
||||
|
||||
/**
|
||||
* TSL object that represents the current `x`/`y` pixel position on the screen in physical pixel units.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec2>}
|
||||
*/
|
||||
export const screenCoordinate = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.COORDINATE );
|
||||
|
||||
// Viewport
|
||||
|
||||
/**
|
||||
* TSL object that represents the viewport rectangle as `x`, `y`, `width` and `height` in physical pixel units.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec4>}
|
||||
*/
|
||||
export const viewport = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.VIEWPORT );
|
||||
|
||||
/**
|
||||
* TSL object that represents the viewport resolution in physical pixel units.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec2>}
|
||||
*/
|
||||
export const viewportSize = viewport.zw;
|
||||
|
||||
/**
|
||||
* TSL object that represents the current `x`/`y` pixel position on the viewport in physical pixel units.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec2>}
|
||||
*/
|
||||
export const viewportCoordinate = /*@__PURE__*/ screenCoordinate.sub( viewport.xy );
|
||||
|
||||
/**
|
||||
* TSL object that represents normalized viewport coordinates, unitless in `[0, 1]`.
|
||||
*
|
||||
* @tsl
|
||||
* @type {ScreenNode<vec2>}
|
||||
*/
|
||||
export const viewportUV = /*@__PURE__*/ viewportCoordinate.div( viewportSize );
|
||||
|
||||
// Deprecated
|
||||
|
||||
/**
|
||||
* @deprecated since r169. Use {@link screenSize} instead.
|
||||
*/
|
||||
export const viewportResolution = /*@__PURE__*/ ( Fn( () => { // @deprecated, r169
|
||||
|
||||
console.warn( 'THREE.TSL: "viewportResolution" is deprecated. Use "screenSize" instead.' );
|
||||
|
||||
return screenSize;
|
||||
|
||||
}, 'vec2' ).once() )();
|
||||
242
app/node_modules/three/src/nodes/display/ToneMappingFunctions.js
generated
vendored
Normal file
242
app/node_modules/three/src/nodes/display/ToneMappingFunctions.js
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
import { Fn, float, mat3, vec3, If } from '../tsl/TSLBase.js';
|
||||
import { select } from '../math/ConditionalNode.js';
|
||||
import { clamp, log2, max, min, pow, mix } from '../math/MathNode.js';
|
||||
import { mul, sub, div } from '../math/OperatorNode.js';
|
||||
|
||||
/**
|
||||
* Linear tone mapping, exposure only.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color that should be tone mapped.
|
||||
* @param {Node<float>} exposure - The exposure.
|
||||
* @return {Node<vec3>} The tone mapped color.
|
||||
*/
|
||||
export const linearToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => {
|
||||
|
||||
return color.mul( exposure ).clamp();
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'linearToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Reinhard tone mapping.
|
||||
*
|
||||
* Reference: {@link https://www.cs.utah.edu/docs/techreports/2002/pdf/UUCS-02-001.pdf}
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color that should be tone mapped.
|
||||
* @param {Node<float>} exposure - The exposure.
|
||||
* @return {Node<vec3>} The tone mapped color.
|
||||
*/
|
||||
export const reinhardToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => {
|
||||
|
||||
color = color.mul( exposure );
|
||||
|
||||
return color.div( color.add( 1.0 ) ).clamp();
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'reinhardToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Cineon tone mapping.
|
||||
*
|
||||
* Reference: {@link http://filmicworlds.com/blog/filmic-tonemapping-operators/}
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color that should be tone mapped.
|
||||
* @param {Node<float>} exposure - The exposure.
|
||||
* @return {Node<vec3>} The tone mapped color.
|
||||
*/
|
||||
export const cineonToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => {
|
||||
|
||||
// filmic operator by Jim Hejl and Richard Burgess-Dawson
|
||||
color = color.mul( exposure );
|
||||
color = color.sub( 0.004 ).max( 0.0 );
|
||||
|
||||
const a = color.mul( color.mul( 6.2 ).add( 0.5 ) );
|
||||
const b = color.mul( color.mul( 6.2 ).add( 1.7 ) ).add( 0.06 );
|
||||
|
||||
return a.div( b ).pow( 2.2 );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'cineonToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
|
||||
// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs
|
||||
|
||||
const RRTAndODTFit = /*@__PURE__*/ Fn( ( [ color ] ) => {
|
||||
|
||||
const a = color.mul( color.add( 0.0245786 ) ).sub( 0.000090537 );
|
||||
const b = color.mul( color.add( 0.4329510 ).mul( 0.983729 ) ).add( 0.238081 );
|
||||
|
||||
return a.div( b );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* ACESFilmic tone mapping.
|
||||
*
|
||||
* Reference: {@link https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs}
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color that should be tone mapped.
|
||||
* @param {Node<float>} exposure - The exposure.
|
||||
* @return {Node<vec3>} The tone mapped color.
|
||||
*/
|
||||
export const acesFilmicToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => {
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const ACESInputMat = mat3(
|
||||
0.59719, 0.35458, 0.04823,
|
||||
0.07600, 0.90834, 0.01566,
|
||||
0.02840, 0.13383, 0.83777
|
||||
);
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const ACESOutputMat = mat3(
|
||||
1.60475, - 0.53108, - 0.07367,
|
||||
- 0.10208, 1.10813, - 0.00605,
|
||||
- 0.00327, - 0.07276, 1.07602
|
||||
);
|
||||
|
||||
color = color.mul( exposure ).div( 0.6 );
|
||||
|
||||
color = ACESInputMat.mul( color );
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit( color );
|
||||
|
||||
color = ACESOutputMat.mul( color );
|
||||
|
||||
// Clamp to [0, 1]
|
||||
return color.clamp();
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'acesFilmicToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
|
||||
const LINEAR_REC2020_TO_LINEAR_SRGB = /*@__PURE__*/ mat3( vec3( 1.6605, - 0.1246, - 0.0182 ), vec3( - 0.5876, 1.1329, - 0.1006 ), vec3( - 0.0728, - 0.0083, 1.1187 ) );
|
||||
const LINEAR_SRGB_TO_LINEAR_REC2020 = /*@__PURE__*/ mat3( vec3( 0.6274, 0.0691, 0.0164 ), vec3( 0.3293, 0.9195, 0.0880 ), vec3( 0.0433, 0.0113, 0.8956 ) );
|
||||
|
||||
const agxDefaultContrastApprox = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => {
|
||||
|
||||
const x = vec3( x_immutable ).toVar();
|
||||
const x2 = vec3( x.mul( x ) ).toVar();
|
||||
const x4 = vec3( x2.mul( x2 ) ).toVar();
|
||||
|
||||
return float( 15.5 ).mul( x4.mul( x2 ) ).sub( mul( 40.14, x4.mul( x ) ) ).add( mul( 31.96, x4 ).sub( mul( 6.868, x2.mul( x ) ) ).add( mul( 0.4298, x2 ).add( mul( 0.1191, x ).sub( 0.00232 ) ) ) );
|
||||
|
||||
} );
|
||||
|
||||
/**
|
||||
* AgX tone mapping.
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color that should be tone mapped.
|
||||
* @param {Node<float>} exposure - The exposure.
|
||||
* @return {Node<vec3>} The tone mapped color.
|
||||
*/
|
||||
export const agxToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => {
|
||||
|
||||
const colortone = vec3( color ).toVar();
|
||||
const AgXInsetMatrix = mat3( vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) );
|
||||
const AgXOutsetMatrix = mat3( vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) );
|
||||
const AgxMinEv = float( - 12.47393 );
|
||||
const AgxMaxEv = float( 4.026069 );
|
||||
colortone.mulAssign( exposure );
|
||||
colortone.assign( LINEAR_SRGB_TO_LINEAR_REC2020.mul( colortone ) );
|
||||
colortone.assign( AgXInsetMatrix.mul( colortone ) );
|
||||
colortone.assign( max( colortone, 1e-10 ) );
|
||||
colortone.assign( log2( colortone ) );
|
||||
colortone.assign( colortone.sub( AgxMinEv ).div( AgxMaxEv.sub( AgxMinEv ) ) );
|
||||
colortone.assign( clamp( colortone, 0.0, 1.0 ) );
|
||||
colortone.assign( agxDefaultContrastApprox( colortone ) );
|
||||
colortone.assign( AgXOutsetMatrix.mul( colortone ) );
|
||||
colortone.assign( pow( max( vec3( 0.0 ), colortone ), vec3( 2.2 ) ) );
|
||||
colortone.assign( LINEAR_REC2020_TO_LINEAR_SRGB.mul( colortone ) );
|
||||
colortone.assign( clamp( colortone, 0.0, 1.0 ) );
|
||||
|
||||
return colortone;
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'agxToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
|
||||
/**
|
||||
* Neutral tone mapping.
|
||||
*
|
||||
* Reference: {@link https://modelviewer.dev/examples/tone-mapping}
|
||||
*
|
||||
* @tsl
|
||||
* @function
|
||||
* @param {Node<vec3>} color - The color that should be tone mapped.
|
||||
* @param {Node<float>} exposure - The exposure.
|
||||
* @return {Node<vec3>} The tone mapped color.
|
||||
*/
|
||||
export const neutralToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => {
|
||||
|
||||
const StartCompression = float( 0.8 - 0.04 );
|
||||
const Desaturation = float( 0.15 );
|
||||
|
||||
color = color.mul( exposure );
|
||||
|
||||
const x = min( color.r, min( color.g, color.b ) );
|
||||
const offset = select( x.lessThan( 0.08 ), x.sub( mul( 6.25, x.mul( x ) ) ), 0.04 );
|
||||
|
||||
color.subAssign( offset );
|
||||
|
||||
const peak = max( color.r, max( color.g, color.b ) );
|
||||
|
||||
If( peak.lessThan( StartCompression ), () => {
|
||||
|
||||
return color;
|
||||
|
||||
} );
|
||||
|
||||
const d = sub( 1, StartCompression );
|
||||
const newPeak = sub( 1, d.mul( d ).div( peak.add( d.sub( StartCompression ) ) ) );
|
||||
color.mulAssign( newPeak.div( peak ) );
|
||||
const g = sub( 1, div( 1, Desaturation.mul( peak.sub( newPeak ) ).add( 1 ) ) );
|
||||
|
||||
return mix( color, vec3( newPeak ), g );
|
||||
|
||||
} ).setLayout( {
|
||||
name: 'neutralToneMapping',
|
||||
type: 'vec3',
|
||||
inputs: [
|
||||
{ name: 'color', type: 'vec3' },
|
||||
{ name: 'exposure', type: 'float' }
|
||||
]
|
||||
} );
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user