super-three 0.169.1 → 0.170.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/three.cjs +974 -562
- package/build/three.module.js +975 -559
- package/build/three.module.min.js +1 -1
- package/build/three.webgpu.js +8398 -9842
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +8398 -9842
- package/build/three.webgpu.nodes.min.js +1 -1
- package/examples/jsm/Addons.js +3 -3
- package/examples/jsm/animation/MMDAnimationHelper.js +2 -0
- package/examples/jsm/animation/MMDPhysics.js +2 -0
- package/examples/jsm/controls/TransformControls.js +22 -6
- package/examples/jsm/csm/CSM.js +2 -2
- package/examples/jsm/csm/CSMFrustum.js +7 -4
- package/examples/jsm/csm/CSMHelper.js +2 -0
- package/examples/jsm/csm/CSMShadowNode.js +435 -0
- package/examples/jsm/curves/NURBSCurve.js +34 -3
- package/examples/jsm/exporters/GLTFExporter.js +138 -71
- package/examples/jsm/exporters/KTX2Exporter.js +35 -12
- package/examples/jsm/exporters/MMDExporter.js +6 -0
- package/examples/jsm/exporters/USDZExporter.js +21 -3
- package/examples/jsm/geometries/DecalGeometry.js +65 -20
- package/examples/jsm/geometries/InstancedPointsGeometry.js +2 -0
- package/examples/jsm/helpers/TextureHelperGPU.js +175 -0
- package/examples/jsm/interactive/HTMLMesh.js +1 -0
- package/examples/jsm/lighting/TiledLighting.js +18 -0
- package/examples/jsm/lights/RectAreaLightTexturesLib.js +1 -1
- package/examples/jsm/lines/LineMaterial.js +7 -2
- package/examples/jsm/lines/LineSegmentsGeometry.js +2 -0
- package/examples/jsm/lines/webgpu/LineSegments2.js +0 -15
- package/examples/jsm/lines/webgpu/Wireframe.js +56 -0
- package/examples/jsm/loaders/3DMLoader.js +1 -0
- package/examples/jsm/loaders/3MFLoader.js +91 -0
- package/examples/jsm/loaders/FBXLoader.js +12 -2
- package/examples/jsm/loaders/GLTFLoader.js +2 -0
- package/examples/jsm/loaders/KTX2Loader.js +140 -49
- package/examples/jsm/loaders/LDrawLoader.js +22 -136
- package/examples/jsm/loaders/LottieLoader.js +1 -0
- package/examples/jsm/loaders/MMDLoader.js +9 -2
- package/examples/jsm/materials/LDrawConditionalLineMaterial.js +143 -0
- package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +114 -0
- package/examples/jsm/materials/MeshGouraudMaterial.js +6 -2
- package/examples/jsm/math/ColorSpaces.js +76 -0
- package/examples/jsm/misc/ProgressiveLightMap.js +52 -40
- package/examples/jsm/misc/ProgressiveLightMapGPU.js +293 -0
- package/examples/jsm/misc/VolumeSlice.js +1 -0
- package/examples/jsm/objects/WaterMesh.js +8 -8
- package/examples/jsm/postprocessing/AfterimagePass.js +14 -3
- package/examples/jsm/postprocessing/SSRPass.js +6 -0
- package/examples/jsm/renderers/CSS2DRenderer.js +6 -3
- package/examples/jsm/renderers/CSS3DRenderer.js +7 -4
- package/examples/jsm/shaders/FXAAShader.js +225 -224
- package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
- package/{src/nodes → examples/jsm/tsl}/display/AfterImageNode.js +17 -20
- package/{src/nodes → examples/jsm/tsl}/display/AnaglyphPassNode.js +2 -6
- package/{src/nodes → examples/jsm/tsl}/display/AnamorphicNode.js +12 -18
- package/{src/nodes → examples/jsm/tsl}/display/BleachBypass.js +1 -3
- package/{src/nodes → examples/jsm/tsl}/display/BloomNode.js +11 -40
- package/{src/nodes → examples/jsm/tsl}/display/DenoiseNode.js +18 -41
- package/{src/nodes → examples/jsm/tsl}/display/DepthOfFieldNode.js +2 -8
- package/{src/nodes → examples/jsm/tsl}/display/DotScreenNode.js +2 -9
- package/examples/jsm/tsl/display/FXAANode.js +316 -0
- package/{src/nodes → examples/jsm/tsl}/display/FilmNode.js +2 -6
- package/{src/nodes → examples/jsm/tsl}/display/GTAONode.js +30 -70
- package/{src/nodes → examples/jsm/tsl}/display/GaussianBlurNode.js +74 -36
- package/examples/jsm/tsl/display/LensflareNode.js +161 -0
- package/{src/nodes → examples/jsm/tsl}/display/Lut3DNode.js +1 -4
- package/{src/nodes → examples/jsm/tsl}/display/MotionBlur.js +2 -3
- package/examples/jsm/tsl/display/OutlineNode.js +434 -0
- package/{src/nodes → examples/jsm/tsl}/display/ParallaxBarrierPassNode.js +1 -5
- package/{src/nodes → examples/jsm/tsl}/display/PixelationPassNode.js +3 -15
- package/{src/nodes → examples/jsm/tsl}/display/RGBShiftNode.js +1 -6
- package/examples/jsm/tsl/display/SMAANode.js +620 -0
- package/{src/nodes → examples/jsm/tsl}/display/SSAAPassNode.js +10 -25
- package/examples/jsm/tsl/display/SSRNode.js +343 -0
- package/{src/nodes → examples/jsm/tsl}/display/Sepia.js +1 -2
- package/{src/nodes → examples/jsm/tsl}/display/SobelOperatorNode.js +3 -11
- package/{src/nodes → examples/jsm/tsl}/display/StereoCompositePassNode.js +9 -11
- package/{src/nodes → examples/jsm/tsl}/display/StereoPassNode.js +10 -11
- package/examples/jsm/tsl/display/TRAAPassNode.js +355 -0
- package/{src/nodes → examples/jsm/tsl}/display/TransitionNode.js +1 -6
- package/examples/jsm/tsl/display/hashBlur.js +24 -0
- package/examples/jsm/tsl/lighting/TiledLightsNode.js +392 -0
- package/examples/jsm/utils/{TextureUtilsGPU.js → WebGPUTextureUtils.js} +2 -1
- package/examples/jsm/webxr/OculusHandPointerModel.js +21 -21
- package/examples/jsm/webxr/Text2D.js +6 -6
- package/package.json +2 -2
- package/src/Three.WebGPU.Nodes.js +4 -0
- package/src/Three.WebGPU.js +4 -0
- package/src/constants.js +1 -6
- package/src/core/BufferGeometry.js +44 -6
- package/src/geometries/CylinderGeometry.js +2 -2
- package/src/materials/LineBasicMaterial.js +6 -2
- package/src/materials/LineDashedMaterial.js +6 -2
- package/src/materials/Material.js +14 -1
- package/src/materials/MeshBasicMaterial.js +6 -2
- package/src/materials/MeshDepthMaterial.js +6 -2
- package/src/materials/MeshDistanceMaterial.js +6 -2
- package/src/materials/MeshLambertMaterial.js +6 -2
- package/src/materials/MeshMatcapMaterial.js +6 -2
- package/src/materials/MeshNormalMaterial.js +6 -2
- package/src/materials/MeshPhongMaterial.js +6 -2
- package/src/materials/MeshPhysicalMaterial.js +6 -2
- package/src/materials/MeshStandardMaterial.js +6 -2
- package/src/materials/MeshToonMaterial.js +6 -2
- package/src/materials/PointsMaterial.js +6 -2
- package/src/materials/RawShaderMaterial.js +6 -2
- package/src/materials/ShaderMaterial.js +6 -2
- package/src/materials/ShadowMaterial.js +6 -2
- package/src/materials/SpriteMaterial.js +6 -2
- package/src/materials/nodes/NodeMaterial.js +31 -9
- package/src/materials/nodes/SpriteNodeMaterial.js +11 -2
- package/src/materials/nodes/manager/NodeMaterialObserver.js +111 -2
- package/src/math/ColorManagement.js +118 -85
- package/src/math/Vector4.js +11 -0
- package/src/nodes/Nodes.js +1 -21
- package/src/nodes/TSL.js +6 -24
- package/src/nodes/accessors/Camera.js +0 -1
- package/src/nodes/accessors/SceneNode.js +35 -1
- package/src/nodes/accessors/StorageBufferNode.js +32 -10
- package/src/nodes/accessors/VelocityNode.js +13 -3
- package/src/nodes/code/FunctionCallNode.js +16 -5
- package/src/nodes/code/ScriptableNode.js +4 -4
- package/src/nodes/core/Node.js +1 -0
- package/src/nodes/core/NodeBuilder.js +29 -5
- package/src/nodes/core/VarNode.js +15 -3
- package/src/nodes/display/ColorAdjustment.js +53 -4
- package/src/nodes/display/ColorSpaceFunctions.js +5 -5
- package/src/nodes/display/ColorSpaceNode.js +27 -39
- package/src/nodes/display/PassNode.js +6 -4
- package/src/nodes/display/ToneMappingNode.js +1 -1
- package/src/nodes/display/ViewportDepthNode.js +33 -1
- package/src/nodes/functions/PhysicalLightingModel.js +21 -15
- package/src/nodes/functions/material/getAlphaHashThreshold.js +64 -0
- package/src/nodes/functions/material/getGeometryRoughness.js +8 -2
- package/src/nodes/functions/material/getParallaxCorrectNormal.js +22 -0
- package/src/nodes/gpgpu/ComputeNode.js +9 -1
- package/src/nodes/lighting/AnalyticLightNode.js +12 -416
- package/src/nodes/lighting/LightsNode.js +24 -12
- package/src/nodes/lighting/PointLightNode.js +36 -26
- package/src/nodes/lighting/RectAreaLightNode.js +3 -0
- package/src/nodes/lighting/ShadowNode.js +484 -0
- package/src/nodes/utils/LoopNode.js +2 -2
- package/src/nodes/utils/Oscillators.js +6 -0
- package/src/nodes/utils/PostProcessingUtils.js +89 -0
- package/src/nodes/utils/ReflectorNode.js +101 -15
- package/src/nodes/utils/Timer.js +29 -0
- package/src/objects/BatchedMesh.js +458 -241
- package/src/renderers/WebGLRenderer.js +120 -117
- package/src/renderers/common/Attributes.js +4 -0
- package/src/renderers/common/Backend.js +2 -0
- package/src/renderers/common/Background.js +14 -4
- package/src/renderers/common/Bindings.js +3 -2
- package/src/renderers/common/Constants.js +2 -1
- package/src/renderers/common/Geometries.js +20 -0
- package/src/renderers/common/IndirectStorageBufferAttribute.js +15 -0
- package/src/renderers/common/Lighting.js +45 -0
- package/src/renderers/common/PostProcessingUtils.js +86 -0
- package/src/renderers/common/RenderList.js +39 -11
- package/src/renderers/common/RenderLists.js +4 -2
- package/src/renderers/common/RenderObject.js +18 -1
- package/src/renderers/common/Renderer.js +165 -26
- package/src/renderers/common/Textures.js +30 -14
- package/src/renderers/common/nodes/NodeLibrary.js +1 -14
- package/src/renderers/common/nodes/Nodes.js +2 -2
- package/src/renderers/shaders/ShaderChunk/colorspace_pars_fragment.glsl.js +4 -24
- package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +8 -0
- package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +2 -2
- package/src/renderers/webgl/WebGLBufferRenderer.js +2 -6
- package/src/renderers/webgl/WebGLCapabilities.js +0 -7
- package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +2 -6
- package/src/renderers/webgl/WebGLProgram.js +24 -28
- package/src/renderers/webgl/WebGLPrograms.js +5 -2
- package/src/renderers/webgl/WebGLState.js +37 -1
- package/src/renderers/webgl/WebGLTextures.js +29 -12
- package/src/renderers/webgl-fallback/WebGLBackend.js +98 -31
- package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +2 -7
- package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +33 -8
- package/src/renderers/webgpu/WebGPUBackend.js +105 -25
- package/src/renderers/webgpu/WebGPURenderer.Nodes.js +1 -1
- package/src/renderers/webgpu/WebGPURenderer.js +1 -1
- package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +0 -8
- package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +0 -8
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +10 -20
- package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +12 -4
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +29 -9
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +24 -6
- package/src/renderers/webgpu/utils/WebGPUUtils.js +0 -1
- package/src/renderers/webxr/WebXRManager.js +4 -4
- package/examples/jsm/cameras/CinematicCamera.js +0 -208
- package/src/nodes/display/FXAANode.js +0 -332
- package/src/nodes/utils/OscNode.js +0 -85
- package/src/nodes/utils/TimerNode.js +0 -97
- /package/examples/jsm/utils/{TextureUtils.js → WebGLTextureUtils.js} +0 -0
|
@@ -3,7 +3,35 @@ import { getDistanceAttenuation } from './LightUtils.js';
|
|
|
3
3
|
import { uniform } from '../core/UniformNode.js';
|
|
4
4
|
import { lightViewPosition } from '../accessors/Lights.js';
|
|
5
5
|
import { positionView } from '../accessors/Position.js';
|
|
6
|
-
import {
|
|
6
|
+
import { Fn } from '../tsl/TSLBase.js';
|
|
7
|
+
import { renderGroup } from '../core/UniformGroupNode.js';
|
|
8
|
+
|
|
9
|
+
export const directPointLight = Fn( ( { color, lightViewPosition, cutoffDistance, decayExponent }, builder ) => {
|
|
10
|
+
|
|
11
|
+
const lightingModel = builder.context.lightingModel;
|
|
12
|
+
|
|
13
|
+
const lVector = lightViewPosition.sub( positionView ); // @TODO: Add it into LightNode
|
|
14
|
+
|
|
15
|
+
const lightDirection = lVector.normalize();
|
|
16
|
+
const lightDistance = lVector.length();
|
|
17
|
+
|
|
18
|
+
const lightAttenuation = getDistanceAttenuation( {
|
|
19
|
+
lightDistance,
|
|
20
|
+
cutoffDistance,
|
|
21
|
+
decayExponent
|
|
22
|
+
} );
|
|
23
|
+
|
|
24
|
+
const lightColor = color.mul( lightAttenuation );
|
|
25
|
+
|
|
26
|
+
const reflectedLight = builder.context.reflectedLight;
|
|
27
|
+
|
|
28
|
+
lightingModel.direct( {
|
|
29
|
+
lightDirection,
|
|
30
|
+
lightColor,
|
|
31
|
+
reflectedLight
|
|
32
|
+
}, builder.stack, builder );
|
|
33
|
+
|
|
34
|
+
} );
|
|
7
35
|
|
|
8
36
|
class PointLightNode extends AnalyticLightNode {
|
|
9
37
|
|
|
@@ -33,32 +61,14 @@ class PointLightNode extends AnalyticLightNode {
|
|
|
33
61
|
|
|
34
62
|
}
|
|
35
63
|
|
|
36
|
-
setup(
|
|
37
|
-
|
|
38
|
-
const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this;
|
|
39
|
-
|
|
40
|
-
const lightingModel = builder.context.lightingModel;
|
|
41
|
-
|
|
42
|
-
const lVector = lightViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode
|
|
43
|
-
|
|
44
|
-
const lightDirection = lVector.normalize();
|
|
45
|
-
const lightDistance = lVector.length();
|
|
46
|
-
|
|
47
|
-
const lightAttenuation = getDistanceAttenuation( {
|
|
48
|
-
lightDistance,
|
|
49
|
-
cutoffDistance: cutoffDistanceNode,
|
|
50
|
-
decayExponent: decayExponentNode
|
|
51
|
-
} );
|
|
52
|
-
|
|
53
|
-
const lightColor = colorNode.mul( lightAttenuation );
|
|
54
|
-
|
|
55
|
-
const reflectedLight = builder.context.reflectedLight;
|
|
64
|
+
setup() {
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
directPointLight( {
|
|
67
|
+
color: this.colorNode,
|
|
68
|
+
lightViewPosition: lightViewPosition( this.light ),
|
|
69
|
+
cutoffDistance: this.cutoffDistanceNode,
|
|
70
|
+
decayExponent: this.decayExponentNode
|
|
71
|
+
} ).append();
|
|
62
72
|
|
|
63
73
|
}
|
|
64
74
|
|
|
@@ -6,6 +6,7 @@ import { renderGroup } from '../core/UniformGroupNode.js';
|
|
|
6
6
|
|
|
7
7
|
import { Matrix4 } from '../../math/Matrix4.js';
|
|
8
8
|
import { Vector3 } from '../../math/Vector3.js';
|
|
9
|
+
import { NodeUpdateType } from '../core/constants.js';
|
|
9
10
|
|
|
10
11
|
const _matrix41 = /*@__PURE__*/ new Matrix4();
|
|
11
12
|
const _matrix42 = /*@__PURE__*/ new Matrix4();
|
|
@@ -27,6 +28,8 @@ class RectAreaLightNode extends AnalyticLightNode {
|
|
|
27
28
|
this.halfHeight = uniform( new Vector3() ).setGroup( renderGroup );
|
|
28
29
|
this.halfWidth = uniform( new Vector3() ).setGroup( renderGroup );
|
|
29
30
|
|
|
31
|
+
this.updateType = NodeUpdateType.RENDER;
|
|
32
|
+
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
update( frame ) {
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import Node from '../core/Node.js';
|
|
2
|
+
import { NodeUpdateType } from '../core/constants.js';
|
|
3
|
+
import { uniform } from '../core/UniformNode.js';
|
|
4
|
+
import { float, vec2, vec3, vec4, If, int, Fn, nodeObject } from '../tsl/TSLBase.js';
|
|
5
|
+
import { reference } from '../accessors/ReferenceNode.js';
|
|
6
|
+
import { texture } from '../accessors/TextureNode.js';
|
|
7
|
+
import { positionWorld } from '../accessors/Position.js';
|
|
8
|
+
import { transformedNormalWorld } from '../accessors/Normal.js';
|
|
9
|
+
import { mix, fract, step, max, clamp, sqrt } from '../math/MathNode.js';
|
|
10
|
+
import { add, sub } from '../math/OperatorNode.js';
|
|
11
|
+
import { DepthTexture } from '../../textures/DepthTexture.js';
|
|
12
|
+
import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
|
|
13
|
+
import QuadMesh from '../../renderers/common/QuadMesh.js';
|
|
14
|
+
import { Loop } from '../utils/LoopNode.js';
|
|
15
|
+
import { screenCoordinate } from '../display/ScreenNode.js';
|
|
16
|
+
import { HalfFloatType, LessCompare, RGFormat, VSMShadowMap, WebGPUCoordinateSystem } from '../../constants.js';
|
|
17
|
+
import { renderGroup } from '../core/UniformGroupNode.js';
|
|
18
|
+
import { perspectiveDepthToLogarithmicDepth } from '../display/ViewportDepthNode.js';
|
|
19
|
+
|
|
20
|
+
const BasicShadowMap = Fn( ( { depthTexture, shadowCoord } ) => {
|
|
21
|
+
|
|
22
|
+
return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z );
|
|
23
|
+
|
|
24
|
+
} );
|
|
25
|
+
|
|
26
|
+
const PCFShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => {
|
|
27
|
+
|
|
28
|
+
const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
|
|
29
|
+
|
|
30
|
+
const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
|
|
31
|
+
const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
|
|
32
|
+
|
|
33
|
+
const texelSize = vec2( 1 ).div( mapSize );
|
|
34
|
+
const dx0 = texelSize.x.negate().mul( radius );
|
|
35
|
+
const dy0 = texelSize.y.negate().mul( radius );
|
|
36
|
+
const dx1 = texelSize.x.mul( radius );
|
|
37
|
+
const dy1 = texelSize.y.mul( radius );
|
|
38
|
+
const dx2 = dx0.div( 2 );
|
|
39
|
+
const dy2 = dy0.div( 2 );
|
|
40
|
+
const dx3 = dx1.div( 2 );
|
|
41
|
+
const dy3 = dy1.div( 2 );
|
|
42
|
+
|
|
43
|
+
return add(
|
|
44
|
+
depthCompare( shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ),
|
|
45
|
+
depthCompare( shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ),
|
|
46
|
+
depthCompare( shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ),
|
|
47
|
+
depthCompare( shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ),
|
|
48
|
+
depthCompare( shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ),
|
|
49
|
+
depthCompare( shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ),
|
|
50
|
+
depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ),
|
|
51
|
+
depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ),
|
|
52
|
+
depthCompare( shadowCoord.xy, shadowCoord.z ),
|
|
53
|
+
depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ),
|
|
54
|
+
depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ),
|
|
55
|
+
depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ),
|
|
56
|
+
depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ),
|
|
57
|
+
depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ),
|
|
58
|
+
depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ),
|
|
59
|
+
depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
|
|
60
|
+
depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
|
|
61
|
+
).mul( 1 / 17 );
|
|
62
|
+
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
const PCFSoftShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => {
|
|
66
|
+
|
|
67
|
+
const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
|
|
68
|
+
|
|
69
|
+
const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
|
|
70
|
+
|
|
71
|
+
const texelSize = vec2( 1 ).div( mapSize );
|
|
72
|
+
const dx = texelSize.x;
|
|
73
|
+
const dy = texelSize.y;
|
|
74
|
+
|
|
75
|
+
const uv = shadowCoord.xy;
|
|
76
|
+
const f = fract( uv.mul( mapSize ).add( 0.5 ) );
|
|
77
|
+
uv.subAssign( f.mul( texelSize ) );
|
|
78
|
+
|
|
79
|
+
return add(
|
|
80
|
+
depthCompare( uv, shadowCoord.z ),
|
|
81
|
+
depthCompare( uv.add( vec2( dx, 0 ) ), shadowCoord.z ),
|
|
82
|
+
depthCompare( uv.add( vec2( 0, dy ) ), shadowCoord.z ),
|
|
83
|
+
depthCompare( uv.add( texelSize ), shadowCoord.z ),
|
|
84
|
+
mix(
|
|
85
|
+
depthCompare( uv.add( vec2( dx.negate(), 0 ) ), shadowCoord.z ),
|
|
86
|
+
depthCompare( uv.add( vec2( dx.mul( 2 ), 0 ) ), shadowCoord.z ),
|
|
87
|
+
f.x
|
|
88
|
+
),
|
|
89
|
+
mix(
|
|
90
|
+
depthCompare( uv.add( vec2( dx.negate(), dy ) ), shadowCoord.z ),
|
|
91
|
+
depthCompare( uv.add( vec2( dx.mul( 2 ), dy ) ), shadowCoord.z ),
|
|
92
|
+
f.x
|
|
93
|
+
),
|
|
94
|
+
mix(
|
|
95
|
+
depthCompare( uv.add( vec2( 0, dy.negate() ) ), shadowCoord.z ),
|
|
96
|
+
depthCompare( uv.add( vec2( 0, dy.mul( 2 ) ) ), shadowCoord.z ),
|
|
97
|
+
f.y
|
|
98
|
+
),
|
|
99
|
+
mix(
|
|
100
|
+
depthCompare( uv.add( vec2( dx, dy.negate() ) ), shadowCoord.z ),
|
|
101
|
+
depthCompare( uv.add( vec2( dx, dy.mul( 2 ) ) ), shadowCoord.z ),
|
|
102
|
+
f.y
|
|
103
|
+
),
|
|
104
|
+
mix(
|
|
105
|
+
mix(
|
|
106
|
+
depthCompare( uv.add( vec2( dx.negate(), dy.negate() ) ), shadowCoord.z ),
|
|
107
|
+
depthCompare( uv.add( vec2( dx.mul( 2 ), dy.negate() ) ), shadowCoord.z ),
|
|
108
|
+
f.x
|
|
109
|
+
),
|
|
110
|
+
mix(
|
|
111
|
+
depthCompare( uv.add( vec2( dx.negate(), dy.mul( 2 ) ) ), shadowCoord.z ),
|
|
112
|
+
depthCompare( uv.add( vec2( dx.mul( 2 ), dy.mul( 2 ) ) ), shadowCoord.z ),
|
|
113
|
+
f.x
|
|
114
|
+
),
|
|
115
|
+
f.y
|
|
116
|
+
)
|
|
117
|
+
).mul( 1 / 9 );
|
|
118
|
+
|
|
119
|
+
} );
|
|
120
|
+
|
|
121
|
+
// VSM
|
|
122
|
+
|
|
123
|
+
const VSMShadowMapNode = Fn( ( { depthTexture, shadowCoord } ) => {
|
|
124
|
+
|
|
125
|
+
const occlusion = float( 1 ).toVar();
|
|
126
|
+
|
|
127
|
+
const distribution = texture( depthTexture ).uv( shadowCoord.xy ).rg;
|
|
128
|
+
|
|
129
|
+
const hardShadow = step( shadowCoord.z, distribution.x );
|
|
130
|
+
|
|
131
|
+
If( hardShadow.notEqual( float( 1.0 ) ), () => {
|
|
132
|
+
|
|
133
|
+
const distance = shadowCoord.z.sub( distribution.x );
|
|
134
|
+
const variance = max( 0, distribution.y.mul( distribution.y ) );
|
|
135
|
+
let softnessProbability = variance.div( variance.add( distance.mul( distance ) ) ); // Chebeyshevs inequality
|
|
136
|
+
softnessProbability = clamp( sub( softnessProbability, 0.3 ).div( 0.95 - 0.3 ) );
|
|
137
|
+
occlusion.assign( clamp( max( hardShadow, softnessProbability ) ) );
|
|
138
|
+
|
|
139
|
+
} );
|
|
140
|
+
|
|
141
|
+
return occlusion;
|
|
142
|
+
|
|
143
|
+
} );
|
|
144
|
+
|
|
145
|
+
const VSMPassVertical = Fn( ( { samples, radius, size, shadowPass } ) => {
|
|
146
|
+
|
|
147
|
+
const mean = float( 0 ).toVar();
|
|
148
|
+
const squaredMean = float( 0 ).toVar();
|
|
149
|
+
|
|
150
|
+
const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) );
|
|
151
|
+
const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) );
|
|
152
|
+
|
|
153
|
+
Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => {
|
|
154
|
+
|
|
155
|
+
const uvOffset = uvStart.add( float( i ).mul( uvStride ) );
|
|
156
|
+
|
|
157
|
+
const depth = shadowPass.uv( add( screenCoordinate.xy, vec2( 0, uvOffset ).mul( radius ) ).div( size ) ).x;
|
|
158
|
+
mean.addAssign( depth );
|
|
159
|
+
squaredMean.addAssign( depth.mul( depth ) );
|
|
160
|
+
|
|
161
|
+
} );
|
|
162
|
+
|
|
163
|
+
mean.divAssign( samples );
|
|
164
|
+
squaredMean.divAssign( samples );
|
|
165
|
+
|
|
166
|
+
const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) );
|
|
167
|
+
return vec2( mean, std_dev );
|
|
168
|
+
|
|
169
|
+
} );
|
|
170
|
+
|
|
171
|
+
const VSMPassHorizontal = Fn( ( { samples, radius, size, shadowPass } ) => {
|
|
172
|
+
|
|
173
|
+
const mean = float( 0 ).toVar();
|
|
174
|
+
const squaredMean = float( 0 ).toVar();
|
|
175
|
+
|
|
176
|
+
const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) );
|
|
177
|
+
const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) );
|
|
178
|
+
|
|
179
|
+
Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => {
|
|
180
|
+
|
|
181
|
+
const uvOffset = uvStart.add( float( i ).mul( uvStride ) );
|
|
182
|
+
|
|
183
|
+
const distribution = shadowPass.uv( add( screenCoordinate.xy, vec2( uvOffset, 0 ).mul( radius ) ).div( size ) );
|
|
184
|
+
mean.addAssign( distribution.x );
|
|
185
|
+
squaredMean.addAssign( add( distribution.y.mul( distribution.y ), distribution.x.mul( distribution.x ) ) );
|
|
186
|
+
|
|
187
|
+
} );
|
|
188
|
+
|
|
189
|
+
mean.divAssign( samples );
|
|
190
|
+
squaredMean.divAssign( samples );
|
|
191
|
+
|
|
192
|
+
const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) );
|
|
193
|
+
return vec2( mean, std_dev );
|
|
194
|
+
|
|
195
|
+
} );
|
|
196
|
+
|
|
197
|
+
const _shadowFilterLib = [ BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, VSMShadowMapNode ];
|
|
198
|
+
|
|
199
|
+
//
|
|
200
|
+
|
|
201
|
+
let _overrideMaterial = null;
|
|
202
|
+
const _quadMesh = /*@__PURE__*/ new QuadMesh();
|
|
203
|
+
|
|
204
|
+
class ShadowNode extends Node {
|
|
205
|
+
|
|
206
|
+
static get type() {
|
|
207
|
+
|
|
208
|
+
return 'ShadowNode';
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
constructor( light, shadow = null ) {
|
|
213
|
+
|
|
214
|
+
super();
|
|
215
|
+
|
|
216
|
+
this.light = light;
|
|
217
|
+
this.shadow = shadow || light.shadow;
|
|
218
|
+
|
|
219
|
+
this.shadowMap = null;
|
|
220
|
+
|
|
221
|
+
this.vsmShadowMapVertical = null;
|
|
222
|
+
this.vsmShadowMapHorizontal = null;
|
|
223
|
+
|
|
224
|
+
this.vsmMaterialVertical = null;
|
|
225
|
+
this.vsmMaterialHorizontal = null;
|
|
226
|
+
|
|
227
|
+
this.updateBeforeType = NodeUpdateType.RENDER;
|
|
228
|
+
this._node = null;
|
|
229
|
+
|
|
230
|
+
this.isShadowNode = true;
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
setupShadow( builder ) {
|
|
235
|
+
|
|
236
|
+
const { object, renderer } = builder;
|
|
237
|
+
|
|
238
|
+
if ( _overrideMaterial === null ) {
|
|
239
|
+
|
|
240
|
+
_overrideMaterial = new NodeMaterial();
|
|
241
|
+
_overrideMaterial.fragmentNode = vec4( 0, 0, 0, 1 );
|
|
242
|
+
_overrideMaterial.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.fragmentNode unintentionally when using material.shadowNode
|
|
243
|
+
_overrideMaterial.name = 'ShadowMaterial';
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const shadow = this.shadow;
|
|
248
|
+
const shadowMapType = renderer.shadowMap.type;
|
|
249
|
+
|
|
250
|
+
const depthTexture = new DepthTexture( shadow.mapSize.width, shadow.mapSize.height );
|
|
251
|
+
depthTexture.compareFunction = LessCompare;
|
|
252
|
+
|
|
253
|
+
const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height );
|
|
254
|
+
shadowMap.depthTexture = depthTexture;
|
|
255
|
+
|
|
256
|
+
shadow.camera.updateProjectionMatrix();
|
|
257
|
+
|
|
258
|
+
// VSM
|
|
259
|
+
|
|
260
|
+
if ( shadowMapType === VSMShadowMap ) {
|
|
261
|
+
|
|
262
|
+
depthTexture.compareFunction = null; // VSM does not use textureSampleCompare()/texture2DCompare()
|
|
263
|
+
|
|
264
|
+
this.vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } );
|
|
265
|
+
this.vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } );
|
|
266
|
+
|
|
267
|
+
const shadowPassVertical = texture( depthTexture );
|
|
268
|
+
const shadowPassHorizontal = texture( this.vsmShadowMapVertical.texture );
|
|
269
|
+
|
|
270
|
+
const samples = reference( 'blurSamples', 'float', shadow ).setGroup( renderGroup );
|
|
271
|
+
const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
|
|
272
|
+
const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
|
|
273
|
+
|
|
274
|
+
let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() );
|
|
275
|
+
material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical } ).context( builder.getSharedContext() );
|
|
276
|
+
material.name = 'VSMVertical';
|
|
277
|
+
|
|
278
|
+
material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() );
|
|
279
|
+
material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal } ).context( builder.getSharedContext() );
|
|
280
|
+
material.name = 'VSMHorizontal';
|
|
281
|
+
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
//
|
|
285
|
+
|
|
286
|
+
const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup );
|
|
287
|
+
const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup );
|
|
288
|
+
const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup );
|
|
289
|
+
|
|
290
|
+
const position = object.material.shadowPositionNode || positionWorld;
|
|
291
|
+
|
|
292
|
+
let shadowCoord = uniform( shadow.matrix ).setGroup( renderGroup ).mul( position.add( transformedNormalWorld.mul( normalBias ) ) );
|
|
293
|
+
|
|
294
|
+
let coordZ;
|
|
295
|
+
|
|
296
|
+
if ( shadow.camera.isOrthographicCamera || renderer.logarithmicDepthBuffer !== true ) {
|
|
297
|
+
|
|
298
|
+
shadowCoord = shadowCoord.xyz.div( shadowCoord.w );
|
|
299
|
+
|
|
300
|
+
coordZ = shadowCoord.z;
|
|
301
|
+
|
|
302
|
+
if ( renderer.coordinateSystem === WebGPUCoordinateSystem ) {
|
|
303
|
+
|
|
304
|
+
coordZ = coordZ.mul( 2 ).sub( 1 ); // WebGPU: Conversion [ 0, 1 ] to [ - 1, 1 ]
|
|
305
|
+
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
} else {
|
|
309
|
+
|
|
310
|
+
const w = shadowCoord.w;
|
|
311
|
+
shadowCoord = shadowCoord.xy.div( w ); // <-- Only divide X/Y coords since we don't need Z
|
|
312
|
+
|
|
313
|
+
// The normally available "cameraNear" and "cameraFar" nodes cannot be used here because they do not get
|
|
314
|
+
// updated to use the shadow camera. So, we have to declare our own "local" ones here.
|
|
315
|
+
// TODO: How do we get the cameraNear/cameraFar nodes to use the shadow camera so we don't have to declare local ones here?
|
|
316
|
+
const cameraNearLocal = uniform( 'float' ).onRenderUpdate( () => shadow.camera.near );
|
|
317
|
+
const cameraFarLocal = uniform( 'float' ).onRenderUpdate( () => shadow.camera.far );
|
|
318
|
+
|
|
319
|
+
coordZ = perspectiveDepthToLogarithmicDepth( w, cameraNearLocal, cameraFarLocal );
|
|
320
|
+
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
shadowCoord = vec3(
|
|
324
|
+
shadowCoord.x,
|
|
325
|
+
shadowCoord.y.oneMinus(), // follow webgpu standards
|
|
326
|
+
coordZ.add( bias )
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
|
|
330
|
+
.and( shadowCoord.x.lessThanEqual( 1 ) )
|
|
331
|
+
.and( shadowCoord.y.greaterThanEqual( 0 ) )
|
|
332
|
+
.and( shadowCoord.y.lessThanEqual( 1 ) )
|
|
333
|
+
.and( shadowCoord.z.lessThanEqual( 1 ) );
|
|
334
|
+
|
|
335
|
+
//
|
|
336
|
+
|
|
337
|
+
const filterFn = shadow.filterNode || _shadowFilterLib[ renderer.shadowMap.type ] || null;
|
|
338
|
+
|
|
339
|
+
if ( filterFn === null ) {
|
|
340
|
+
|
|
341
|
+
throw new Error( 'THREE.WebGPURenderer: Shadow map type not supported yet.' );
|
|
342
|
+
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const shadowColor = texture( shadowMap.texture, shadowCoord );
|
|
346
|
+
const shadowNode = frustumTest.select( filterFn( { depthTexture: ( shadowMapType === VSMShadowMap ) ? this.vsmShadowMapHorizontal.texture : depthTexture, shadowCoord, shadow } ), float( 1 ) );
|
|
347
|
+
|
|
348
|
+
this.shadowMap = shadowMap;
|
|
349
|
+
this.shadow.map = shadowMap;
|
|
350
|
+
|
|
351
|
+
return mix( 1, shadowNode.rgb.mix( shadowColor, 1 ), shadowIntensity.mul( shadowColor.a ) );
|
|
352
|
+
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
setup( builder ) {
|
|
356
|
+
|
|
357
|
+
if ( builder.renderer.shadowMap.enabled === false ) return;
|
|
358
|
+
|
|
359
|
+
return this._node !== null ? this._node : ( this._node = this.setupShadow( builder ) );
|
|
360
|
+
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
updateShadow( frame ) {
|
|
364
|
+
|
|
365
|
+
const { shadowMap, light, shadow } = this;
|
|
366
|
+
const { renderer, scene, camera } = frame;
|
|
367
|
+
|
|
368
|
+
const shadowType = renderer.shadowMap.type;
|
|
369
|
+
|
|
370
|
+
const depthVersion = shadowMap.depthTexture.version;
|
|
371
|
+
this._depthVersionCached = depthVersion;
|
|
372
|
+
|
|
373
|
+
const currentOverrideMaterial = scene.overrideMaterial;
|
|
374
|
+
|
|
375
|
+
scene.overrideMaterial = _overrideMaterial;
|
|
376
|
+
|
|
377
|
+
shadowMap.setSize( shadow.mapSize.width, shadow.mapSize.height );
|
|
378
|
+
|
|
379
|
+
shadow.updateMatrices( light );
|
|
380
|
+
shadow.camera.layers.mask = camera.layers.mask;
|
|
381
|
+
|
|
382
|
+
const currentRenderTarget = renderer.getRenderTarget();
|
|
383
|
+
const currentRenderObjectFunction = renderer.getRenderObjectFunction();
|
|
384
|
+
|
|
385
|
+
renderer.setRenderObjectFunction( ( object, ...params ) => {
|
|
386
|
+
|
|
387
|
+
if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) {
|
|
388
|
+
|
|
389
|
+
renderer.renderObject( object, ...params );
|
|
390
|
+
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
} );
|
|
394
|
+
|
|
395
|
+
renderer.setRenderTarget( shadowMap );
|
|
396
|
+
renderer.render( scene, shadow.camera );
|
|
397
|
+
|
|
398
|
+
renderer.setRenderObjectFunction( currentRenderObjectFunction );
|
|
399
|
+
|
|
400
|
+
// vsm blur pass
|
|
401
|
+
|
|
402
|
+
if ( light.isPointLight !== true && shadowType === VSMShadowMap ) {
|
|
403
|
+
|
|
404
|
+
this.vsmPass( renderer );
|
|
405
|
+
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
renderer.setRenderTarget( currentRenderTarget );
|
|
409
|
+
|
|
410
|
+
scene.overrideMaterial = currentOverrideMaterial;
|
|
411
|
+
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
vsmPass( renderer ) {
|
|
415
|
+
|
|
416
|
+
const { shadow } = this;
|
|
417
|
+
|
|
418
|
+
this.vsmShadowMapVertical.setSize( shadow.mapSize.width, shadow.mapSize.height );
|
|
419
|
+
this.vsmShadowMapHorizontal.setSize( shadow.mapSize.width, shadow.mapSize.height );
|
|
420
|
+
|
|
421
|
+
renderer.setRenderTarget( this.vsmShadowMapVertical );
|
|
422
|
+
_quadMesh.material = this.vsmMaterialVertical;
|
|
423
|
+
_quadMesh.render( renderer );
|
|
424
|
+
|
|
425
|
+
renderer.setRenderTarget( this.vsmShadowMapHorizontal );
|
|
426
|
+
_quadMesh.material = this.vsmMaterialHorizontal;
|
|
427
|
+
_quadMesh.render( renderer );
|
|
428
|
+
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
dispose() {
|
|
432
|
+
|
|
433
|
+
this.shadowMap.dispose();
|
|
434
|
+
this.shadowMap = null;
|
|
435
|
+
|
|
436
|
+
if ( this.vsmShadowMapVertical !== null ) {
|
|
437
|
+
|
|
438
|
+
this.vsmShadowMapVertical.dispose();
|
|
439
|
+
this.vsmShadowMapVertical = null;
|
|
440
|
+
|
|
441
|
+
this.vsmMaterialVertical.dispose();
|
|
442
|
+
this.vsmMaterialVertical = null;
|
|
443
|
+
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if ( this.vsmShadowMapHorizontal !== null ) {
|
|
447
|
+
|
|
448
|
+
this.vsmShadowMapHorizontal.dispose();
|
|
449
|
+
this.vsmShadowMapHorizontal = null;
|
|
450
|
+
|
|
451
|
+
this.vsmMaterialHorizontal.dispose();
|
|
452
|
+
this.vsmMaterialHorizontal = null;
|
|
453
|
+
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
this.updateBeforeType = NodeUpdateType.NONE;
|
|
457
|
+
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
updateBefore( frame ) {
|
|
461
|
+
|
|
462
|
+
const { shadow } = this;
|
|
463
|
+
|
|
464
|
+
const needsUpdate = shadow.needsUpdate || shadow.autoUpdate;
|
|
465
|
+
|
|
466
|
+
if ( needsUpdate ) {
|
|
467
|
+
|
|
468
|
+
this.updateShadow( frame );
|
|
469
|
+
|
|
470
|
+
if ( this.shadowMap.depthTexture.version === this._depthVersionCached ) {
|
|
471
|
+
|
|
472
|
+
shadow.needsUpdate = false;
|
|
473
|
+
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export default ShadowNode;
|
|
483
|
+
|
|
484
|
+
export const shadow = ( light, shadow ) => nodeObject( new ShadowNode( light, shadow ) );
|
|
@@ -102,10 +102,10 @@ class LoopNode extends Node {
|
|
|
102
102
|
condition = param.condition;
|
|
103
103
|
update = param.update;
|
|
104
104
|
|
|
105
|
-
if ( typeof start === 'number' ) start =
|
|
105
|
+
if ( typeof start === 'number' ) start = builder.generateConst( type, start );
|
|
106
106
|
else if ( start && start.isNode ) start = start.build( builder, type );
|
|
107
107
|
|
|
108
|
-
if ( typeof end === 'number' ) end =
|
|
108
|
+
if ( typeof end === 'number' ) end = builder.generateConst( type, end );
|
|
109
109
|
else if ( end && end.isNode ) end = end.build( builder, type );
|
|
110
110
|
|
|
111
111
|
if ( start !== undefined && end === undefined ) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { time } from './Timer.js';
|
|
2
|
+
|
|
3
|
+
export const oscSine = ( t = time ) => t.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 );
|
|
4
|
+
export const oscSquare = ( t = time ) => t.fract().round();
|
|
5
|
+
export const oscTriangle = ( t = time ) => t.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs();
|
|
6
|
+
export const oscSawtooth = ( t = time ) => t.fract();
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { abs, cross, float, Fn, normalize, ivec2, sub, vec2, vec3, vec4 } from '../tsl/TSLBase.js';
|
|
2
|
+
import { textureSize } from '../accessors/TextureSizeNode.js';
|
|
3
|
+
import { textureLoad } from '../accessors/TextureNode.js';
|
|
4
|
+
import { WebGPUCoordinateSystem } from '../../constants.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Computes a position in view space based on a fragment's screen position expressed as uv coordinates, the fragments
|
|
8
|
+
* depth value and the camera's inverse projection matrix.
|
|
9
|
+
*
|
|
10
|
+
* @param {vec2} screenPosition - The fragment's screen position expressed as uv coordinates.
|
|
11
|
+
* @param {float} depth - The fragment's depth value.
|
|
12
|
+
* @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix.
|
|
13
|
+
* @return {vec3} The fragments position in view space.
|
|
14
|
+
*/
|
|
15
|
+
export const getViewPosition = /*@__PURE__*/ Fn( ( [ screenPosition, depth, projectionMatrixInverse ], builder ) => {
|
|
16
|
+
|
|
17
|
+
let clipSpacePosition;
|
|
18
|
+
|
|
19
|
+
if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem ) {
|
|
20
|
+
|
|
21
|
+
screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 );
|
|
22
|
+
clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 );
|
|
23
|
+
|
|
24
|
+
} else {
|
|
25
|
+
|
|
26
|
+
clipSpacePosition = vec4( vec3( screenPosition.x, screenPosition.y.oneMinus(), depth ).mul( 2.0 ).sub( 1.0 ), 1.0 );
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const viewSpacePosition = vec4( projectionMatrixInverse.mul( clipSpacePosition ) );
|
|
31
|
+
|
|
32
|
+
return viewSpacePosition.xyz.div( viewSpacePosition.w );
|
|
33
|
+
|
|
34
|
+
} );
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Computes a screen position expressed as uv coordinates based on a fragment's position in view space
|
|
38
|
+
* and the camera's projection matrix
|
|
39
|
+
*
|
|
40
|
+
* @param {vec3} viewPosition - The fragments position in view space.
|
|
41
|
+
* @param {mat4} projectionMatrix - The camera's projection matrix.
|
|
42
|
+
* @return {vec2} The fragment's screen position expressed as uv coordinates.
|
|
43
|
+
*/
|
|
44
|
+
export const getScreenPosition = /*@__PURE__*/ Fn( ( [ viewPosition, projectionMatrix ] ) => {
|
|
45
|
+
|
|
46
|
+
const sampleClipPos = projectionMatrix.mul( vec4( viewPosition, 1.0 ) );
|
|
47
|
+
const sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar();
|
|
48
|
+
return vec2( sampleUv.x, sampleUv.y.oneMinus() );
|
|
49
|
+
|
|
50
|
+
} );
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Computes a normal vector based on depth data. Can be used as a fallback when no normal render
|
|
54
|
+
* target is available or if flat surface normals are required.
|
|
55
|
+
*
|
|
56
|
+
* @param {vec2} uv - The texture coordinate.
|
|
57
|
+
* @param {DepthTexture} depthTexture - The depth texture.
|
|
58
|
+
* @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix.
|
|
59
|
+
* @return {vec3} The computed normal vector.
|
|
60
|
+
*/
|
|
61
|
+
export const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMatrixInverse ] ) => {
|
|
62
|
+
|
|
63
|
+
const size = textureSize( textureLoad( depthTexture ) );
|
|
64
|
+
const p = ivec2( uv.mul( size ) ).toVar();
|
|
65
|
+
|
|
66
|
+
const c0 = textureLoad( depthTexture, p ).toVar();
|
|
67
|
+
|
|
68
|
+
const l2 = textureLoad( depthTexture, p.sub( ivec2( 2, 0 ) ) ).toVar();
|
|
69
|
+
const l1 = textureLoad( depthTexture, p.sub( ivec2( 1, 0 ) ) ).toVar();
|
|
70
|
+
const r1 = textureLoad( depthTexture, p.add( ivec2( 1, 0 ) ) ).toVar();
|
|
71
|
+
const r2 = textureLoad( depthTexture, p.add( ivec2( 2, 0 ) ) ).toVar();
|
|
72
|
+
const b2 = textureLoad( depthTexture, p.add( ivec2( 0, 2 ) ) ).toVar();
|
|
73
|
+
const b1 = textureLoad( depthTexture, p.add( ivec2( 0, 1 ) ) ).toVar();
|
|
74
|
+
const t1 = textureLoad( depthTexture, p.sub( ivec2( 0, 1 ) ) ).toVar();
|
|
75
|
+
const t2 = textureLoad( depthTexture, p.sub( ivec2( 0, 2 ) ) ).toVar();
|
|
76
|
+
|
|
77
|
+
const dl = abs( sub( float( 2 ).mul( l1 ).sub( l2 ), c0 ) ).toVar();
|
|
78
|
+
const dr = abs( sub( float( 2 ).mul( r1 ).sub( r2 ), c0 ) ).toVar();
|
|
79
|
+
const db = abs( sub( float( 2 ).mul( b1 ).sub( b2 ), c0 ) ).toVar();
|
|
80
|
+
const dt = abs( sub( float( 2 ).mul( t1 ).sub( t2 ), c0 ) ).toVar();
|
|
81
|
+
|
|
82
|
+
const ce = getViewPosition( uv, c0, projectionMatrixInverse ).toVar();
|
|
83
|
+
|
|
84
|
+
const dpdx = dl.lessThan( dr ).select( ce.sub( getViewPosition( uv.sub( vec2( float( 1 ).div( size.x ), 0 ) ), l1, projectionMatrixInverse ) ), ce.negate().add( getViewPosition( uv.add( vec2( float( 1 ).div( size.x ), 0 ) ), r1, projectionMatrixInverse ) ) );
|
|
85
|
+
const dpdy = db.lessThan( dt ).select( ce.sub( getViewPosition( uv.add( vec2( 0, float( 1 ).div( size.y ) ) ), b1, projectionMatrixInverse ) ), ce.negate().add( getViewPosition( uv.sub( vec2( 0, float( 1 ).div( size.y ) ) ), t1, projectionMatrixInverse ) ) );
|
|
86
|
+
|
|
87
|
+
return normalize( cross( dpdx, dpdy ) );
|
|
88
|
+
|
|
89
|
+
} );
|